Testujeme, abyste nemuseli · č. 3
Proč tvůj backtest lže: placebo test za 40 řádků
Každý backtest, který ti kdy někdo ukázal, byl ziskový — jinak by ti ho neukazoval. Většina z nich přitom neměřila strategii, ale štěstí a bull trh. Tohle je nejlevnější detektor sebeklamu, jaký známe: 300 náhodných dvojníků tvé strategie. Kód přiložen, funguje, otestovali jsme jím rok vlastní práce.
Znáš to: histogram zisků, křivka rostoucí doprava nahoru, „strategie porazila buy&hold o 30 %". Vypadá to jako důkaz. Jenže backtest umí lhát mnoha způsoby najednou — a ten nejzákeřnější nevyžaduje žádnou chybu v kódu. Stačí, že sis z mnoha nápadů vybral ten, který na minulosti vyšel. My jsme si těmi lžemi prošli všemi. Za rok testování nám „krásné" výsledky ukázalo šest strategií — a placebo test s OOS bránou jich dvanáct ze třinácti popravily dřív, než stály jedinou korunu.
§ 1
Tři lži, které backtest říká nejraději
- Výběr zpětným zrcátkem. Otestuješ 50 nápadů, ukážeš (i sobě) ten nejlepší. Vítěz z 50 náhodných pokusů vypadá vždycky geniálně — přesně tak nás napálil grid bot: nejlepší z 48 kombinací +13,8 % ročně, tatáž kombinace na neviděných datech −13,8 %.
- Expozice vydávaná za um. Long-only strategie v rostoucím trhu vydělá skoro vždycky — ne proto, že umí časovat, ale proto, že drží. „Porazil jsem buy&hold" často znamená jen „měl jsem menší expozici v propadu".
- Obyčejné štěstí. Pár desítek obchodů je malý vzorek. Náhoda v něm umí vyrobit +30 % stejně snadno jako −30 %.
Na první lež je lék out-of-sample test (vybírej na jedné části dat, suď na druhé). Na druhé dvě je lék placebo.
§ 2
Placebo: 300 náhodných dvojníků
Myšlenka je stejná jako v medicíně. Účinek léku neměříš proti „nic", ale proti cukrové pilulce. Účinek strategie neměř proti buy&hold, ale proti strategii, která dělá totéž co ta tvoje — jen náhodně.
Dvojník zachová všechno, co není signál: stejný trh, stejný počet obchodů, stejné délky držení. Jediné, co se změní, jsou časy vstupů (náhodné) a směr (mince). Vyrobíš 300 takových dvojníků a dostaneš rozdělení: „kolik na tomhle trhu s touhle aktivitou vydělá čistá náhoda". Tvoje strategie musí porazit 95. percentil toho rozdělení. Jinak neměříš informaci — měříš šum.
Obr. 1 · ilustrační schéma
Kde ve výsledcích náhody leží tvoje strategie?
§ 3
Kód
Žádný framework, jen numpy. Vstup: pole zavíracích cen a obchody tvé strategie jako (index_vstupu, index_výstupu, směr):
import numpy as np
def placebo_test(closes, trades, reps=300, seed=42, long_only=False):
"""Random-entry placebo: porazila by strategie 300 náhodných dvojníků?
closes : pole zavíracích cen (1 svíčka = 1 krok)
trades : obchody strategie [(entry_idx, exit_idx, side)], side +1/-1
Vrací (průměrný výnos strategie, p95 náhody, podíl placebů >= strategie).
"""
closes = np.asarray(closes, dtype=float)
rets = [s * (closes[x] / closes[e] - 1.0) for e, x, s in trades]
real = float(np.mean(rets))
holds = np.array([x - e for e, x, _ in trades]) # držení v barech
n, rng = len(trades), np.random.default_rng(seed)
placebo = np.empty(reps)
for r in range(reps):
entries = rng.integers(0, len(closes) - holds.max() - 1, size=n)
exits = entries + rng.permutation(holds) # stejná držení, jiné časy
sides = np.ones(n) if long_only else rng.choice((-1.0, 1.0), size=n)
placebo[r] = np.mean(sides * (closes[exits] / closes[entries] - 1.0))
p95 = float(np.quantile(placebo, 0.95))
return real, p95, float((placebo >= real).mean())
# použití:
real, p95, frac = placebo_test(closes, trades, long_only=True)
print(f"strategie {real*1e4:+.1f} bp/obchod | p95 náhody {p95*1e4:+.1f} bp"
f" | {'PROŠLA' if real > p95 else 'NEPROŠLA'}"
f" ({frac:.0%} dvojníků bylo lepších)")
Sanity check, který jsme spustili před publikací: náhodná strategie na náhodné procházce neprošla (−10,6 bp vs p95 +80,6 bp; 60 % dvojníků bylo lepších) a podvodník, který zná budoucnost, prošel s přehledem (+525 bp, 0 % dvojníků lepších). Test měří přesně to, co má.
§ 4
Nejdůležitější přepínač: long_only
Tady padá nejvíc dip-buying strategií. Když tvoje strategie jen nakupuje, dvojníci musí taky jen nakupovat. Jinak srovnáváš „long v bull trhu" proti „mince hází long/short" — a lichotíš si.
V našem sanity checku porazily náhodné long-only vstupy v rostoucím trhu ±placebo… a proti long-only placebu neprošly.
Stejný mechanismus zabil případ 010: kupování dipů na 256 coinech „porazilo buy&hold" v desítkách případů — proti long-only placebu prošlo 23/256 (čekali bychom ~13 náhodou) a na majorech 0/14. Iluze nižší expozice, ne edge.
§ 5
Placebo v akci: rok našich testů
| kandidát | porazil placebo? | verdikt |
|---|---|---|
| Kupování dipů (majoři) | NE — 0/14 | NO-GO |
| Trend-following 12m (ETF koš) | NE — Sharpe 0,75 vs p95 0,77 | NO-GO |
| Vol-targeting na kryptu | NE — 0/3 aktiva | NO-GO |
| Order-flow / L2 mikrostruktura | ANO — o desítky sigma | přesto NO-GO |
Poslední řádek je klíčový: order-flow signál porazil placebo naprosto drtivě — a stejně neprošel, protože gross 1 bp na obchod nezaplatí 36 bp nákladů. Placebo je brána nutná, ne postačující. Odhalí šum a expozici; náklady a lookahead musí hlídat další testy.
§ 6
Checklist, než uvěříš backtestu
- Prošel placebo testem proti p95 — se správným long_only nastavením?
- Prošel out-of-sample: parametry vybrané na jednom období, souzené na jiném — v obou polovinách dat?
- Počítá skutečné náklady (poplatky, spread, u páky funding a likvidace)?
- Jsou obchody nepřekrývající se a je jich dost (stovky, ne desítky)?
- Kolik nápadů jsi zahodil, než vyšel tenhle? (Odpověď „hodně" = přísnější laťka.)
Metodika v kostce
Test: random-entry placebo — 300 dvojníků se stejným počtem obchodů a stejnými délkami držení (permutace), náhodné časy vstupů, směr mincí (nebo long-only), brána = 95. percentil.
Ověření kódu: náhodná strategie na náhodné procházce neprošla (60 % dvojníků lepších); lookahead „podvodník" prošel (+525 bp, 0 %); long-only náhoda v bull trhu prošla proti ±placebu a neprošla proti long-only placebu — přesně dle očekávání.
Limity: nechytí lookahead bias ani náklady (na to OOS split + fee model); při překrývajících se obchodech podhodnocuje rozptyl.
Testujeme, abyste nemuseli — série poctivých pitev obchodních strategií. Č. 1: Edge existuje. Jen na něj nedosáhnete. · Č. 2: Grid bot sliboval 8–15 % měsíčně.
Kód v článku je volně k použití (MIT). Nejde o investiční doporučení.