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.
Articles
O Negativo Honesto: Dezenas de Milhares de Backtests, Cinco Majors, Nenhuma Vantagem Robusta
O ponto culminante do arco de busca-e-overfitting, e ele termina em um resultado negativo — o correto. Uma busca de timeframe duplo em um único símbolo no ETHUSDT encontrou uma configuração que valia +16,35% out-of-sample e +2,62% em um holdout intocado; o Deflated Sharpe Ratio, considerando ~37.000 tentativas, deflacionou-o para 0,00. Uma passagem cross-instrument sobre cinco majors (ETH/BTC/SOL/BNB/XRP, ~1,18M de barras de 1m cada), selecionando pela mediana out-of-sample, o mata de vez: DSR duplo 0,24 / PBO 0,264, DSR triplo 0,14 / PBO 0,327 — ambos falham nos limiares. O campeão é lucrativo em 1 de 5 símbolos e negativo no restante. É para isso que serve o aparato anti-overfitting: para impedir você de embarcar o melhor do ruído como alfa.
Provando a Ausência de Look-Ahead em Backtests Multi-Timeframe: Perturbe o Futuro, Prove que o Passado Não Pode Vê-lo
Backtests multi-timeframe vazam o futuro através de uma barra de timeframe superior ainda em formação, cujo fechamento final ainda não existe. Não se chega à confiança por revisão de código — é preciso testar. Reproduzimos exatamente a regra de barra fechada do bot ao vivo e depois provamos a ausência de vazamento com uma sonda de futuro deslocado: perturbamos cada barra futura e verificamos que todo sinal e trade passado permanece bit a bit inalterado. 25/25 verificações de paridade, e a sonda tem dentes.
Quando a GPU Compensa: O Roofline do Sweep de Parâmetros, Onde um 167x de Manchete É na Verdade 27x de Algoritmo Vezes 6.2x de Hardware
A vantagem da GPU sobre a CPU cresce com o tamanho do batch — de 54.5x com um combo por chamada até 359.6x com 61 na nossa pré-computação de indicadores multi-timeframe — porque um sweep pequeno não consegue amortizar o overhead de lançamento de kernel e de transferência. Decompomos um 167x de manchete em uma vitória algorítmica de 27x que também ajuda a CPU e uma vitória de hardware de 6.2x, mostramos que a vantagem verdadeira GPU-vs-melhor-CPU é de apenas 3.2x em single-timeframe e 6.2x em multi, e damos um guia de decisão sobre quão largo um sweep precisa ser antes que valha a pena apostar em uma GPU.
A Armadilha de Precisão da GPU: Como um Backtest em fp32 na Apple Metal Retorna Lixo Silenciosamente
A GPU Metal da Apple não tem float64. Portar um backtest vetorizado para ela de forma ingênua faz a tentadora WMA por soma de prefixos estourar o fp32 — erro relativo máximo de 211× — mas ainda assim ele roda e devolve números com aparência plausível. A correção não é mais precisão; é uma formulação diferente: uma convolução direta por janela, segura em fp32 até 8×10⁻⁷ e 55.9× mais rápida que o numba de thread única. A armadilha, a aritmética por trás dela, e como provar que você não caiu nela.
O Portão de Fidelidade: o Backtest do Grosseiro ao Fino Engana Você Mais Rápido, a Menos que o Proxy Barato Classifique Como o Caro
A busca drill-down / multi-fidelidade (ASHA, eliminação sucessiva, Hyperband) filtra milhares de configs de forma barata e promove apenas os sobreviventes para a avaliação completa e cara. É um ganho de velocidade genuíno — mas colapsa silenciosamente se a classificação de baixa fidelidade discordar da de alta fidelidade. Medimos a correlação de ranking por dobra: em uma dobra, o ρ de Spearman pode ser 0.03 (classifica quase aleatoriamente), subindo para 0.43, 0.67, 0.78, 0.91 à medida que as dobras se acumulam. A correção é um portão obrigatório — meça ρ(barato, completo) primeiro, e eleve automaticamente a fidelidade mínima para o primeiro degrau em que ρ ≥ 0.5.
Busca Aleatória vs. Busca Inteligente: o Cruzamento é o Custo de Avaliação, Não o Algoritmo
Quando um backtest é barato, o Sobol embaralhado e burro vence em throughput bruto — samplers inteligentes (TPE, CMA-ES, ASHA) pagam uma taxa de ask/tell em Python que os derruba em 20x, fazendo com que avaliem muito menos pontos no mesmo tempo de relógio e percam. Torne cada avaliação cara (multi-TF + folds de walk-forward) e o cruzamento se inverte. Medimos os dois regimes, e por que a fidelidade de rank por fold (ρ@1 subindo de 0.03→0.43) é a pré-condição para que o pruning valha a pena.
O espaço de parâmetros de dois eixos: por que a maior parte do seu sweep deveria ser quase gratuita
Nem todos os parâmetros custam o mesmo para pesquisar. Os parâmetros de uma estratégia dividem-se num eixo caro (indicadores — recalculados sobre toda a série) e num eixo barato (limiares de decisão — uma passagem O(n) sobre sinais pré-calculados). Como os indicadores são invariantes aos limiares, calculam-se uma vez e percorrem-se milhares de configurações de limiares a ~5.600 cfg/s — cerca de 1.600 vezes mais barato do que recalcular por configuração. Uma reavaliação do custo da maldição da dimensionalidade.
O imposto do framework: quando sua biblioteca de backtest é mais lenta que um loop ingênuo de pandas
Comparamos oito motores de backtest em uma mesma varredura de parâmetros idêntica — 150k barras, 80 combinações de cruzamento de HMA, com a paridade de número de operações travada em 2707. Dois dos frameworks orientados a eventos mais populares ficaram mais lentos que um loop de pandas escrito à mão, enquanto um motor vetorizado/compilado rodou o mesmo trabalho cerca de 13,000× mais rápido. Um estudo sobre a sobrecarga por barra que as bibliotecas populares nunca foram feitas para amortizar.
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.