High-Performance Backtest Engines
How to build a backtest engine that runs hundreds of times faster without changing a single PnL number - data layout, caching, adaptive resolution, and architecture, from first speedups to production internals.
Polars vs. Pandas für Algotrading: Benchmarks mit echten Daten
Detaillierter Vergleich von Polars und Pandas bei Algotrading-Aufgaben: Benchmarks für Filterung, Aggregation, Rolling-Signalberechnungen, I/O und Speicherverbrauch. Hybride Polars + Numba-Architektur für maximale Backtest-Performance.
VectorBT: The Fastest Backtesting Framework for Python
Overview of VectorBT - an innovative quantitative analysis library that changes the approach to backtesting thanks to the power of NumPy and Numba.
Die Backtest-Geschwindigkeitsleiter: 298x auf einer Laptop-CPU, identischer PnL bis zum letzten Trade
Fünf Implementierungen desselben Parameter-Sweeps über 80 Kombinationen, alle nachweislich mit identischem PnL: pandas rolling.apply braucht 69,9 Sekunden, numpy 3,1, numba 2,0, paralleles numba 0,23 - eine gemessene 298-fache Beschleunigung auf einem Apple M2 Max ohne jede Hardware-Änderung und immer noch ~13x gegenüber einer soliden vektorisierten Basislinie. Was jede Stufe bringt, warum eine GPU nicht das fehlende Teil ist und wo der eigentliche Engpass der massenhaften Parametersuche liegt.
Die Framework-Steuer: Wenn deine Backtest-Bibliothek langsamer ist als eine naive Pandas-Schleife
Wir haben acht Backtest-Engines auf einem einzigen identischen Parameter-Sweep gemessen - 150k Bars, 80 HMA-Cross-Kombinationen, mit auf 2707 fixierter Trade-Anzahl-Parität. Zwei der beliebtesten ereignisgesteuerten Frameworks liefen langsamer als eine handgeschriebene Pandas-Schleife, während eine vektorisierte/kompilierte Engine dieselbe Arbeit rund 13.000× schneller erledigte. Eine Untersuchung des Overheads pro Bar, den beliebte Bibliotheken nie amortisieren sollten.
Aggregierter Parquet-Cache: Wie man Multi-Timeframe-Backtests um das Hundertfache beschleunigt
Wie man Timeframes und Indikatoren aus Minutenkerzen vorberechnet, sie in Parquet speichert und für Massentests von Strategien nutzt, ohne redundante Neuberechnungen.
Der zweiachsige Parameterraum: Warum der Großteil Ihres Sweeps nahezu kostenlos sein sollte
Nicht jeder Parameter kostet gleich viel bei der Suche. Die Parameter einer Strategie teilen sich auf in eine teure Achse (Indikatoren - über die gesamte Zeitreihe neu berechnet) und eine billige Achse (Entscheidungsschwellen - ein O(n)-Durchlauf über vorberechnete Signale). Weil Indikatoren gegenüber Schwellen invariant sind, berechnen Sie sie einmal und durchlaufen Tausende von Schwellenkonfigurationen mit ~5.600 cfg/s - etwa 1.600-mal billiger als eine Neuberechnung pro Konfiguration. Eine Neubewertung des Fluchs der Dimensionalität.
Adaptives Drill-Down: Backtest mit variabler Granularität von Minuten bis zu einzelnen Trades
Wie adaptive Datengranularität Backtests beschleunigt und Speicher spart: Drill-down von 1m auf 1s, 100ms und Roh-Trades nur dort, wo sich der Preis deutlich bewegt hat oder das Volumen ausschlug, nicht über die gesamte historische Zeitreihe.
Das Fidelity-Gate: Grob-zu-fein-Backtesting täuscht dich schneller - es sei denn, der billige Proxy rankt genauso wie die teure Auswertung
Drill-Down- / Multi-Fidelity-Suche (ASHA, Sukzessive Halbierung, Hyperband) screent Tausende Konfigurationen billig und befördert nur die Überlebenden zur teuren vollständigen Auswertung. Das ist eine echte Beschleunigung - aber sie bricht lautlos zusammen, wenn das Low-Fidelity-Ranking dem High-Fidelity-Ranking widerspricht. Wir haben die Fold-Rangkorrelation gemessen: Bei einem Fold kann Spearman ρ bei 0.03 liegen (rankt fast zufällig), steigend auf 0.43, 0.67, 0.78, 0.91, je mehr Folds hinzukommen. Die Lösung ist ein verpflichtendes Gate - zuerst ρ(billig, voll) messen und die Mindest-Fidelity automatisch auf die erste Stufe anheben, bei der ρ ≥ 0.5 gilt.
Random Search vs. intelligente Suche: Der Crossover liegt an den Eval-Kosten, nicht am Algorithmus
Wenn ein Backtest billig ist, gewinnt dummes, verwürfeltes Sobol beim reinen Durchsatz - intelligente Sampler (TPE, CMA-ES, ASHA) zahlen eine Python-Ask/Tell-Steuer, die sie um das 20-fache ausbremst, sodass sie bei gleicher Wall-Clock-Zeit weit weniger Punkte auswerten und verlieren. Macht man jede Auswertung teuer (Multi-TF + Walk-Forward-Folds), kippt der Crossover. Wir haben beide Regime gemessen - und warum Fold-Rang-Fidelity (ρ@1 steigt von 0.03 auf 0.43) die Voraussetzung dafür ist, dass sich Pruning überhaupt auszahlt.
Koordinatenabstieg vs. Bayessche Optimierung: Wer findet die besseren Parameter
Warum eine erschöpfende Suche bei 12+ Parametern unmöglich ist, wie der Koordinatenabstieg Wechselwirkungen übersieht und wie Optuna mit einem TPE-Sampler in 500 Iterationen findet, was OAT in 96 nicht finden kann. Praktische Codebeispiele, Sampler-Vergleich und Multi-Objective-Optimierung.
Die GPU-Präzisionsfalle: Wie ein fp32-Backtest auf Apple Metal lautlos Datenmüll zurückgibt
Apples Metal-GPU kennt kein float64. Portiert man einen vektorisierten Backtest naiv darauf, läuft die verlockende Prefix-Sum-WMA in einen fp32-Overflow - maximaler relativer Fehler 211× - und trotzdem läuft sie durch und liefert plausibel aussehende Zahlen. Die Lösung ist nicht mehr Präzision, sondern eine andere Formulierung: eine direkte Fenster-Faltung, fp32-sicher bis auf 8×10⁻⁷ und 55,9× schneller als Single-Thread-Numba. Die Falle, die Arithmetik dahinter, und wie man beweist, dass man nicht hineingetappt ist.
Wann sich die GPU lohnt: Die Parameter-Sweep-Roofline, wo eine 167x-Schlagzeile in Wahrheit 27x Algorithmus mal 6.2x Hardware ist
Der Vorsprung der GPU vor der CPU wächst mit der Batch-Größe - von 54.5x bei einer Kombination pro Aufruf bis 359.6x bei 61 auf unserem Multi-Timeframe-Indikator-Precompute - weil ein kleiner Sweep den Kernel-Launch- und Transfer-Overhead nicht amortisieren kann. Wir zerlegen eine 167x-Schlagzeile in einen algorithmischen 27x-Gewinn, der auch der CPU hilft, und einen 6.2x-Hardware-Gewinn, zeigen, dass der wahre Vorsprung GPU vs. beste CPU nur 3.2x single-timeframe und 6.2x multi beträgt, und geben einen Entscheidungsleitfaden, wie breit ein Sweep sein muss, bevor sich der Kauf einer GPU lohnt.
Die IPC-Steuer: Die Backtest-Engine hinter einen Socket stellen und 13% verlieren - fast nichts davon geht auf den Socket
Wir haben einen numba-Backtest-Kernel Zeile für Zeile nach Rust portiert und ihn auf vier Arten über eine Prozessgrenze hinweg aufgerufen, mit einem Äquivalenz-Gate, das identisches PnL bis zum letzten Trade bestätigt. Das Versenden der gesamten 1,2-MB-Preisreihe über einen Unix-Socket kostet ~2 ms - etwa 0,1% des Jobs. JSON-Kodierung derselben Payload kostet 1348x mehr als rohe Bytes, geschwätzige Aufrufe pro Kombination verschicken die Daten 80 Mal erneut, und ein Aufrufmuster pro Bar würde 2,1 s reine IPC bei einem 2,0-s-Job kosten. Die Grenze ist billig; die Steuer liegt darin, wie man sie überquert.