2. září 2026 · mikrostruktura

Váš limitní příkaz se nevyplnil: dopis o pozici ve frontě, maker backtestech a Sharpe, který jste si vymysleli

Váš limitní příkaz se nevyplnil: dopis o pozici ve frontě, maker backtestech a Sharpe, který jste si vymysleli

Minulý týden jste mi poslali notebook: stejný signál, stejný soubor instrumentů, stejných 14 měsíců dat BTCUSDT perpetualu. Změnila se jen exekuce. Přestali jste překračovat spread a začali jste nechávat nákupní příkazy čekat o 1 tick výš. Sharpe stoupl z 0.42 na 2.14. Ptali jste se, jestli je to skutečné, nebo jestli jste něco pokazili.

Něco jste pokazili. Chci vám přesně ukázat kde, protože chyba je na jednom řádku a poučení, které z ní plyne, je mnohem větší než ten řádek.

Tady je vaše pravidlo pro plnění, zkopírované z enginu:

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

Říká to: pokud se během této minuty zobchodovalo za mou cenu nebo níže, můj příkaz se vyplnil za mou cenu. Ve skutečnosti to ale znamená, že se cena vaší úrovně jen dotkla. Dotyk není plnění. Mezi těmito dvěma událostmi stojí fronta, kterou jste v modelu nechali prázdnou.

Co stojí před vámi

Když zadáte nákupní příkaz na BTCUSDT perpetualu za 84,120.0, zařadíte se na konec všeho, co už na této ceně čeká. Na nejlepší cenové úrovni tohoto kontraktu je to obvykle 4 až 30 BTC podle denní doby; medián ve vašem vzorku je zhruba 12 BTC. Váš příkaz má velikost 0.4 BTC. Aby se zobchodoval, musí prodejci prodat na této úrovni takový celkový objem, který stačí na odbavení všech, kdo dorazili před vámi. A musí to stihnout dřív, než se příkazy na této úrovni zruší nebo cena uteče nahoru.

Váš backtest se tedy nemá ptát „dosáhla cena hodnoty 84,120.0“, ale „zobchodovalo se na úrovni 84,120.0 alespoň 12.4 BTC prodejními market příkazy, když tam čekal můj příkaz?“ To jsou úplně jiné události. Ve vašich datech se liší zhruba trojnásobně.

12.4 BTCmedián objemu před vámi při dotyku ceny
100%míra plnění předpokládaná vaším backtestem
31%dotyků, při kterých se odbavila fronta před vámi
4,180obchodů, z nichž zůstalo zhruba 1,300

3 pravidla plnění, 3 různé strategie

Znovu jsem spustil váš signál se stejnými vstupy a 3 modely exekuce. Stejná alfa, stejné poplatky, stejné fundingové platby. Změnila se jen logika plnění.

Pravidlo plněníPočet plněníPrůměrná 60s výhoda po plněníSharpe
Dotyk: low <= limit4,180+2.6 bp2.14
Přísné překročení ceny: low < limit - 1 tick1,712+0.4 bp0.61
Simulace fronty podle objemu na cenové úrovni1,306+0.9 bp0.77

Prostřední řádek je hrubá oprava, po které většina lidí sáhne jako první: plnění započítejte, jen když se na trhu obchodovalo striktně za vaší cenou, protože pokud cena pokračovala dál, musela váš příkaz spotřebovat. Směrově to dává smysl a odstraní to většinu fantazie. Má to ale i ošklivé zkreslení, k němuž se dostanu za chvíli.

Spodní řádek je model, který byste měli postavit. Nepotřebuje L3 feed ani rekonstrukci každého příkazu zvlášť. Většinu potřebných dat už máte.

Simulace fronty, kterou postavíte z aggTrades

Místo kline svíček stáhněte stream agregovaných obchodů. Každý záznam obsahuje cenu, množství, časové razítko a příznak strany maker, který říká, zda agresor nakupoval, nebo prodával. To stačí pro použitelnou simulaci vašeho pasivního příkazu:

  1. Při zadání příkazu uložte aktuální objem čekajících příkazů na vaší ceně. Pokud máte jen feed knihy objednávek s intervalem 100ms, použijte poslední snímek; chyba je malá ve srovnání s tou, kterou opravujete.
  2. Nastavte queue_ahead = resting_size. Buďte pesimističtí a předpokládejte, že jste poslední. Pokud úroveň sami nevytváříte, jste.
  3. Procházejte stream obchodů. Každý záznam, kde je agresorem prodávající a cena je stejná nebo nižší než vaše, sníží queue_ahead o své množství. Když hodnota klesne pod nulu, váš příkaz se vyplní za vaši cenu a v čase daného záznamu.
  4. Když se cena vzdálí o 1 tick, nenastavujte frontu zpět na nulu. Nechte ji postupně klesat. Některé příkazy před vámi se zruší, když úroveň zastará, jiné zůstanou. Pokles o 30-40% za každou celou sekundu mimo nejlepší cenu odpovídal mým rekonstrukcím lépe než kterýkoli z obou extrémů.
  5. Pokud by vaše strategie příkaz zrušila a zadala znovu, modelujte nové zadání jako nový příkaz na konci nové fronty. Tento krok lidé vynechávají a právě tady se skrývá zbytek fantazie.

U kroku 2 se mnou budete chtít polemizovat. Ano, někdy budete blízko začátku, protože jste příkaz zadali ve chvíli, kdy se úroveň vytvořila. Dobře — zaznamenávejte to, nepředpokládejte. Ukládejte objem čekajících příkazů při zadání a nechte data ukázat, jaký podíl vašich příkazů je opravdu mezi prvními. Ve vaší strategii to bylo 11%, protože signál se spouští až po pohybu. To znamená, že úroveň, ke které se připojujete, už existuje a už na ní čeká dav.

