Numba JIT für Backtests: Python-Speed in C-Geschwindigkeit.

Manche Backtest-Logiken lassen sich einfach nicht vektorisieren. Stop-Loss-Logik mit Trailing-Stop, Order-Queue-Simulation, Event-Driven-Loops — alles Code, der natürlich als Schleife geschrieben wird. Numba macht aus diesen Schleifen kompilierten Maschinencode, mit einer einzigen Zeile Decorator. Faktor 50–200 ist Standard.

Was Numba ist und wie es funktioniert.

Numba ist ein Just-In-Time-Compiler für Python, der auf LLVM aufsetzt. Sie dekorieren eine Funktion mit @njit, und beim ersten Aufruf wird sie zu nativem Maschinencode kompiliert. Folgende Aufrufe laufen ohne Python-Interpreter — die Schleife läuft im Tempo von handgeschriebenem C.

Der Trick: Numba unterstützt nur eine Untermenge von Python — vor allem NumPy-Arrays und numerische Typen. Pandas-DataFrames, dicts, Strings funktionieren entweder gar nicht oder nur eingeschränkt. Für Trading-Backtests ist das selten ein Problem, weil die heißen Schleifen meist auf NumPy-Arrays arbeiten.

Erstes Beispiel: Trailing-Stop-Simulation.

Klassischer Fall, den man nicht sauber vektorisieren kann: ein Trailing-Stop, der dem höchsten Preis seit Entry folgt und auslöst, sobald der Preis um X % fällt.

import numpy as np
from numba import njit

@njit(cache=True)
def trailing_stop_backtest(prices, entries, stop_pct=0.02):
    n = len(prices)
    position = 0
    entry_price = 0.0
    peak = 0.0
    pnl = np.zeros(n)
    cum = 0.0
    for i in range(n):
        price = prices[i]
        if position == 0 and entries[i]:
            position = 1
            entry_price = price
            peak = price
        elif position == 1:
            if price > peak:
                peak = price
            if price < peak * (1 - stop_pct):
                # Exit
                cum += (price - entry_price) / entry_price
                position = 0
        pnl[i] = cum
    return pnl

Auf einer Million Bars läuft diese Funktion in unter 100 Millisekunden — ohne Decorator wären es 30 bis 60 Sekunden. Faktor 300 bis 600, ohne die Logik umzuschreiben.

Wann sich Numba lohnt.

Die Faustregel: wenn Sie eine Schleife haben, die nicht vektorisierbar ist (weil jeder Schritt vom vorherigen abhängt) und die mit nur numerischen Daten arbeitet, ist Numba die richtige Wahl. Typische Fälle im Trading:

Wo Numba nicht funktioniert.

Numba unterstützt nicht alles. Stolperfallen aus der Praxis:

Parallelisierung mit prange.

Numba kann Schleifen automatisch parallelisieren — auf alle Kerne. Voraussetzung: keine Datenabhängigkeiten zwischen den Iterationen. Ein klassischer Anwendungsfall ist ein Parameter-Sweep, bei dem jede Kombination unabhängig getestet wird.

import numpy as np
from numba import njit, prange

@njit(parallel=True, cache=True)
def parameter_sweep(prices, fast_periods, slow_periods):
    n_fast = len(fast_periods)
    n_slow = len(slow_periods)
    sharpe = np.zeros((n_fast, n_slow))
    for i in prange(n_fast):
        for j in range(n_slow):
            fast = fast_periods[i]
            slow = slow_periods[j]
            if fast >= slow:
                continue
            sharpe[i, j] = run_strategy(prices, fast, slow)
    return sharpe

@njit(cache=True)
def run_strategy(prices, fast, slow):
    # ... Single-Combo-Backtest
    return 1.5  # Dummy

Bei 8 Kernen erwartet man Faktor 6–7 Speedup — die fehlenden zwei Punkte gehen für Cache-Effekte und Overhead drauf. Trotzdem: Ein Parameter-Sweep, der seriell 20 Minuten lief, ist parallel in 3 Minuten durch.

Numba vs Alternativen.

Numba ist nicht der einzige Weg, Python schneller zu machen. Wer schon Polars benutzt, hat für vektorisierbaren Code oft eine bessere Lösung. Cython gibt mehr Kontrolle, ist aber deutlich aufwendiger im Setup. Rust-Bindings (über pyo3) sind für maximale Performance ideal, aber überdimensioniert für die meisten Backtest- Workloads.

Mein Stack: Pandas/Polars für Datenvorbereitung und vektorisierbare Indikatoren, Numba für die unvektorisierbaren Schleifen, Rust nur dort, wo Numba an Grenzen stößt — was selten passiert.

Tipps für robusten Numba-Code.

Typisches Beispiel.

Ein typisches Szenario: Ein Backtest mit bar-by-bar Option-Pricing-Simulation und Greek-Berechnung läuft pro Marktdaten-Tag Stunden — naturgemäß nicht vektorisierbar, weil jeder Hedge vom vorherigen Bestand abhängt.

Mit Numba inkl. prange über die Underlying-Pfade lässt sich die Laufzeit oft um mehr als eine Größenordnung senken — der Unterschied zwischen „ein Test pro Tag“ und vielen Tests pro Stunde. Diese Iterationsgeschwindigkeit verändert die gesamte Strategie-Entwicklung.

Fazit.

Numba ist das beste Werkzeug in der Python-Welt, wenn Sie unvektorisierbare Trading-Logik schnell machen wollen. Ein Decorator, manchmal eine Typdeklaration — und Sie sind bei C-Speed, ohne C zu schreiben. Wer Backtests baut und Numba nicht kennt, verschenkt Stunden pro Woche. Wer einmal damit gearbeitet hat, will nicht mehr zurück.

Stand: Mai 2026, überarbeitet Oktober 2026. Angaben zu Produkten, Preisen, Gesetzen und Fristen können sich seitdem geändert haben; maßgeblich sind die aktuellen Angaben der Anbieter und Behörden.

Ihr Backtest läuft Stunden und Sie wissen, dass die heiße Schleife das Problem ist? Unverbindlich anfragen — wir bringen den richtigen Code in den richtigen JIT. Mehr zu meinem Angebot: Trading-Systeme entwickeln lassen.