2 вересня 2026 · мікроструктура

Ваш лімітний ордер не виконався: лист про позицію в черзі, maker-бектести та Sharpe, який ви вигадали

Ваш лімітний ордер не виконався: лист про позицію в черзі, maker-бектести та Sharpe, який ви вигадали

Минулого тижня ви надіслали мені ноутбук: той самий сигнал, той самий набір інструментів, ті самі 14 місяців даних BTCUSDT perp. Змінилося лише виконання. Ви перестали перетинати спред і почали виставляти заявки на купівлю на один тік усередині спреду — Sharpe зріс з 0.42 до 2.14. Ви запитали, чи це справжній результат, чи ви щось зламали.

Ви щось зламали. Хочу докладно показати, де саме, бо помилка в одному рядку, а урок за ним набагато ширший.

Ось ваше правило виконання, скопійоване з рушія:

if bar.low <= limit_price: fill(limit_price)

Це означає: якщо протягом цієї хвилини на ринку пройшла угода за моєю ціною або нижче, мою заявку виконано за моєю ціною. Насправді ж це правило фіксує, що ціна торкнулася вашого рівня. Дотик — це ще не виконання. Між цими двома подіями стоїть черга, а ви змоделювали її так, ніби вона порожня.

Хто стоїть перед вами

Коли ви виставляєте заявку на купівлю BTCUSDT perp за 84,120.0, ви стаєте в кінець черги тих, хто вже чекає на цьому рівні. На найкращому рівні книги заявок цього контракту там зазвичай стоїть від 4 до 30 BTC — залежно від часу доби; медіана у вашому вибірковому вікні становить близько 12 BTC. Ваша заявка — 0.4 BTC. Щоб відбулася угода, продавці мають продати на цьому рівні достатній сукупний обсяг, аби пройти всіх, хто став у чергу перед вами, і зробити це до того, як рівень скасують з-під вас або ринок піде вгору.

Тож у бектесті слід запитувати не «чи сягнула ціна 84,120.0», а «чи виконали ринкові продавці угоди обсягом щонайменше 12.4 BTC за ціною 84,120.0, поки моя заявка стояла в книзі». Це зовсім різні події. У ваших даних їхня частота відрізняється приблизно втричі.

12.4 BTCмедіанний обсяг попереду вас у черзі при дотику до рівня
100%частка виконання, яку припускає ваш бектест
31%дотиків, за яких обсяг пройшов усю чергу перед вами
4,180угод, з яких стало приблизно 1,300

Три правила виконання — три різні стратегії

Я повторно прогнав ваш сигнал з тими самими входами й трьома моделями виконання. Та сама альфа, ті самі комісії, те саме фінансування. Змінилася лише логіка виконання.

Правило виконанняВиконанняСереднє відхилення ціни через 60s після виконанняSharpe
Дотик: low <= limit4,180+2.6 bp2.14
Строге проходження ціни: low < limit - 1 tick1,712+0.4 bp0.61
Симуляція черги за обсягом на рівні1,306+0.9 bp0.77

Середній рядок — це грубе виправлення, до якого зазвичай вдаються першим: зараховувати виконання лише тоді, коли ринок торгував нижче вашої ціни, виходячи з того, що якщо ціна пішла далі, то мала виконати вашу заявку. Загалом напрям правильний, і так зникає більша частина фантазійних результатів. Але це також створює серйозне викривлення — зараз поясню.

Нижній рядок — модель, яку варто побудувати. Для неї не потрібен потік L3 чи відновлення кожного ордера. У вас уже є більшість потрібного.

Симуляція черги на основі aggTrades

Завантажте потік агрегованих угод замість свічок klines. Кожен запис містить ціну, обсяг, часову мітку та прапорець сторони maker, який показує, хто був ініціатором угоди — покупець чи продавець. Цього достатньо для придатної до роботи симуляції вашого пасивного ордера:

  1. Коли вашу заявку розміщено, зафіксуйте обсяг заявок, що вже стоять за вашою ціною. Якщо у вас є лише книга заявок з оновленням кожні 100ms, візьміть останній знімок; ця похибка мала порівняно з тією, яку ви виправляєте.
  2. Задайте queue_ahead = resting_size. Будьте песимістичні й припускайте, що ви останні в черзі. Так і є, якщо тільки ви самі не створили цей рівень.
  3. Переберіть потік угод. Кожен запис про продаж з ініціативи продавця за вашою ціною або нижче зменшує queue_ahead на свій обсяг. Коли значення стає від’ємним, вашу заявку виконано за вашою ціною в цей момент часу.
  4. Якщо ціна відходить на один тік, не обнуляйте чергу. Зменшуйте її поступово. Частина заявок перед вами скасовується, коли рівень втрачає актуальність, частина залишається. Зменшення на 30-40% за кожну повну секунду поза найкращою ціною краще узгодилося з моїми реконструкціями, ніж обидві крайності.
  5. Якщо стратегія скасовує заявку й виставляє її знову, моделюйте повторне розміщення як новий ордер у кінці черги на новому рівні. Цей крок часто пропускають — саме там і ховається решта фантазійних результатів.

Саме щодо кроку 2 вам захочеться зі мною посперечатися. Так, іноді ви опиняєтеся на початку черги, бо виставили заявку щойно сформувався рівень. Гаразд — вимірюйте це, а не припускайте. Записуйте обсяг заявок у книзі на момент виставлення й дайте даним показати, яка частка ваших ордерів справді стояла на початку черги. У вашій стратегії це було 11%, бо сигнал спрацьовує після руху, а отже, рівень, до якого ви приєднуєтеся, вже існує і на ньому вже є натовп.

