← Макалаларга кайтуу
July 16, 2026
5 мүн окуу

Филл симуляциясы: клоуз-баадагы фантазиядан кезек-эске алган чындыкка чейинки тепкич

Филл симуляциясы: клоуз-баадагы фантазиядан кезек-эске алган чындыкка чейинки тепкич
#филл симуляциясы
#бэктест
#лимиттик ордерлер
#кезектеги позиция
#бөлүк-филлдер
#маркет-мейкинг
#аткаруу
#маркет микроструктурасы

Сиздин бэктестиңизде эки модель бар: альфаңыздын модели жана филлдериңиздин модели. Көпчүлүк адамдар күч-аракетинин 95% биринчисине жумшап, экинчисин колдонуп жаткан кайсы фреймворк болсо, ошондон мурас кылып алышат. Бул тескери. Ак ниет филл модели менен орто деңгээлдеги сигнал орто деңгээлдеги, бирок чыныгы PnL баасын берет. Ал эми fill_price = candle.close менен эң мыкты сигнал эч нерсенин баасы болбогон санды берет — бул сиз эч качан текшербеген божомолдун чыгарылышы.

Ликвиддүү инструменттердеги такер стратегиялары үчүн филл модели — оңдоо мүчөсү. Ал эми ордердо турган лимиттик ордерлерге тиешелүү нерселердин баарында — маркет-мейкинг, пассивдүү кириштер, post-only рибейт жыйноо — филл модели дал өзү стратегия болуп саналат. Сиздин филлиңиз болобу же жокпу, качан, кандай көлөмдө жана кийинки кайсы баа кыймылына шартталып болот — бул PnLдин чоңдугун гана эмес, анын белгисин аныктайт.

Backtest-live parity макаласында биз бэктест менен лайвдын ажырымдарынын толук таксономиясын түзүп, аткаруу ажырымын 5/5 оордуктагы деп бааладык — эң жаман класс. Ал макалада филл симуляциясына үч орой тактык деңгээли берилип, андан ары өткөн болчу. Бул макала анын тереңдик коштоочусу: толук тепкич, баскычтан баскычка, ордердин жашоо циклин штат машинасы катары карап, чындыгында эсептесе боло турган филл-ыктымалдык чектери менен жана "кирешелүү" мейкер стратегиясынын тепкичтин так кайсы жеринде өлөрүн көрсөткөн өлчөнгөн эксперимент менен.

Тепкич

Филл симуляциясынын тактыгынын беш баскычтуу тепкичи

Ар бир баскыч көбүрөөк маалыматты жана көбүрөөк кодду талап кылат, ошондой эле ар бир баскыч белгилүү бир системалуу жамгырды жоет. Баскычтар алардын баасы боюнча гана эмес, алар эмнени туура эмес чечкени боюнча иреттелген.

0-баскыч: клоуз-баадагы филл

fill_price = bar.close

Ордер сигналды жараткан бардын клоузунда бир заматта, толук аткарылат. Сигнал ошол эле клоуздон эсептелген, ошондуктан баа басып чыкканда болбогон маалымат менен соода кылып жатасыз: аткаруу костюмун кийген look-ahead жамгыры. Обороту бар кайсы стратегия болбосун бул жерде жакшы көрүнөт.

1-баскыч: кийинки бардын опени

fill_price = next_bar.open

Барлардагы такер логикасы үчүн минималдуу ак ниет модель. Сигнал tt барында эсептелет, филл t+1t+1 бардын биринчи байкала турган баасында болот. Бул look-aheadди жоет, бирок дагы эле нөл спред, нөл таасир, опен басмасында чексиз ликвиддүүлүк жана 100% филл ишенимдүүлүгүн болжолдойт. Лимиттик ордерлер үчүн бул тач-филл логикасына айланат (эмне үчүн бул уу экенин төмөндө көбүрөөк).

2-баскыч: спред + туруктуу проскальзывание

half_spread = mid * spread_bps / 2e4
slip        = mid * slippage_bps / 1e4
fill_price  = mid + side * (half_spread + slip)   # side: +1 buy, -1 sell

