4. září 2026 · zpětné testování

Stop-loss i take-profit byly ve stejné svíčce. Který z nich vybral váš backtest?

Stop-loss i take-profit byly ve stejné svíčce. Který z nich vybral váš backtest?

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.

12.6%obchodů zasáhlo obě úrovně v jedné svíčce
2.31Sharpe, take-profit se vyhodnocuje první
0.18Sharpe, stop-loss se vyhodnocuje první
0.94Sharpe, rozřešení na 1sekundových svíčkách

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íčkyObchody s oběma úrovněmi uvnitř jedné svíčkySharpe (take-profit první)
1s0.3%0.91
1m12.6%2.31
5m34%3.60
15m49%4.42
1h71%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í)
Zdrojobchody na této burzeindex několika burz + báze
Chování knotůplný cenový výkyvsilně tlumený
Typický rozdíl1–3 bps v klidu, 20–35 bps v minutě s kaskádou
Důsledek pro backteststop-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.

  1. 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.
  2. 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.
  3. 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ý.
  4. 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.
  5. 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í.

plnění uvnitř svíčkystop příkazyzpětné testováníkrypto futuresmikrostruktura trhu
← Všechny články