2 septembrie 2026 · microstructure

Ordinul tău limită nu s-a executat: o scrisoare despre poziția în coadă, backtesturile maker și Sharpe-ul pe care l-ai inventat

Ordinul tău limită nu s-a executat: o scrisoare despre poziția în coadă, backtesturile maker și Sharpe-ul pe care l-ai inventat

Ne-ai trimis notebookul săptămâna trecută: același semnal, același univers, aceleași 14 luni de date BTCUSDT perp. Singura schimbare a fost execuția. Ai încetat să traversezi spreadul și ai început să lași biduri cu un tick mai sus, iar Sharpe-ul a crescut de la 0.42 la 2.14. Ai întrebat dacă rezultatul e real sau dacă ai stricat ceva.

Ai stricat ceva. Vreau să-ți arăt exact unde, fiindcă bugul e într-un singur rând, iar lecția din spatele lui e mult mai amplă.

Iată regula ta de execuție, copiată din motorul tău:

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

Asta spune: dacă piața a tranzacționat la prețul meu sau sub el în acel minut, ordinul meu s-a executat la prețul meu. De fapt, regula codifică doar faptul că prețul a atins nivelul tău. Atingerea nu înseamnă execuție. Între cele două se află o coadă, iar tu ai modelat-o ca și cum ar fi goală.

Ce stă în fața ta

Când plasezi un bid la 84,120.0 pe BTCUSDT perp, te așezi la coada ordinelor deja aflate acolo. La nivelul cel mai bun din carnetul acelui contract, sunt de obicei între 4 și 30 BTC, în funcție de momentul zilei; mediana din intervalul eșantionului tău este în jur de 12 BTC. Ordinul tău are 0.4 BTC. Ca să tranzacționezi, vânzătorii trebuie să lovească acel nivel cu un volum agregat suficient pentru a-i epuiza pe toți cei ajunși înaintea ta, înainte ca nivelul să fie anulat de sub tine sau ca piața să urce de acolo.

Așadar, întrebarea pe care ar trebui să o pună backtestul tău nu este „a ajuns prețul la 84,120.0?”, ci „s-au executat cel puțin 12.4 BTC în ordine de vânzare la piață la 84,120.0 cât timp ordinul meu a stat acolo?”. Sunt evenimente complet diferite. În datele tale, diferă de aproximativ 3 ori.

12.4 BTCvolum median aflat înaintea ta când prețul atinge nivelul
100%rata de execuție presupusă de backtestul tău
31%din atingeri au epuizat coada din fața ta
4,180tranzacții, devenite aproximativ 1,300

3 reguli de execuție, 3 strategii diferite

Am rulat din nou semnalul tău cu aceleași intrări și 3 modele de execuție. Același alpha, aceleași comisioane, aceeași finanțare. S-a schimbat doar logica execuțiilor.

Regulă de execuțieExecuțiiEdge mediu la 60s după execuțieSharpe
Atingere: low <= limit4,180+2.6 bp2.14
Penetrare strictă: low < limit - 1 tick1,712+0.4 bp0.61
Simulare de coadă bazată pe volumul la nivel1,306+0.9 bp0.77

Rândul din mijloc este soluția simplă la care recurge toată lumea mai întâi: numără execuția doar dacă piața a tranzacționat strict dincolo de prețul tău, pe ideea că, dacă a trecut de el, trebuie să te fi executat. Intuiția e în direcția bună și elimină mare parte din fantezie. Dar introduce și o distorsiune serioasă, la care voi reveni.

Rândul de jos este modelul pe care ar trebui să-l construiești. Nu necesită flux L3 și nici reconstruirea fiecărui ordin. Ai deja mare parte din date.

O simulare de coadă pe care o poți construi din aggTrades