Эми ар бир такер соодасы спреддин жарымын кошуу менен калибрленген туруктууну төлөйт. Бул жогорку оборотуу стратегия бэктестте өлө ала турган биринчи баскыч — бул анын максаты. Калдык ката: проскальзывание туруктуу эмес. Ал көрсөтүлгөн тереңдикке салыштырмалуу ордердин көлөмүнө жараша масштабдалат жана сиздин стратегияңыз соода кылганды эң каалаган учурда так жарылат. Туруктуу 5 bps — режимдер боюнча орточо; сиздин стратегияңыз орточо режимде соода кылбайт.

3-баскыч: маркет ордерлер үчүн L2 тереңдик боюнча басуу

Стакандын снапшоттору менен сиз проскальзыванияны болжолдоону токтотуп, аны эсептейсиз. QQ көлөмдөгү маркет-бай аск тарабын деңгээлден деңгээлге басып өтөт; филл баасы керектелген деңгээлдер боюнча көлөм менен өлчөнгөн орточо:

Pfill(Q)=1Qipimin ⁣(qi,  Qj<iqj)P_{\text{fill}}(Q) = \frac{1}{Q}\sum_{i} p_i \cdot \min\!\left(q_i,\; Q - \textstyle\sum_{j<i} q_j\right)

def depth_walk(levels: list[tuple[float, float]], qty: float) -> tuple[float, float]:
    """levels: [(price, size), ...] sorted best-first. Returns (vwap, filled_qty)."""
    remaining, cost = qty, 0.0
    for price, size in levels:
        take = min(size, remaining)
        cost += take * price
        remaining -= take
        if remaining <= 0:
            break
    filled = qty - remaining
    return (cost / filled if filled > 0 else float("nan"), filled)

Эки оңдоо муну кыйла ак ниетирээк кылат. Биринчиден, латенттик: стакандын сиздин чечим убакытыңыздан Δt\Delta t кийин турган абалын басып өтүңүз, мында Δt\Delta t — сиз өлчөгөн сигналдан биржага чейинки латенттик — сиз көргөн стакан сиз соккон стакан эмес. Экинчиден, бөлүк-маркетабл филлдер: эгер сиздин лимит-аркылуу бааңыздын ичиндеги көрсөтүлгөн тереңдик QQ көлөмүнөн азыраак болсо, модель бөлүк-филл кайтарып, калдыгын ордерде калтырышы керек, ал өз кезегинде маселени төмөндөгү штат машинасына тапшырат.

3-баскычтагы калдык ката — таасир жана толуктоо: сиз стаканды статикалык объект катары керектейсиз, бирок чыныгы стакандар жарым-жартылай толукталат (жана чыныгы контрагенттер реакция кылат). Топ-оф-буктун тереңдигинин бир нече пайызынан аз клип көлөмдөрү үчүн бул ката аз; чоңураак клиптер үчүн үстүнө кабатталган таасир модели керек (Almgren-Chriss 2001).

4-баскыч: лимиттик ордерлер үчүн кезектеги позицияны эске алган ыктымалдык филлдер

0-3-баскычтар "менин агрессивдүү ордерим кайсы баада филлденет" деген суроого жооп берет. 4-баскыч татаалыраак суроого жооп берет: менин пассивдүү ордерим таптакыр филлденеби — жана бул мейкер стратегиясын баалай ала турган жалгыз баскыч. pp баасында турган лимиттик ордер pp баасында кумулятивдик соода көлөмү анын алдында турган кезек көлөмүнөн ашканда филлденет. Бул сиз түздөн-түз байкай албаган FIFO кезектеги позицияңызды кадоону талап кылат.

Кезектеги позицияны баалоо механизми — баштапкы позиция, соодаларга каршы жокко чыгарууларга жаңылоо эрежелери, байкалбаган жокко чыгарууларды бөлүштүрүү үчүн f(x)f(x) ыктымалдык үй-бүлөсү — биз Queue inside the wall макаласында курган примитив. Мен аны бул жерде кайра чыгарбайм; симулятор аны керектейт. 4-баскыч кошкон нерсе — бул баанын үстүнө филл чечим эрежеси, ал төмөндөгү филл-ыктымалдык бөлүмүндө камтылган.

Бул баскычтын эмне үчүн маанилүү экени адабиятта сандык түрдө көрсөтүлгөн: Moallemi жана Yuan (2016), "A Model for Queue Position Valuation in a Limit Order Book," чоң-тик инструменттери үчүн кезектин алдыңкы позициясынын экономикалык баалуулугу кезектин арткы жагына салыштырмалуу спреддин жарымына салыштырма — маркет-мейкинг стратегиясынын бүткүл теориялык кырынын так ошол эле чоңдук тартиби менен. Кезектеги позицияны эске албаган филл модели мейкердин PnLин туура эмес баалабайт; ал башка стратегиянын PnLин баалайт.

