Ти надіслав мені ноутбук у неділю ввечері, і відтоді він відкритий на другому моніторі. Крос-секційний імпульс, 150 безстрокових контрактів Binance USDⓈ-M із найбільшим обсягом у доларах за 30 днів, щотижневе перебалансування, довга позиція в найкращому децилі, коротка — у найгіршому, період із 2021-01 до 2026-06. Sharpe 2.31, максимальне просідання 14.2%, і модель витрат, яка здавалася мені чесною: taker на вході й виході, нарахування funding за кожен інтервал, прослизання, що зростає разом із розміром твоєї позиції відносно книги заявок. Складну роботу ти зробив правильно. А потім запитав, чому шість тижнів паперової торгівлі дали нульовий результат і чи не зникла перевага.
Вона не зникла. Її взагалі не було в бектесті. Подивись на комірку 4:
info = requests.get(BASE + "/fapi/v1/exchangeInfo").json()
symbols = [s["symbol"] for s in info["symbols"]
if s["status"] == "TRADING" and s["quoteAsset"] == "USDT"]
Ти викликав цей ендпоінт у червні 2026 року й використав відповідь, щоб визначити, чим можна було торгувати в березні 2021-го. Кожен інструмент у тому списку дожив до червня 2026-го — так його й було сформовано. Ось у чому вся проблема, і вона важить більше, ніж решта твоєї моделі витрат разом узята.
Чого не покаже ендпоінт
В exchangeInfo немає історії. Немає параметра asOf, архіву чи журналу змін. Це знімок поточного стану, і Binance ніколи не обіцяла нічого іншого. Коли контракт делістять, його запис зникає з відповіді, а для API перестає існувати й сам тикер. Із 2019 року Binance додала понад 600 безстрокових контрактів USDⓈ-M і вивела з обігу значно більше сотні. BTS, COCOS, TOMO, RAY, FTT, SC — довгий хвіст контрактів альтсезону 2021 року, кожен із яких пережив один блискучий квартал, а потім торгівля ним поступово згасла, аж поки біржа його не прибрала.
Подумай, які назви любить 30-денний імпульсний фільтр. Не BTC. Йому подобається те, що щойно потроїлося на пампі після лістингу й ажіотажі у Twitter. Ця група інструментів значною мірою перетинається з тими, що зрештою делістять, а твій фільтр всесвіту прибрав саме цей перетин.
Я перерахував твою стратегію на нашому архіві знімків, із всесвітом на певний момент часу, тим самим сигналом і тими самими витратами. Sharpe вийшов 0.74, просідання — 31%. Приблизно дві п’ятих розриву припадає на делістовані інструменти, якими тобі взагалі не можна було торгувати. Ще чверть — на дзеркальну проблему, тоншу, і, підозрюю, вона тобі сподобається менше.
Інший край машини часу: інструменти, яких ще не існувало
Твоя ознака — дохідність за 90 днів. У рухомому вікні задано min_periods=20, бо ти встановив його раз і назавжди, щоб розігрів не знищив перший квартал вибірки, і більше до цього не повертався. Тож контракт, доданий 21 день тому, отримує імпульсний бал за даними трьох тижнів після лістингу, потрапляє до найкращого дециля приблизно щоразу, коли лістинг проходив вдало, і входить у твій портфель.
Цю частину ще можна вважати прийнятною. Ось що неприйнятно: провайдер заднім числом додав до деяких із цих інструментів спотові або індексні дані за період до появи безстрокового контракту, тож історія kline кількох контрактів починається раніше за їхню власну onboardDate. Це можна перевірити приблизно за хвилину. Зістав таблицю цін із датами лістингу й порахуй рядки, що передують лістингу. У твоїх даних є 41 інструмент із барами до лістингу, а один із них улітку 2023 року додав до кривої капіталу 6% за один тиждень завдяки позиції в контракті, який з’явиться лише через дев’ять днів.
Рядок тикера — це не ідентифікатор. Це назва, яку біржа здає в оренду, іноді двічі.
Це підводить до перейменувань. MATICUSDT став POLUSDT. FTMUSDT став SUSDT після конвертації 1:1. Після історії з LUNA у травні 2022 року залишився LUNCUSDT, а згодом з’явився новий LUNAUSDT із тим самим коренем тикера, що й у монети, яка втратила майже всю вартість. Якщо завантажувач використовує рядок символу як ключ і склеює всі знайдені файли, у тебе щонайменше один часовий ряд із розривом, який не є рухом ціни. А ознака імпульсу сприйме цей розрив як найсильніший сигнал у всьому перерізі.
Усе інше, що змінюється з часом
Щойно визнаєш, що список інструментів змінюється з часом, той самий аргумент поширюється на кожне інше поле у відповіді. А ти для всіх них використовуєш сьогоднішні значення.
| Поле | Як змінюється | Що ламається |
|---|---|---|
| status | TRADING → SETTLING → зникнення | Упередження виживання; фіктивні виходи за ціною закриття, якої ніколи не було на ринку |
| onboardDate | Щотижня з’являються нові лістинги; для зниклих інструментів значення відсутнє | Торгівля контрактами до їхньої появи |
| tickSize / stepSize | Переналаштовуються зі зміною рівня ціни | Округлення ордерів і лімітні ціни, які біржа відхилила б |
| minNotional | З часом підвищується для малоліквідних книг заявок | Малі позиції, які твій торговий маршрутизатор відхилив би |
| fundingIntervalHours | Роками було 8h, потім для багатьох інструментів стало 4h або 1h | Витрати на фінансування занижені в 2–3× саме для альткоїнів, які тримає твій фільтр |
| leverage brackets | Рівні та підтримувальна маржа змінювалися | Моделювання ліквідації та доступний обсяг маржі |
У твоєму випадку найбільше шкодить funding. У циклі нарахування ти припускаєш три виплати на день за всю історію. Чимала частина альткоїнового портфеля перейшла на funding кожні чотири години, а на коротких позиціях у контрактах із високим funding формується значна частина твого симульованого PnL. Тут помилка не в округленні. Вона в рази.
Делістинг — це подія, а ти її не моделюєш
У повторному прогоні з даними на певний момент часу я дав стратегії щедрі умови виходу. Насправді делістинг відбувається за сценарієм: оголошення, зазвичай за сім-чотирнадцять днів, потім період лише для скорочення позицій, а тоді примусове закриття за mark price. Оголошення — публічна інформація, на яку можна відреагувати, тож чесна симуляція передбачає вихід за ціною закриття дня оголошення. Але на типовому делістингу альткоїна ця ціна вже на 10-20% нижча за ціну попереднього тижня, книга заявок малоліквідна, і модель прослизання має враховувати, що працює в іншому режимі. Якщо твій рушій виконання видає ціну розрахунку без впливу на ринок, ти непомітно зробив активи, що зникають, доступними для торгівлі за справедливою вартістю.
Якщо ти ніколи не архівував exchangeInfo, це ще не кінець. У відкритому дампі на data.binance.vision/data/futures/um/monthly/klines/ каталоги делістованих інструментів зберігаються ще довго після того, як API про них забуває. Переглянь список каталогів: перший і останній місячний файл для кожного інструмента дадуть приблизний інтервал між лістингом і делістингом без жодного постачальника даних. Це реконструкція, а не архівний запис, і розміри тіку чи інтервали funding вона не відновить. Але вона покаже, які інструменти коли існували, а це 80% того, що потрібно тобі в понеділок.
Що я раджу побудувати, перш ніж знову чіпати сигнал
- Cron-завдання, яке щодня отримує exchangeInfo з кожної біржі, яку ти досліджуєш, і записує його в об’єктне сховище з датою в ключі. У gzip це менше ніж пів мегабайта. Десять років обійдуться в похибку округлення рахунку S3 і дадуть тобі дослідницьку можливість, яку згодом уже не купиш.
- Довідник активів на основі цих знімків: один рядок на кожну пару (біржа, символ, valid_from, valid_to) з повним набором полів. Порівнюй послідовні знімки, щоб його сформувати, і записуй кожну зміну поля як новий рядок.
- Функція побудови всесвіту з обов’язковим аргументом часової мітки.
universe(ts), ніколи неuniverse(). Налаштуй її так, щоб ніхто, навіть ти сам у майбутньому о 1am, не міг випадково звернутися до списку тих, хто вижив. - Перевірка в завантажувачі даних: барів до
onboard_tsмінус один день бути не може. Зупиняй прогін, не просто виводь попередження. - Стабільний внутрішній ID інструмента, який не змінюється після перейменувань; тикер зберігай лише як атрибут. Зістав POL і MATIC з одним ID, а деномінації позначай окремо, щоб логіка безперервності не з’єднувала їх.
Зроби це й перерахуй стратегію. Гадаю, результат буде близький до мого 0.74, і тоді головне питання — чи є щось вартісне для паперової торгівлі в результаті 0.74, до якого включено зниклі інструменти. Можливо, є. Крос-секційний імпульс на безстрокових контрактах — це не нуль, а частина того, що залишиться після виправлення всесвіту, — справжня дохідність від утримання коротких позицій. Ти також побачиш, що результати паперової торгівлі та бектест починають збігатися, адже паперова торгівля завжди працювала з усесвітом на певний момент часу. Вона не могла працювати інакше.
P.S. Це не особливість крипти, просто тут вона помітніша. Фахівці з дослідження акцій борються з дохідністю делістованих паперів і повторним використанням тикерів відтоді, як CRSP почала їх постачати. На ринках прогнозів це доходить до крайнощів: кожен контракт за задумом має термін дії, тож усесвіт складається лише з лістингів і зникнень. Якщо переноситимеш цей фільтр на Kalshi, спочатку створи довідник активів. Іншої історії там немає.
← Усі статті