Preia fluxul tranzacțiilor agregate în locul lumânărilor. Fiecare tranzacție înregistrată conține prețul, cantitatea, marcajul temporal și indicatorul părții maker, care îți spune dacă agresorul cumpăra sau vindea. E suficient pentru o simulare funcțională a propriului ordin pasiv:

  1. Când ordinul tău este plasat, înregistrează volumul aflat deja la prețul tău. Dacă ai doar un flux al carnetului actualizat la fiecare 100ms, folosește ultima captură; eroarea este mică față de cea pe care încerci s-o corectezi.
  2. Setează queue_ahead = resting_size. Fii pesimist și presupune că ești ultimul. Așa e, dacă nu tu ai creat nivelul.
  3. Parcurge fluxul tranzacțiilor. Fiecare tranzacție inițiată de un vânzător, la prețul tău sau sub el, scade cantitatea din queue_ahead cu volumul tranzacției. Când valoarea devine negativă, ordinul tău s-a executat la prețul tău și la marcajul temporal respectiv.
  4. Dacă prețul se îndepărtează cu un tick, nu reseta coada la zero. Redu-i volumul treptat. Unele ordine aflate înaintea ta sunt anulate când nivelul devine învechit, altele rămân. O reducere de 30-40% pentru fiecare secundă întreagă petrecută departe de nivel s-a potrivit mai bine cu reconstrucțiile mele decât oricare dintre extreme.
  5. Dacă strategia ta ar anula ordinul și l-ar plasa din nou, modelează noul ordin la coada noului nivel. Mulți sar peste pasul acesta, iar aici se ascunde restul fanteziei.

La pasul 2 probabil vei vrea să mă contrazici. Da, uneori ești aproape în față, fiindcă ai plasat ordinul chiar când s-a format nivelul. În regulă — măsoară asta, nu o presupune. Înregistrează volumul aflat la nivel când plasezi ordinul și lasă datele să-ți arate ce proporție dintre ordinele tale sunt într-adevăr printre primele. În strategia ta, era 11%, fiindcă semnalul apare după o mișcare, ceea ce înseamnă că nivelul la care te alături există deja și are deja destui participanți.

Execuțiile pe care le primești sunt cele pe care ți-ai fi dorit să nu le primești

Acum urmează partea care contează cu adevărat și explică de ce regula penetrării stricte este distorsionată.

Gândește-te la momentul în care bidul tău este executat în întregime. Se întâmplă când presiunea de vânzare e suficient de mare încât să consume tot nivelul. Prin construcție, acesta este momentul în care piața coboară prin prețul tău. Cele mai sigure execuții sunt cele în care poziția ta intră imediat pe pierdere.

Împarte execuțiile în funcție de cum s-au produs și măsoară mark-out-ul la 60 de secunde:

Tipul execuțieiPonderea execuțiilorMark-out la 60s
Tranzacționare la nivel, prețul a ricoșat în sus38%+3.1 bp
Tranzacționare la nivel, prețul a rămas stabil21%+0.2 bp
Prețul a trecut de nivel cu cel puțin 2 ticks41%−2.4 bp

Backtestul tău naiv a inclus toate cele 3 categorii și le-a tratat pe toate ca și cum ar fi fost gratuite. Regula penetrării stricte îți oferă aproape exclusiv a treia categorie, motiv pentru care edge-ul ei s-a prăbușit mai mult decât cel al simulării de coadă. Niciuna dintre metode nu e corectă. Simularea de coadă îți oferă o combinație realistă, iar combinația e tot jocul: execuția pasivă îți aduce spreadul și te costă prin selecția adversă; raportul dintre cele două este strategia ta reală.

Perspectiva vechilor deskuri de acțiuni rămâne valabilă: un ordin maker este o opțiune gratuită pe care ai vândut-o pieței. Cineva o exercită atunci când îi convine s-o facă. Backtestul tău încasa prima și uita că opțiunea implică și o plată.

Tranzacțiile pe care nu le-ai obținut schimbă strategia, nu doar costul