5-баскыч да бар — толук агенттик симуляция, мында рынок сиздин ордерлериңизге реакция кылат (Huang, Lehalle жана Rosenbaum 2015 маанисиндеги кезек-реактивдүү моделдер; ABIDES сыяктуу көп агенттик фреймворктор, Byrd et al. 2020). Тарыхый кайра ойнотуу, кезекти эске алса дагы, сиздин ордериңиз калгандардын жүрүм-турумунда эч нерсени өзгөртпөйт деп болжолдойт. Бул болжол чекене көлөмдө туура жана сиздин котировкаларыңыз деңгээлдин көрүнөө үлүшүнө айланган сайын барган сайын туура эмес болот. 5-баскыч бул жерде масштабдан тышкары; тепкич 4те бүтпөй турганын билиңиз.

Штат машинасы катары бөлүк-филлдер

0-2-баскычтар ордер функция чакырыгы деп кыла алат: жиберүү, баа алуу, бүттү. 3-баскычтан жогору ордер — жашоо цикли бар процесс, жана симулятор аны штат машинасы катары моделдеши керек, антпесе эң маанилүү учурларды үнсүз туура эмес иштетет.

Кезектеги позиция белгилери менен ордердин жашоо циклинин штат машинасы

enum OrderState {
    PendingNew,                                  // sent, not yet acked (latency window)
    Resting     { remaining: f64, q_ahead: f64 }, // in book, queue position estimated
    PartialFill { remaining: f64, q_ahead: f64 }, // some qty done, rest still queued
    PendingAmend,                                 // amend in flight
    PendingCancel,                                // cancel in flight
    Filled,
    Canceled    { filled_qty: f64 },              // may be partially filled at cancel time
    Rejected,
}

Өтүүлөр экономиканы алып жүрөт:

  • PendingNewResting: ордер кезекке чечим убакытында эмес, ack убакытында бар болгон бардык нерселердин артынан кошулат. Сиздин кезектеги позицияңыз t+Δtackt + \Delta t_{\text{ack}} убакытындагы деңгээл көлөмү менен себилет. Чечим убакытында себе турган симуляторлор кезек артыкчылыгын системалуу түрдө ашыкча баалашат — так сиздин латенттик терезеңиздин ичинде келген көлөмгө, ал болсо жарылуулар учурундагы көлөмдүн көбү.
  • RestingPartialFill: сиздин деңгээлиңиздеги алдыңкы кезектен чоңураак соода сизди жарым-жартылай филлдейт. Калдыгы өзүнүн (эми кезектин алдыңкы) позициясын сактайт. Бөлүк-филлдер ызы-чуу эмес — алар маалымат: 1.0дүн 0.3ин филлдеп, баанын алыстап секиргенин көрүү толук филлге караганда башка PnL окуясы, жана мейкердин инвентарь процесси ушул бөлүктөрдөн курулат.
  • RestingPendingAmendResting: тузак. Дээрлик ар бир крипто-биржада амэнд деген cancel/replace — Binanceдин cancelReplace кош-аткарууга каршы атомдук, бирок кезектин артындагы жаңы ордер IDсин кайтарат. Тубаса модификация семантикасы бар биржалар (CME Globex) дагы убакыт артыкчылыгын санды азайтуу үчүн гана сактайт; баа өзгөрүшү же санды көбөйтүү аны жоготот. Демек симулятордо: кайсы баа амэнди болбосун q_aheadти учурдагы толук деңгээл көлөмүнө кайра орнотот. Ар бир 500msда кайра пеглей турган котировка кыймылдаткычы "котировканы кармап турган" эмес — ал түбөлүккө кезектин артына кайра кирип жатат, жана анын реалдуу филл профили дээрлик таза адверс селекция. Moallemi-Yuan жыйынтыгы менен айкалышканда: кайра котировкалоонун баасы бар, жана бул баа — сиздин кезектеги позицияңыз.
  • PendingCancelPartialFillCanceled: жокко чыгаруулар да латенттик талап кылат. Котировканы тартып алууну чечкен убак менен жокко чыгаруунун дал келүү кыймылдаткычына жеткен убактын ортосундагы терезеде сиз дагы эле филлдене аласыз — жана ал филлдер сиз алган эң жаман филлдер, анткени котировканы тартып алуу себебиңиз рынок сизди тебелегени калды. Жокко чыгаруу латенттиги жок симулятор сиздин тарыхыңыздан так эң уулуу филлдерди өчүрөт.

