Eugen Soloviov
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.
Artikelen
Het Eerlijke Negatieve Resultaat: Tienduizenden Backtests, Vijf Grote Munten, Geen Robuuste Edge
Het sluitstuk van de zoek-en-overfit-boog, en het eindigt in een negatief resultaat — het juiste. Een single-symbol dual-timeframe-zoektocht op ETHUSDT vond een configuratie ter waarde van +16.35% out-of-sample en +2.62% op een ongebruikte holdout; de Deflated Sharpe Ratio, rekening houdend met ~37,000 trials, deflateerde dit tot 0.00. Een cross-instrument-doorloop over vijf grote munten (ETH/BTC/SOL/BNB/XRP, elk ~1.18M 1m-bars), selecterend op mediaan out-of-sample, maakt er definitief korte metten mee: dual DSR 0.24 / PBO 0.264, triple DSR 0.14 / PBO 0.327 — beide falen op de gates. De kampioen is winstgevend op 1 van de 5 symbolen en negatief op de rest. Hier is het anti-overfitting-apparaat voor bedoeld: om te voorkomen dat je de beste van de ruis als alpha shipt.
Bewijzen dat multi-timeframe backtests geen look-ahead vertonen: verstoor de toekomst, bewijs dat het verleden de toekomst niet kan zien
Multi-timeframe backtests lekken de toekomst door een nog vormende higher-timeframe bar waarvan de uiteindelijke close nog niet bestaat. Je kunt niet via code review naar vertrouwen toe redeneren — je moet het testen. We reproduceren de closed-bar regel van de live bot exact, en bewijzen vervolgens de afwezigheid van lekkage met een shifted-future probe: verstoor elke toekomstige bar en toon aan dat elk signaal en elke trade uit het verleden bitwise ongewijzigd blijft. 25/25 parity checks, en de probe heeft tanden.
Wanneer de GPU loont: de parameter-sweep-roofline, waar een headline van 167x in werkelijkheid 27x algoritme maal 6.2x hardware is
De voorsprong van de GPU op de CPU groeit met de batchgrootte — van 54.5x bij een combo per call tot 359.6x bij 61 op onze multi-timeframe indicator-precompute — omdat een kleine sweep de kernel-launch- en transfer-overhead niet kan amortiseren. We ontleden een headline van 167x in een algoritmische winst van 27x die ook de CPU helpt en een hardwarewinst van 6.2x, laten zien dat de echte voorsprong van de GPU op de beste CPU slechts 3.2x is bij single-timeframe en 6.2x bij multi, en geven een beslisgids voor hoe breed een sweep moet zijn voordat een GPU de aanschaf waard is.
De GPU-precisievalstrik: Hoe een fp32-backtest op Apple Metal stilletjes onzin teruggeeft
Apple's Metal-GPU heeft geen float64. Zet er naïef een gevectoriseerde backtest naartoe over en de verleidelijke prefixsom-WMA loopt over fp32 heen — maximale relatieve fout 211× — en toch draait hij nog steeds en geeft plausibel ogende getallen terug. De oplossing is niet meer precisie; het is een andere formulering: een directe gevensterde convolutie, fp32-veilig tot 8×10⁻⁷ en 55.9× sneller dan single-thread numba. De valstrik, de rekenkunde, en hoe je bewijst dat je er niet in getrapt bent.
De Fidelity Gate: Grof-naar-Fijn Backtesten Bedriegt Je Sneller Tenzij de Goedkope Proxy Net Zo Rangschikt als de Dure
Drill-down / multi-fidelity zoeken (ASHA, successive halving, Hyperband) screent duizenden configuraties goedkoop en promoveert alleen overlevenden naar de dure volledige evaluatie. Het is een echte snelheidswinst — maar hij stort stilletjes in als de low-fidelity-rangschikking niet overeenkomt met de high-fidelity-rangschikking. We maten de fold-rangcorrelatie: bij één fold kan Spearman ρ 0.03 zijn (rangschikt bijna willekeurig), oplopend naar 0.43, 0.67, 0.78, 0.91 naarmate folds zich opstapelen. De oplossing is één verplichte poort — meet eerst ρ(goedkoop, volledig), en verhoog automatisch de minimale fidelity naar de eerste trede waar ρ ≥ 0.5.
Random vs Smart Search: De Crossover Zit in de Eval-kosten, Niet in het Algoritme
Als één backtest goedkoop is, wint domme scrambled Sobol op pure doorvoersnelheid — slimme samplers (TPE, CMA-ES, ASHA) betalen een Python ask/tell-belasting die ze 20x vertraagt, waardoor ze bij gelijke wall-clock veel minder punten evalueren en verliezen. Maak elke eval duur (multi-TF + walk-forward-folds) en de crossover keert om. We hebben beide regimes gemeten, en waarom fold-rank-fidelity (ρ@1 stijgend van 0.03→0.43) de voorwaarde is waaraan voldaan moet zijn wil pruning zich uitbetalen.
De parameterruimte met twee assen: waarom het grootste deel van je sweep bijna gratis zou moeten zijn
Niet alle parameters kosten evenveel om te doorzoeken. De parameters van een strategie splitsen zich in een dure as (indicatoren — herberekend over de hele reeks) en een goedkope as (beslissingsdrempels — een O(n)-pass over vooraf berekende signalen). Omdat indicatoren invariant zijn ten opzichte van drempels, bereken je ze eenmalig en sweep je duizenden drempelconfiguraties met ~5.600 cfg/s — ruwweg 1.600x goedkoper dan per configuratie herberekenen. Een herprijzing van de vloek van de dimensionaliteit.
De framework-belasting: wanneer je backtestbibliotheek trager is dan een naïeve pandas-loop
We hebben acht backtest-engines gebenchmarkt op één identieke parameter-sweep — 150k bars, 80 HMA-cross-combinaties, trade-count-pariteit vastgezet op 2707. Twee van de populairste event-driven frameworks kwamen trager uit dan een met de hand geschreven pandas-loop, terwijl een gevectoriseerde/gecompileerde engine hetzelfde werk ~13,000× sneller draaide. Een studie van de per-bar overhead die populaire bibliotheken nooit gebouwd waren om te amortiseren.
The Probability of Backtest Overfitting: Did Your Search Beat a Coin Flip?
The Deflated Sharpe Ratio prices the winning strategy; PBO prices the search that picked it. Combinatorially Symmetric Cross-Validation runs C(16,8) = 12,870 train/test splits over a 1000x200 performance matrix and asks: does the in-sample winner land in the bottom half out of sample? The catch almost everyone misses — PBO's null is 0.5, not 1. On 200 zero-edge strategies the best in-sample annualized Sharpe of 1.98 collapses to 0.06 out of sample and PBO = 0.476: a coin flip, fully overfit. Plant a real edge (annualized Sharpe 2.38) and PBO drops to 0.001, the in-sample 3.73 surviving to an out-of-sample 2.34. A moving-average grid on a pure random walk has no out-of-sample skill either — PBO 0.463 averaged over 60 matrices, statistically indistinguishable from the null — and on one representative matrix the mirage is vivid: a best in-sample Sharpe of 2.33 collapses to a median out-of-sample -0.22, PBO 0.573, a 63% chance of a loss.
The IPC Tax: Put the Backtest Engine Behind a Socket and Lose 13% — Almost None of It to the Socket
We ported a numba backtest kernel line-for-line to Rust and called it across a process boundary four ways, with an equivalence gate confirming identical PnL to the last trade. Shipping the entire 1.2 MB price series through a Unix socket costs ~2 ms — about 0.1% of the job. JSON-encoding the same payload costs 1348x more than raw bytes, chatty per-combo calls re-ship the data 80 times, and a per-bar call pattern would pay 2.1 s of pure IPC on a 2.0 s job. The boundary is cheap; the tax is in how you cross it.
The Deflated Sharpe Ratio: How Many of Your Backtest 'Winners' Survive Multiple Testing?
A parameter search is a machine for manufacturing luck. On pure noise — 1,000 strategies with zero true edge — the best annual Sharpe averages 1.63 and the naive significance test flags a discovery 100% of the time. We build controlled ground truth and show that the Deflated Sharpe Ratio, the Harvey-Liu haircut, and White's Reality Check restore honesty: false discoveries drop from 1.000 to 0.001-0.057, genuine edges above the noise ceiling are kept with power ~1 — and one real trap (correlated grids) where the raw DSR over-deflates and the verdict must be read across a whole band of effective-trial estimates, not one.
Objective-Function Design: The Metric You Optimize Secretly Picks Your Strategy
To search for the 'best' strategy you must first define 'best' — and that scalar silently chooses the winner. On synthetic data with a known edge (600 seeds, T=2000, 80 thresholds), a naive per-trade Sharpe crowns a lottery: it picks a sub-5%-exposure winner in 56% of seeds and degenerates in 57% — on the starkest seed, 8 trades posting an in-sample Sharpe of 21.09 that collapses to 0.13 out of sample. The honest repair is almost dull: measure on the full timeline, which never degenerates (out-of-sample 1.71). A trade-count (conf_k) shrinkage and an exposure floor can retrofit a per-trade metric, but even fully repaired they only match full-timeline Sharpe (1.70 vs 1.71) — never beat it. Goodhart's law, in a backtest, with controlled ground truth.