Aici vreau cel mai mult să te oprești și să te gândești. Când modelezi prost execuția taker, obții tranzacțiile potrivite la prețul greșit, iar corectarea comisioanelor rezolvă cea mai mare parte a problemei. Când modelezi prost execuția maker, obții cu totul alt set de tranzacții. Aproximativ 2,900 dintre cele 4,180 de intrări ale tale nu s-au produs niciodată. Unele erau semnalele tale cele mai bune, pe lumânări care au trecut brusc de nivel și apoi s-au întors — exact tiparul în care piața a plecat fără tine.

Așadar, ramura pentru ordinele neexecutate are nevoie de logică reală. Ce face strategia când ordinul de intrare nu se execută până când semnalul devine învechit? Urmărește prețul cu un ordin taker și plătește spreadul plus impactul? Plasează un nou ordin mai jos și acceptă o altă bază de intrare? Renunță la tranzacție și rămâne fără poziție? Fiecare alegere produce o curbă de capital substanțial diferită și niciuna nu înseamnă „presupune că ordinul s-a executat”. În testele noastre, adăugarea unei reguli oneste de urmărire — traversarea spreadului după 20 de secunde fără execuție, cu derapajul limitat la 3 bp — a recuperat aproximativ o treime din tranzacțiile lipsă și aproape jumătate din diferența dintre Sharpe-ul naiv și cel obținut cu simularea de coadă. Rezultatul e cu adevărat interesant și apare doar când modelul de execuție e suficient de realist încât întrebarea să aibă sens.

Verificare rapidă, 10 minute: ia jurnalul tranzacțiilor tale live pe cont demo și backtestul pentru aceeași perioadă. Compară rata de execuție, nu PnL-ul. Dacă backtestul execută 100% dintre ordinele pasive, iar contul demo 34%, nu compari două strategii; ai un bug în modelul de execuție. Corectează-l înainte să te uiți la vreun randament.

Încă 2 lucruri, cât te am la telefon

Refuzuri post-only. Dacă folosești post-only pentru a garanta nivelul de comision maker, iar carnetul se schimbă între decizia ta și confirmarea exchange-ului, ordinul este refuzat în loc să fie pus în carnet. În jurnalele noastre de tranzacționare pe cont demo, asta se întâmplă în 3-6% dintre încercările pe BTCUSDT în orele obișnuite și în peste 15% dintre încercările din minutul de după publicarea datelor CPI din SUA. Un ordin refuzat nu este nici un ordin executat, nici un ordin pasiv neexecutat; este o tranzacție care n-a existat niciodată. Dacă backtestul tău nu include starea asta, numărul tranzacțiilor e umflat tocmai în regimurile care te interesează cel mai mult.

Prevenirea auto-tranzacționării și amprenta propriilor ordine. La 0.4 BTC nu miști BTCUSDT, așa că poți ignora aspectul acesta. Dar ai spus că vrei să rulezi strategia pe un perp al unui altcoin cu capitalizare medie, unde valoarea nominală de la cel mai bun nivel din carnet este adesea sub $15k. Acolo, ordinul tău reprezintă o parte semnificativă din coadă, iar valoarea pe care o înregistrezi pentru volumul din față include efectul prezenței ultimului tău ordin. Când ordinul tău depășește aproximativ 10% din volumul aflat la nivel, simularea trebuie să țină cont de faptul că ceilalți participanți reacționează la tine. Sincer, în acel punct aș avea mai multă încredere în tranzacționarea pe cont demo decât în orice simulare pe care am putea s-o scriem tu sau eu.

Rulează-l din nou cu simularea de coadă și trimite-mi tabelul mark-out, separat după tipul execuției. Dacă categoria cu ricoșeu păstrează în continuare cea mai mare parte din edge, iar categoria în care prețul a trecut de nivel nu-l anulează în întregime, s-ar putea să ai ceva ce merită testat pe cont demo. Dacă totul se datora celor 2,900 de execuții pe care nu le-ai fi obținut niciodată, e mai bine să afli acum decât după 4 săptămâni în care urmărești un cont demo ce nu face ce promitea notebookul.

ordine limităpoziția în coadăselecție adversăbacktestingfutures cripto
← Toate articolele