Штат машинасы ошондой эле симулятордун эсебин ак ниет кылат: комиссиялар ар бир филл окуясы боюнча топтолот, инвентарь ар бир филл окуясы боюнча жаңыланат, жана штаттагы убакыт статистикасы (ордерлер филлденгенге чейин канча узак турат, же жокко чыгарылат) лайв логдор менен түздөн-түз салыштырма болот — бул макаланын аягындагы калибрлөө цикли эмне менен азыктанат.

Лимит-филл ыктымалдыгы: үч модель жана кашаа

pp баасында (мисалы, бид) турган ордер берилгенде, симулятор качан филлди жарыялайт? Үч чечим эрежеси, ак ниеттиктин өсүшү боюнча:

1. Тач-филл (жөнөкөй). Эгер баа сиздин деңгээлиңизге тийсе филл: lowtp\text{low}_t \le p. Бул биринчи-өтүү-убакыт эрежеси, жана анын ийгиликсиздиги чейрек кылым мурда өлчөнгөн: Lo, MacKinlay жана Zhang (2002), "Econometric Models of Limit-Order Executions" (Journal of Financial Economics 65), чыныгы лимиттик ордер маалыматтарына жашоо моделдерин ыңгайлаштырып, биринчи-өтүү убактарынан курулган гипотетикалык аткаруулар "чыныгы лимиттик ордер аткарууларынын өтө начар прокси" деген жыйынтыкка келишет. Ийгиликсиздик режими структуралык: баа сиздин деңгээлиңизге тийип секиргенде, тийүү кезектин алдыңкы жагын — сизден мурда котировкалаган трейдерлерди — керектеди. Тач-филл сизге алардын филлдерин ыйгарат. Андан жаманы, ал так жакшы филлдерди ыйгарат (тий-жана-секир — мейкер үчүн кирешелүү сценарий), ал эми сиздин чыныгы филл топтомуңуз тий-жана-аркылуу-жүр — адверс тандалган — тарапка кыйшайган.

2. Трейд-через (консервативдик чек). Баа сиздин деңгээлиңизден так аркылуу соода кылса гана филл: lowt<pϵ\text{low}_t < p - \epsilon, же тик маалыматта pp баасындагы кумулятивдик соода көлөмү бүткүл деңгээлден ашса. Эгер баа аркылуу соода кылса, pp баасындагы бүткүл кезек керектелген, демек позицияга карабай филлденгенсиз. Бул сиз ала албай турган филлди эч качан ыйгарбайт. Анын жамгыры тач-филлдин күзгү чагылышы: ал сизге кезек толук кирбестен сиздин позицияга чейин түгөнгөн ар бир филлди тыюу салат, жана ал берген филлдер диспропорционалдуу түрдө аркылуу-жүрүү (адверс тандалган) филлдер. Трейд-через астындагы мейкер бэктести — стресс-тест, баа эмес.

3. Кезек түгөнүү баасы. Соода тасмасынан сиздин бааңыздагы кумулятивдик соода көлөмү MtM_t жана L2 дельталардан чыгарылган жокко чыгарылган көлөм CtC_t кадаңыз. Сиздин баланган алдыңкы кезегиңиз:

Q^ahead(t)=max ⁣(Q0MtϕCt,  0)\hat{Q}_{\text{ahead}}(t) = \max\!\Big(Q_0 - M_t - \phi \cdot C_t,\; 0\Big)

мында Q0Q_0 — (ack-убактагы) ордер киргизүүдөгү деңгээл көлөмү жана ϕ[0,1]\phi \in [0,1] — сиздин алдыңыздан келди деп болжолдонгон жокко чыгаруулардын үлүшү — принципиалдуу формасы (the f(x)f(x) family) кезектеги позиция макаласында чыгарылган баскыч. Филл Q^ahead=0\hat{Q}_{\text{ahead}} = 0 болгондо башталат; сиздин филлденген көлөмүңүз андан ашык соода көлөмү, ал бөлүк-филлдерди табигый түрдө берет:

filled(t)=min ⁣(S,  max(MtQ0+ϕCt,0))\text{filled}(t) = \min\!\Big(S,\; \max(M_t - Q_0 + \phi\, C_t,\, 0)\Big)

ϕ=1\phi = 1 (бардык жокко чыгаруулар сиздин алдыңызда) орнотуу бул моделдин оптимисттик кырын берет; ϕ=0\phi = 0 — пессимисттик кыр. Сизде сейрек L2 снапшоттор гана болуп, деңгээлде соода тасмасы жок болгондо — 100ms-дроссельденген крипто фиддер менен кеңири таралган — модель-негизделген алдын ала маалыматка кайтсаңыз болот: Cont, Stoikov жана Talreja (2010), "A Stochastic Model for Order Book Dynamics" (Operations Research 58), ар бир баа деңгээлин туулуу-өлүү кезеги катары моделдеп, Лаплас трансформдары аркылуу учурдагы кезек көлөмдөрүнө шартталып, биддеги ордер мид кыймылдоого чейин аткарыла турган ыктымалдыгын эсептешет. Бул аналитикалык филл-ыктымалдык оракулу: тасма кайра ойнотууга караганда орой, тач-филлге караганда алда канча жакшы, жана ысык бэктест циклинин ичинде баалоого жетишерлик арзан.

Кашаа тартиби

Үч эреже атаандаш эмес — алар иреттөө:

fillstrade-through    fillsqueue    fillstouch\text{fills}_{\text{trade-through}} \;\subseteq\; \text{fills}_{\text{queue}} \;\subseteq\; \text{fills}_{\text{touch}}

бул PnL кашаасын пайда кылат. Ар бир мейкер бэктестин үч жолу иштетип, интервалды билдириңиз:

PnLtrade-through    PnLlivePnLtouch\text{PnL}_{\text{trade-through}} \;\le\; \text{PnL}_{\text{live}} \lesssim \text{PnL}_{\text{touch}}

(жогорку теңсиздик болжолдуу — тач-филл стратегияларды жөн гана көбөйтпөстөн, туура эмес рейтингдей алат, анткени ал сизге контрфактуалдуу жакшы филлдерди берет). Андан келип чыккан чечим эрежеси: мейкер стратегиясы кашаанын консервативдик кырында гана аман калса жайгаштырылса болот, жана кашаа чекиттик баа бир нерсени билдире тургандай тар болушу керек. +9kтач/9k тач / -3k трейд-через көрсөткөн стратегиянын 12kкеңдигиндегикашаасыбар;сизсимуляторуңуздунбожомолуальфаңызданүстөмдүккыларынанбашкаэчнерсебилбейсиз.+12k кеңдигиндеги кашаасы бар; сиз симуляторуңуздун божомолу альфаңыздан үстөмдүк кыларынан башка эч нерсе билбейсиз. +2.1k / +$0.4k көрсөткөн стратегия сизге чыныгы бир нерсе айтып жатат.

Эксперимент: бир мейкер стратегиясын тепкичтен ылдый жүргүзүү

Мейкер стратегиясынын PnLи филл-модель тепкичинен ылдый баскычтан баскычка кулап жатат

Атайын жөнөкөй бир мейкерди алалы — эң мыкты бид/аскта симметриялуу котировкалар, туруктуу 0.05 BTC клиптер, ±0.5 BTC менен инвентарь-чектелген, чекте такер тегиздөө менен. Бир айлык BTCUSDT перпетуал маалыматы: төмөнкү баскычтар үчүн 1m барлар, жогорку баскычтар үчүн 100ms L2 диффтер плюс соода тасмасы; мейкер комиссиясы 1.0 bps, такер 4.0 bps. Ар бир баскычта бирдей сигнал коду (shared core, демек жалгыз өзгөрмө — филл модели). Төмөндөгү сандар — биздин бир өкүл иштетүүбүз; сиздин чоңдуктарыңыз биржа, ай жана көлөм боюнча айырмаланат; форма айырмаланбайт:

Баскыч Филл модели Котировка филл ылдамдыгы Филлдер Айлык PnL Вердикт
0 клоуз-филл 98% 41,200 +$14,800 фантазия
1 next-bar-open / 1m барларда тач 89% 37,400 +$9,600 латенттик менен фантазия
2 тач + такер тегиздөөлөрдө спред & туруктуу проскальзывание 89% 37,400 +$7,100 чыгымдар моделденген, филлдер дагы эле ойдон чыгарылган
3 + такер тегиздөөлөрдө L2 тереңдик боюнча басуу 89% 37,400 +$6,400 чыгуулар ак ниет, кириштер дагы эле ойдон чыгарылган
4a трейд-через (консервативдик) 21% 8,900 -$3,900 стресс чек
4b кезек түгөнүү, ϕ\phi калибрленген 37% 15,600 -$700 эң мыкты баа
4c кезек түгөнүү, ϕ=1\phi = 1 (оптимисттик) 44% 18,700 +$1,900 жогорку кыр
лайв көлөкө иштетүү, ошол эле ай 35% 14,100 -$1,150 чындык

Таблицаны жогорудан ылдый окуп, стратегия кайда өлөрүн көрүңүз. Бул 2-баскыч эмес — комиссиялар жана проскальзывание 26% кырат, стратегия дагы эле бекем кирешелүү көрүнөт. Ал 3-баскыч менен 4-баскычтын ортосунда өлөт, жана эч бир чыгым модели камтый албай турган себеп менен өлөт: филл тандоо. Тач-филл 37,400 филл ыйгарды, алардын көпчүлүгү тий-жана-секир — таза спред жыйноо. Кезекти эске алган модель ошол филлдердин 58% өчүрдү, жана өчүргөн филлдер диспропорционалдуу түрдө кирешелүүлөр: деңгээл жеңил тийгенде, кайра котировкалаган чекене-латенттик мейкердин алдыңкы кезеги баарын соруп алат. 4-баскычка чейин аман калган филлдер деңгээл-тазалаган свиптерге кыйшайган — баа сиз аркылуу кыймылдап жаткан филлдер. Филл ылдамдыгы 2.4x түштү; PnL белгисин алмаштырды. Ошол асимметрия — жакшы филлдерди жоготуп, жаман филлдерди сактоо — механикалык түрдө ачык кылынган адверс селекция, жана ал 4төн төмөнкү ар бир баскычта көрүнбөйт.

Ошондой эле кашаа эмне кылганына көңүл буруңуз: [-3,900,+3,900, +1,900] нөлдү аттап, калибрленген баасы -700жаналайв700 жана лайв -1,150. Симулятор лайв PnLди долларга чейин так койгон жок — ал белгини, чоңдукту жана филл ылдамдыгын 2 пунктта тапты. Филл модели ушул үчүн керек. 1-баскыч бэктести бүткүл айлык брутто кыры бир нече миң доллар болгон стратегияда лайв PnLди $10,750 менен өткөрүп жиберди: филл-модель катасы альфадан болжол менен 3x чоңураак болгон. Демек тезис: сиздин филл моделиңиз альфаңызга караганда чоңураак божомол.

Төмөнкү баскычтар үчүн бир эскертүү: эгер сиз бар маалыматында жашашыңыз керек болсо (0-2-баскычтар), кеминде интрабар түшүнүксүздүктү адаптивдик тереңдетүү менен чечиңиз — SL, TP же котировка деңгээлдери бар диапазонунун ичине түшкөн жерде 1m ден 1s/100ms/соодаларга тереңдетүү. Тереңдетүү ирээттөө каталарын оңдойт (кайсы деңгээл биринчи тийди), бирок кезек каталарын оңдой албайт; ал бул макаланын маалымат-чечилиш коштоочусу, 4-баскычтын алмаштыруусу эмес.

Калибрлөө цикли: лайв филлдерге карата жабуу

4-баскыч симуляторунда эркин параметрлер бар — ϕ\phi, латенттик Δt\Delta t, жокко-чыгаруу-латенттиги, деңгээл-толуктоо божомолу. Калибрленбегенде, ал жөн гана башка формадагы божомол. Аны инструментке айландырган цикл:

1. Баарын лайв логдоп жүр. Биржа убакыт белгилери менен ар бир ордер окуясы: жиберүү, ack, ар бир бөлүк-филл, амэнд acktар, жокко чыгаруу acktар. Плюс жиберүү убагындагы L2 абалы. Бул backtest-live parity өзүнүн DivergenceMonitor үчүн талап кылган ошол эле логдоо тартиби — филл-модель калибрлөө ошол мониторунун эң терең катмары.