Vyplní se vám právě ty příkazy, které byste si přáli nevyplnit

Teď k tomu, na čem opravdu záleží, a k důvodu, proč je pravidlo přísného překročení ceny zkreslené.

Zamyslete se, kdy se váš nákupní příkaz celý spotřebuje. Stane se to, když je prodejní tlak dost velký, aby pohltil celou úroveň. Tím pádem je to právě okamžik, kdy trh klesá skrz vaši cenu. U plnění, kterými si můžete být nejjistější, jste okamžitě ve ztrátě.

Rozdělte plnění podle toho, jak k nim došlo, a změřte výsledek po 60 sekundách:

Typ plněníPodíl plněníVýsledek po 60 s
Obchodovalo se na úrovni, cena se odrazila nahoru38%+3.1 bp
Obchodovalo se na úrovni, cena se nepohnula21%+0.2 bp
Cena překročila vaši cenu o 2+ ticků41%−2.4 bp

Váš naivní backtest zahrnul všechny 3 skupiny a všem připsal bezplatné plnění. Pravidlo přísného překročení ceny vám dá téměř výhradně třetí skupinu, a proto jeho výhoda klesla ještě víc než u simulace fronty. Ani jedno není správně. Simulace fronty vám dá realistický mix a právě na něm záleží: pasivní exekuce vám přináší spread a zároveň vás stojí nepříznivou selekci. Vaší skutečnou strategií je poměr mezi těmito dvěma vlivy.

Staré pojetí z akciového trading desku pořád platí: maker příkaz je opce, kterou jste trhu vypsali zdarma. Někdo ji uplatní, když se mu to vyplatí. Váš backtest inkasoval prémii a zapomněl, že opce má i výplatní část.

Nevyplněné příkazy mění strategii, nejen její náklady

Tohle je bod, u kterého bych se rád zastavil nejdéle. Když špatně modelujete taker exekuci, dostanete správné obchody za nesprávnou cenu a většinu problému vyřeší korekce poplatků. Když špatně modelujete maker exekuci, dostanete úplně jinou sadu obchodů. Z vašich 4,180 vstupů se zhruba 2,900 nikdy neuskutečnilo. Některé z nich byly vaše nejlepší signály, na svíčkách, které prudce vystřelily skrz cenu a pak se otočily — přesně v takových situacích trh utekl bez vás.

Proto potřebuje větev pro nevyplněný příkaz skutečnou logiku. Co strategie udělá, když se vstup nevyplní dřív, než signál zastará? Vstoupí agresivně taker příkazem a zaplatí spread i tržní dopad? Zadá nový příkaz níže a přijme jiný základ vstupní ceny? Obchod přeskočí a zůstane mimo trh? Každá možnost vytvoří výrazně odlišnou kapitálovou křivku a žádná neříká „předpokládej, že se příkaz vyplnil“. V našich bězích poctivé pravidlo dohánění (po 20 sekundách bez plnění překročit spread, s limitem skluzu 3 bp) obnovilo asi třetinu chybějících obchodů a zhruba polovinu rozdílu v Sharpe mezi naivním backtestem a simulací fronty. To je opravdu zajímavý výsledek, který se ukáže až ve chvíli, kdy je model plnění dost realistický na to, aby otázka dávala smysl.

Rychlá kontrola, 10 minut: vezměte záznamy ze svého živého paper tradingu a backtest za stejné období. Porovnejte míru plnění, ne PnL. Pokud backtest vyplní 100% čekajících příkazů a paper trading 34%, neporovnáváte strategie, ale máte chybu v modelu plnění. Opravte ji, než se podíváte na jediné číslo výnosu.

Ještě 2 drobnosti, když vás tu mám

Odmítnutí post-only příkazů. Pokud používáte post-only, abyste si zajistili sazbu maker poplatků, a kniha objednávek se změní mezi vaším rozhodnutím a potvrzením burzy, příkaz se odmítne, místo aby začal čekat. V našich paper záznamech to během běžných hodin představuje 3-6% pokusů na BTCUSDT a přes 15% v minutě po zveřejnění amerického CPI. Odmítnutý příkaz není vyplněný příkaz ani nevyplněný čekající příkaz. Je to obchod, který nikdy neexistoval. Pokud váš backtest tento stav nezná, počet obchodů je nadhodnocený právě v režimech, na kterých vám nejvíc záleží.

Prevence vlastního obchodování a vaše stopa na trhu. Při velikosti 0.4 BTC trhem BTCUSDT nehýbete, takže to můžete přeskočit. Zmínili jste ale, že to chcete spustit na perpetualu altcoinu se střední kapitalizací, kde nominální objem na nejlepší ceně často nedosahuje $15k. Tam váš příkaz už představuje významný podíl fronty a údaj o objemu před vámi, který ukládáte, už zahrnuje vliv vašeho posledního příkazu. Jakmile vaše velikost přesáhne zhruba 10% čekajícího objemu, simulace musí zohlednit, že na vás ostatní účastníci reagují. A upřímně, v tu chvíli bych víc věřil paper tradingu než jakékoli simulaci, kterou dokážeme napsat vy nebo já.

Spusťte to znovu se simulací fronty a pošlete mi tabulku výsledků po 60 sekundách rozdělenou podle typu plnění. Pokud skupina odrazů stále tvoří většinu výhody a skupina překročení ceny ji celou nesmaže, možná máte něco, co stojí za vyzkoušení na paper účtu. Pokud celý výsledek stál na 2,900 plněních, ke kterým by nikdy nedošlo, je lepší to zjistit teď než po 4 týdnech sledování paper účtu, který se nechová podle slibů notebooku.

limitní příkazypozice ve frontěnepříznivá selekcebacktestingkrypto futures
← Všechny články