Ви отримуєте саме ті виконання, яких воліли б не мати

Тепер про найважливіше — і про те, чому правило строгого проходження ціни дає викривлений результат.

Подумайте, коли вашу заявку на купівлю виконують повністю. Це стається, коли тиск продавців достатній, щоб поглинути весь обсяг рівня. Тобто за визначенням саме тоді, коли ринок проходить униз крізь вашу ціну. Виконання, у яких ви впевнені найбільше, — це ті, після яких ви одразу опиняєтеся в збитковій позиції.

Розділіть виконання за тим, як вони відбулися, і виміряйте зміну ціни через 60 секунд:

Тип виконанняЧастка виконаньЗміна ціни через 60s
Угоди пройшли на рівні, ціна відскочила вгору38%+3.1 bp
Угоди пройшли на рівні, ціна не змінилася21%+0.2 bp
Ціна пройшла нижче на 2+ тіки41%−2.4 bp

Ваш наївний бектест зарахував усі три групи й вважав виконання безкоштовним. Правило строгого проходження ціни дає майже виключно третю групу — тому його перевага скоротилася сильніше, ніж у симуляції черги. Обидва підходи хибні. Симуляція черги дає реалістичне співвідношення груп, а саме воно визначає все: пасивне виконання приносить вам спред, але ви платите за це несприятливим відбором, і справжня стратегія — це співвідношення між ними.

Старий підхід трейдерів на фондовому ринку й досі актуальний: ордер maker — це опціон, який ви безкоштовно виписали ринку. Його виконує той, кому це вигідно. Ваш бектест отримував премію й забував, що в опціону є ще й сторона виплати.

Угоди, яких ви не отримали, змінюють стратегію, а не лише витрати

Це саме та думка, над якою я хочу, щоб ви затрималися найдовше. Якщо неправильно змоделювати виконання taker, ви отримаєте потрібні угоди за неправильною ціною, і здебільшого це виправить корекція комісій. Якщо ж неправильно змоделювати виконання maker, ви отримаєте зовсім не той набір угод. Приблизно 2,900 з ваших 4,180 входів насправді не відбулися б. Деякі з них були вашими найкращими сигналами — на свічках із різким стрибком і розворотом, тобто саме в ситуаціях, коли ринок пішов без вас.

Тож логіка для гілки невиконаних заявок має бути реальною. Що робить стратегія, якщо заявка не виконалася до того, як сигнал застарів? Наздоганяє ринок ордером taker і платить спред та вплив на ціну? Виставляє нову заявку нижче й погоджується на іншу ціну входу? Пропускає угоду й залишається поза ринком? Кожен варіант дає суттєво іншу криву капіталу, і жоден не означає «вважай, що заявку виконано». У наших запусках чесне правило наздоганяння — перетинати спред після 20 секунд без виконання, обмеживши прослизання 3 bp — повернуло близько третини втрачених угод і приблизно половину різниці між наївним Sharpe та Sharpe симуляції черги. Результат справді цікавий, і побачити його можна лише тоді, коли модель виконання достатньо реалістична, щоб це запитання мало сенс.

Швидка перевірка здорового глузду, на 10 хвилин: візьміть журнал вашої торгівлі на паперовому рахунку й бектест за той самий період. Порівняйте частку виконаних заявок, а не PnL. Якщо бектест виконує 100% пасивних заявок, а паперова торгівля — 34%, ви порівнюєте не стратегії, а помилкову модель виконання. Виправте її, перш ніж дивитися на будь-які показники дохідності.

Ще дві невеликі речі

Відхилення post-only. Якщо ви використовуєте post-only, щоб гарантовано отримати тариф maker, а книга заявок змінюється між вашим рішенням і підтвердженням біржі, ордер буде відхилено, а не залишиться в книзі. За нашими журналами паперової торгівлі, у звичайні години це трапляється у 3-6% спроб з BTCUSDT, а протягом хвилини після публікації індексу споживчих цін США — більш ніж у 15%. Відхилений ордер — це ні виконаний ордер, ні невиконана заявка в книзі: це угода, якої взагалі не було. Якщо у вашому бектесті немає такого стану, кількість угод завищена саме в режимах, які для вас найважливіші.

Запобігання угодам із самим собою та ваш власний вплив. З обсягом 0.4 BTC ви не рухаєте BTCUSDT, тож можете цим знехтувати. Але ви згадували, що хочете запустити стратегію на альткоїні з середньою капіталізацією, де номінальний обсяг найкращої ціни в книзі часто не перевищує $15k. Там ваша заявка є суттєвою частиною черги, а знімок обсягу попереду вас уже враховує присутність вашої попередньої заявки. Коли ваш обсяг перевищує приблизно 10% обсягу заявок на рівні, симуляція має враховувати, що інші учасники реагують на вас. І, відверто кажучи, на цьому етапі я більше довіряв би паперовій торгівлі, ніж будь-якій симуляції, яку можемо написати ви чи я.

Повторно прогоніть стратегію із симуляцією черги й надішліть мені таблицю зміни ціни з розбивкою за типом виконання. Якщо більша частина переваги й далі припадає на групу з відскоком, а група проходження ціни не з’їдає її повністю, можливо, тут є щось, що варто перевірити на паперовому рахунку. Якщо ж усе трималося на 2,900 виконаннях, яких ви ніколи б не отримали, краще дізнатися про це зараз, а не після чотирьох тижнів спостережень за паперовим рахунком, який не робить того, що обіцяв ноутбук.

лімітні ордерипозиція в черзінесприятливий відбірбектестингкриптовалютні ф’ючерси
ПоділитисяXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← Усі статті