2. Ошол эле ордерлерди симулятор аркылуу кайра ойнот. Жазылган рынок маалыматын жана жазылган ордер инструкцияларын (филлдерди эмес) симуляторго бер. Эми сизде жупталган жыйынтыктар бар: ар бир лайв ордер үчүн симуляцияланган тагдыр.

3. Орточолорду эмес, бөлүктөрдө бөлүштүрүүлөрдү салыштыр. Бир глобалдуу филл-ылдамдык дал келүү компенсациялоочу каталарды жашыра алат (тынч режимдерде өтө оптимисттик, жарылууларда өтө пессимисттик — "калибрленген"ге неттелип). Драйверлер боюнча бөлүктө:

import numpy as np
from scipy.stats import ks_2samp

def calibration_report(pairs, bucket_key):
    """pairs: [{'bucket':…, 'live_filled':bool, 'sim_filled':bool,
                'live_ttf':float|None, 'sim_ttf':float|None}, …]"""
    out = {}
    for b in sorted({p['bucket'] for p in pairs}):
        grp = [p for p in pairs if p['bucket'] == b]
        live_fr = np.mean([p['live_filled'] for p in grp])
        sim_fr  = np.mean([p['sim_filled']  for p in grp])
        live_ttf = [p['live_ttf'] for p in grp if p['live_ttf'] is not None]
        sim_ttf  = [p['sim_ttf']  for p in grp if p['sim_ttf']  is not None]
        ks = ks_2samp(live_ttf, sim_ttf) if len(live_ttf) > 20 and len(sim_ttf) > 20 else None
        out[b] = {
            'n': len(grp),
            'fill_rate_live': live_fr,
            'fill_rate_sim':  sim_fr,
            'fill_rate_gap':  sim_fr - live_fr,      # signed: + means sim optimistic
            'ttf_ks_pvalue':  ks.pvalue if ks else None,
        }
    return out

Ар бир бөлүккө эки статистика: белгиленген филл-ылдамдык ажырымы (симулятор минус лайв) жана филлденген ордерлердин арасында убакыт-филлге чейинки бөлүштүрүүлөр боюнча KS тест. Убакыт-филлге чейинки салыштыруу — эң курч: симулятор филл ылдамдыктарын дал келтире алат, бирок системалуу түрдө туура эмес убакытта филлдеп, ал ар бир төмөнкү инвентарь жана адверс-селекция статистикасын бузат. Бул так Lo-MacKinlay-Zhangдын жашоо-анализ формулировкасынын сабагы: аткаруу — окуяга-чейинки-убакыт маселеси, ошондуктан аны ошондой түрдө текшериңиз.

4. Идентификациялоо мүмкүнчүлүгү тартибинде тумчаларды ыңгайлаштыр. Латенттик биринчи (ack убакыт белгилеринен түздөн-түз өлчөнөт — ыңгайлаштырылбайт). Андан кийин ϕ\phi кезек-тереңдик бөлүктөрү боюнча филл-ылдамдык ажырымын минимумга келтирүү менен. Андан кийин вол-режим бөлүктөрүн текшер: жарылуу бөлүктөрүндө топтолгон туруктуу оптимисттик ажырым адатта симуляторуңуз жокко-чыгаруу-латенттиги уулуу филлдерди же деңгээл толуктоону аз моделдеп жатканын билдирет, ϕ\phi эмес.

5. Кашааны кайра иштет. Калибрлөөдөн кийин кезек түгөнүү баасы лайвга жакын кашаанын ичинде отурушу керек, жана — чыныгы кабыл алуу тести — симулятор астындагы стратегия варианттарынын рейтинги көлөкө режиминдеги алардын рейтинги менен дал келиши керек. Андан кийин параметрлерди тоңдуруп, графикке ылайык кайра калибрле; филл динамикасы биржанын комиссия деңгээлдери, тик-өлчөм өзгөрүштөрү жана HFT популяциясы менен дрейфтейт, жана мартта калибрленген ϕ\phi июлга гипотеза.

Биздин иштетүүлөрдөгү конвергенция күтүүлөрү: калибрленбеген 4-баскыч симулятору адатта лайв филл ылдамдыгынын ±10-15 пунктунда келет; бир калибрлөө өтүшүнөн кийин, ±3-5 пункт, убакыт-филлге чейинки KS p-баалуулуктары мындан ары бирдей четке кагылбайт. Тарыхый кайра ойнотуу менен мындан жакшыраак кыла албайсыз — калдык — бул рынактын сизге болгон реакциясы, ал 5-баскычтын маселеси.

