Long pozice otevřená na 84,120. Stop-loss na 84,036, take-profit na 84,271. Dorazí svíčka následující minuty: open 84,118, high 84,290, low 84,010, close 84,240.
Obě úrovně leží uvnitř této svíčky. Stop-loss byl zasažen a take-profit byl zasažen, ale čtyři hodnoty OHLC neobsahují vůbec žádnou informaci o tom, co přišlo dřív. Váš backtest přesto vrátil číslo. Někde ve smyčce o tom rozhodl řádek kódu — nejspíš takový, který vás při psaní nenapadl jako modelovací předpoklad.
Tohle je největší zdroj falešné výkonnosti, který u strategií s krátkým horizontem vídám; předčí poplatky i skluz, protože to jako předpoklad nevypadá. Vypadá to jako technické propojení.
Chybný postup č. 1: nechat rozhodnout řetězec podmínek if
Obvyklá podoba:
if bar.high >= target:
exit(target, "tp")
elif bar.low <= stop:
exit(stop, "sl")
Nikdo si nevybral „take-profit se vyhodnotí před stop-lossem“. Kontrola take-profitu se prostě napsala jako první, protože to je příznivý scénář a právě na něj jste mysleli. Prohoďte obě větve a změní se křivka kapitálu; už to samo by vám mělo napovědět, že P&L strategie částečně závisí na tom, jak jste zrovna psali kód.
Otestoval jsem záměrně obyčejnou skalpovací strategii návratu k průměru na BTCUSDT perp, na třech měsících 1minutových svíček, 4,812 obchodech, se stop-lossem 0.10% a take-profitem 0.18% od vstupní ceny. Signály i poplatky byly stejné, změnila se jen konvence pro rozřešení shody.
Celý výsledek stojí na osmině obchodů. Taková je aritmetika těsné kombinace stop-lossu a take-profitu: nejednoznačné jsou právě obchody, v nichž se cena pohnula oběma směry, tedy většina těch zajímavých; každý z nich může podle hodu mincí přinést celý rozdíl mezi stop-lossem a take-profitem. 12.6% obchodů × rozpětí 0.28% odpovídá 3.5% hrubého nominálního obratu na jednotku vzorku, což výrazně převyšuje skutečnou edge strategie.
Míra závisí na velikosti svíčky vzhledem k rozestupu úrovní a rychle se zhoršuje s prodlužováním intervalu. Stejný stop-loss i take-profit, stejné signály, jiné převzorkování:
| Interval svíčky | Obchody s oběma úrovněmi uvnitř jedné svíčky | Sharpe (take-profit první) |
|---|---|---|
| 1s | 0.3% | 0.91 |
| 1m | 12.6% | 2.31 |
| 5m | 34% | 3.60 |
| 15m | 49% | 4.42 |
| 1h | 71% | 5.88 |
Podívejte se, co ta tabulka skutečně říká. Hrubší svíčky backtest zlepšily. Každý výzkumník by čekal, že hodinové svíčky jsou konzervativní volba: méně šumu a menší přeučení na mikrostrukturu. Jenže když konvence pro události uvnitř svíčky rozhoduje ve váš prospěch, hrubší svíčka je jen větší prostor, v němž můžete předpokládat, že jste měli štěstí. U 1h svíček je sedm z deseti obchodů čistě otázkou konvence. Takový backtest netestuje strategii, ale pořadí dvou příkazů `if` celkem 3,400krát.
Chybný postup č. 2: předpokládat plnění stop-lossu přesně na jeho ceně
Předpokládejme, že pořadí opravíte. Jako první se vyhodnotí stop-loss, zaúčtujete ztrátu přesně 0.10% plus poplatek taker a máte pocit, že postupujete důsledně. Pořád jsou tu dvě různé chyby.
První je, že stop-loss je spouštěč, nikoli cena plnění. Na Binance USDⓈ-M se příkaz STOP_MARKET ve chvíli splnění spouštěcí podmínky změní na tržní příkaz a ten pak spotřebovává dostupnou likviditu v knize objednávek. V klidné minutě to znamená skluz o jeden či dva tickety. V minutě, která váš stop-loss skutečně spustila — s tělem svíčky o 40 bodech a likvidační kaskádou pod ním — je kniha na straně, proti níž obchodujete, právě tehdy řídká. V mém vzorku jsem spároval spuštění stop-lossů s tickovými daty; mediánové plnění bylo 1.4 bps za spouštěcí cenou a 95. percentil 11 bps. U stop-lossu 10 bps vás krajní případy stojí dalších 10% rizika, které jste si mysleli, že máte vymezené.
Druhá chyba je nenápadnější a týká se konkrétně perpetual futures: která cena příkaz spouští. Binance ve výchozím nastavení spouští stop příkazy podle mark price; ta se počítá z indexu a vyhlazované báze, nikoli z posledního obchodu na dané burze. Vaše řada OHLC zachycuje poslední cenu. Jsou to různé řady a nejvíc se rozcházejí právě při událostech, které spouštějí stop-lossy.
| Poslední cena (vaše kline svíčky) | Mark price (výchozí cena spouštění) | |
|---|---|---|
| Zdroj | obchody na této burze | index několika burz + báze |
| Chování knotů | plný cenový výkyv | silně tlumený |
| Typický rozdíl | 1–3 bps v klidu, 20–35 bps v minutě s kaskádou | |
| Důsledek pro backtest | stop-lossy, které se spustily, ale neměly, a naopak | |
Knot dlouhý 25 bps v datech poslední ceny vás tedy v backtestu vyřadí, zatímco živá mark price se k vašemu spouštěcímu limitu 10 bps ani nepřiblížila. Nebo naopak v den, kdy se pohne index a vaše burza zaostává. Nastavíte-li workingType na CONTRACT_PRICE, alespoň sladíte živé chování s daty, což je pro výzkumníka obvykle správná volba. Poctivá simulace spouštění podle mark price totiž znamená vést druhou cenovou řadu celým enginem pro simulaci plnění.
Nejlépe si pamatuju tento případ: někdo od nás „vylepšil“ strategii posunutím take-profitu z 0.18% na 0.21%. Sharpe stoupl z 2.3 na 3.1. Žádná nová edge. Cíl se jen posunul mimo nejhustší část rozdělení knotů na 1minutových svíčkách, takže méně obchodů spadlo do nejednoznačné kategorie, v níž jim kód potichu přiznával výhru. Optimalizovali rozřešení shody.
Chybný postup č. 3: vždy předpokládat nejhorší a nazývat to konzervativním přístupem
První instinkt velí zvolit pesimistický přístup. Pokud jsou zasaženy obě úrovně, započítejte stop-loss. Hotovo, žádný další optimismus, můžeme nasadit.
Dřív jsem to tak dělal. Je to lepší než opačný přístup, ale pořád je to špatně, a to ze dvou důvodů.
Zlikviduje strategie, které jsou v pořádku. Pesimistické rozřešení u 12.6% obchodů ubralo této strategii 2.1 bodu Sharpe oproti hodnotě 0.94 při rozřešení podle tickových dat. Pokud je skutečná hodnota 0.94 a vaše konvence ukazuje 0.18, zahodíte nápad a pustíte se do něčeho horšího. Konzervativní odhad, který se liší o dva body Sharpe, není konzervativní přístup; je to šum s morálním postojem.
Ještě horší je, že to pokřiví optimalizaci. Když parametrickému průzkumu předáte pesimistické rozřešení shod, optimalizátor se naučí nejednoznačnostem vyhýbat, protože jsou teď čistou penalizací. Zamíří k širokým stop-lossům a blízkým cílům nebo k pomalým svíčkám, na kterých se obě úrovně vyskytují současně jen zřídka. Pak vám nabídne parametry vybrané podle vaší konvence plnění, nikoli podle trhu. Je to stejné selhání jako u příliš štědré varianty, jen s opačným znaménkem, a v tearsheetu je stejně neviditelné.
Pravidlo, kterým se řídíme jako prvním: pokud je stop_distance + target_distance menší než 75. percentil rozpětí ve vašem intervalu svíček, má předpoklad o pohybu uvnitř svíčky větší vliv na P&L než váš signál. Spočítejte obě hodnoty. Zabere to čtyři řádky kódu a ukončilo to víc debat o strategiích než jakákoli jiná jednotlivá kontrola.
Co skutečně funguje
Pohyb uvnitř svíčky je součást dat. Získejte je, nebo ohraničte to, co získat nemůžete.
- Rozhodujte podle nejjemnějších dostupných dat. Binance aggTrades pro příslušné minuty obsahují několik stovek řádků a dají jasnou odpověď: která úroveň byla zasažena první a za jakou cenu proběhlo plnění při průchodu cenou. Ticková data nepotřebujete pro celý backtest, stačí pro nejednoznačné svíčky. V mém vzorku šlo o 606 minut ze 129,600. To je malý soubor ke stažení, nikoli infrastrukturní projekt.
- Pokud ticková data nemáte, snižte interval o jednu nebo dvě úrovně, ale jen pro rozřešení. Signály počítejte na 15m svíčkách, výstupy rozřešte podle 1s nebo 1m svíček. Nejednoznačnost klesne ze 49% na zlomek procenta a zbytek je dost malý na to, abyste ho mohli poctivě zanedbat.
- Vždy uvádějte rozpětí výsledků. Každý backtest spusťte dvakrát, s optimistickým a pesimistickým rozřešením, a vedle výsledku s rozřešením podle dat vypište obě hodnoty Sharpe. Rozdíl představuje nejistotu způsobenou děním uvnitř svíčky a patří do tearsheetu vedle intervalu spolehlivosti samotné hodnoty Sharpe. Když je rozpětí 0.2–2.3, žádný závěr v jeho mezích není skutečně podložený.
- Sledujte míru nejednoznačných obchodů jako klíčovou metriku. U nás je na začátku každé karty strategie, vedle počtu obchodů a obratu. Míra nad přibližně 5% znamená, že testujete logiku výstupu, nikoli vstupu.
- Modelujte spouštěcí podmínku odděleně od plnění. Spouštějte příkaz podle cenové řady, kterou skutečně používá burza; plnění počítejte jako spouštěcí cenu plus skluz vylosovaný z rozdělení kalibrovaného podle tickových dat, nikoli za spouštěcí cenu.
Akcie mají stejný problém, jen v jiném hávu. Stop-loss na 62.00 u akcie, která přes noc otevře gapem na 58.40, se neplní na 62.00; plní se někde pod otevírací cenou. Backtest s denními svíčkami, který při průrazech gapem započítá skluz −$0.00, vám klidně oznámí, že overlay se stop-lossem snížil drawdown. Nesnížil. Jen se netestoval ve dnech, na kterých záleží. Totéž platí při pozastavení obchodování: stop-loss se skutečně vypořádá při znovuotevírací aukci za cenu, kterou minimum svíčky nikdy neukáže.
Nic z toho není exotické. Jde o pochopení, že svíčka je souhrn, zatímco strategie se stop-lossem a take-profitem sází na pořadí událostí, které tento souhrn zahodil. Až paper-trading engine konečně spustí strategii proti živým datům, cenová páska bude mít o jejich pořadí jasno. A nikdy ji nezajímalo, kterou větev příkazu if jste napsali jako první.
← Všechny články