Эмнени эске алуу керек

  1. Баскычыңызды атаңыз. Ар бир бэктест бул тепкичте отурат, баскычты сиз тандадыңызбы же фреймворкуңуз сиз үчүн тандадыбы. Эгер филл моделиңиздин баскычын жана анын белгилүү жамгырларын атай албасаңыз, сиздин PnL санынын сиз көрбөгөн ката тилкелери бар.
  2. Такерлер 3-баскычта токтой алат. Тереңдик боюнча басуу плюс өлчөнгөн латенттик чекене көлөмдө агрессивдүү аткарууну ак ниет баалайт. Үнөмдөлгөн күчтү маалымат сапатына жумшаңыз.
  3. Мейкерлер 4-баскычтан башташат. Андан төмөн лимиттик ордер филл логикасы болжолдуу эмес — ал карама-каршы адверс-селекция кыйшайуусу менен контрфактуалдуу филл топтомун тандайт. Мейкер стратегияларынын тач-филл бэктесттери — продакшн менен байланышта өлгөн стратегиялардын эң ишенимдүү генератору.
  4. Филлди эмес, жашоо циклин моделдеңиз. Бөлүк-филлдер, амэнд-кезек-кайра-орнотот, жокко чыгаруу латенттиги — штат машинасы уулуу филлдер жашаган жер, ал эми уулуу филлдер — мейкер PnLи өлгөн жер.
  5. Кашааны билдириңиз. Консервативдик жана оптимисттик чектер эки кошумча бэктест иштетүүсүн талап кылат жана "менин бэктестим +7kдейт"ти"чындык[7k дейт"ти "чындык [-3.9k, +$1.9k] арасында бир жерде"ге айландырат — бул башка жана жакшыраак чечим.
  6. Лайв филлдерге карата бөлүктө калибрлеңиз. Жалпы түрдө гана текшерилген филл модели — жашырылган компенсациялоочу каталары бар филл модели. Бөлүктөгү филл-ылдамдык ажырымдары плюс убакыт-филлге чейинки KS тесттери, чейректе кайра калибрленген.

Тепкичтин баскычтары академиялык градациялар эмес — ар бири сиздин бэктестиңиз сизге айтууну токтоткон конкреттүү жалган. Жалгандар кырыңыздан кичине болгонго чейин чыгыңыз.

Пайдалуу шилтемелер

  1. Moallemi, C., Yuan, K. — A Model for Queue Position Valuation in a Limit Order Book (2016)
  2. Cont, R., Stoikov, S., Talreja, R. — A Stochastic Model for Order Book Dynamics, Operations Research 58(3), 549-563 (2010)
  3. Lo, A., MacKinlay, C., Zhang, J. — Econometric Models of Limit-Order Executions, Journal of Financial Economics 65(1), 31-71 (2002)
  4. Huang, W., Lehalle, C.-A., Rosenbaum, M. — Simulating and Analyzing Order Book Data: The Queue-Reactive Model, JASA 110(509), 107-122 (2015)
  5. Almgren, R., Chriss, N. — Optimal Execution of Portfolio Transactions (2001)
  6. Byrd, D., Hybinette, M., Balch, T. — ABIDES: Towards High-Fidelity Multi-Agent Market Simulation (2020)
  7. Binance API — Cancel-Replace order semantics
  8. CME Globex — Order modification and time priority rules

Citation

@article{soloviov2026fillsimulation,
  author = {Soloviov, Eugen},
  title = {Fill simulation: the ladder from close-price fantasy to queue-aware reality},
  year = {2026},
  url = {https://marketmaker.cc/blog/fill-simulation-partial-fills-backtest},
  description = {Five rungs of fill simulation fidelity — from close-price fills to probabilistic queue-position models. Partial fills as a state machine, limit-fill probability bounds as a PnL bracket, and a calibration loop against live fills.}
}
blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Рынктан бир кадам алдыда болуңуз

AI соода аналитикасы, рынок талдоолору жана платформа жаңылыктары үчүн биздин жаңылыктар бюллетенине жазылыңыз.

Биз сиздин купуялыгыңызды урматтайбыз. Каалаган убакта жазылымдан чыга аласыз.