Hoe gebruik je de 'Sharpe Ratio' als fitness-functie in je algoritme?
Je hebt een algoritme. Je hebt data. Je hebt een broker API.
Maar wat is echt goed? Hoe weet je of je strategie overleeft als de markt omslaat? De Sharpe Ratio is je antwoord.
Het is de ultieme fitness-functie voor je trading bot. Het zegt niet alleen hoeveel winst je maakt, maar vooral hoeveel pijn je onderweg voelde.
Laten we hem inbouwen.
Wat je nodig hebt voordat je begint
Zorg dat je stack klopt. Je hebt geen exotische tools nodig, maar de basis moet rock-solid zijn.
Denk aan een moderne laptop (minimaal 16GB RAM, want backtesten is geheugenverslindend) en een stabiele internetverbinding. Niets is frustrerender dan een API-call die vastloopt net op het moment dat je benchmark data ophaalt. Voor de software zit je goed met Python 3.9+.
We gaan uit van een setup die je waarschijnlijk al hebt, maar fine-tunen is key. Gebruik backtesting.py voor de engine of VectorBT voor pure snelheid op Pandas DataFrames.
Voor data halen we het liefst bij een broker als Interactive Brokers (via ib_insync) of een aggregator als Dukascopy.
En natuurlijk numpy en pandas voor de rekenkracht. Reken op een investering van een uurtje of 3 tot 5 om je omgeving spik en span te krijgen en de data te prepareren. Een veelgemaakte fout is het installeren van teveel bibliotheken (bloat). Houd het bij een lean stack. Je hebt geen zware machine learning libraries nodig voor een simpele Sharpe-optimalisatie.
De Sharpe Ratio zegt: "Kreeg ik genoeg rendement voor de stress die ik moest doorstaan?"
Stap 1: Data voorbereiden en de benchmark instellen
Je algoritme is zo goed als zijn data. Begin met schone, adjust-close data.
Als je handelt op Binance of een CFD broker, haal dan de exacte historical data via hun API. Geen guesswork. Wij gebruiken hier een voorbeeld met 1-uur candles van een populaire crypto-pair of een Forex paar zoals EUR/USD. Definieer je 'risk-free rate'. Dit is cruciaal.
In de huidige markt (2024) is de rente op staatsobligaties (bijv. US 10-Year Treasury) je nul-punt.
Laten we zeggen 4.5% per jaar. Zonder dit getal klopt je Sharpe nooit. Stop dit in een variabele: risk_free = 0.045 / 365 (omzetten naar daily). Veelgemaakte fout: Data-snoepjes.
Je pakt een dataset van 2021 (een bull market) om te testen. Je bot presteert fantastisch.
In 2022 gaat hij failliet. Gebruik altijd een dataset die ten minste 2 tot 3 jaar beslaat, inclusief bear markets en zijwaartse periodes. Tijdsindicatie: Data ophalen en schoonmaken duurt ongeveer 30 minuten tot 1 uur.
- Check op NaN-waardes en vul ze op (forward fill).
- Check op hiaten in de tijd (gaps).
- Normalizeer de tijdzone van je data naar UTC.
Stap 2: De Sharpe Ratio code schrijven
Hier bouwen we de fitness-functie. We berekenen de Sharpe Ratio op basis van de dagelijkse returns van je bot.
De formule is simpel: (Gemiddelde Return - Risk-Free Rate) / Standaardafwijking. In Python schrijven we hier een functie voor die een Pandas Series van returns aanneemt. De code moet robuust zijn.
Als je portfolio maar 1 trade heeft gedaan, is de standaardafwijking 0 en deelt je code door nul (error).
We voegen een check toe: "als er minder dan 20 trades zijn, return dan -999". Dit zorgt ervoor dat de optimizer geen rotzooi selecteert. Een concrete implementatie ziet er zo uit.
We nemen de 'returns' van je equity curve. We tellen de risk-free rate er bij de teller op, of we halen hem eraf bij het gemiddelde.
def calculate_sharpe(returns, risk_free=0.0):
if len(returns) < 20:
return -999.0 # Straf voor te weinig data
mean_return = returns.mean()
std_dev = returns.std()
if std_dev == 0:
return -999.0
# Annualiseren: wortel uit aantal dagen * (mean - rf)
sharpe = (mean_return - risk_free) / std_dev
return sharpe * (365 ** 0.5) # Annualiseer voor een eerlijke vergelijking
Meestal doen we dit op daily basis. Veelgemaakte fout: Vergeten annualiseren.
Als je daily returns hebt en je deelt het gemiddelde door de standaardafwijking, krijg je een daily Sharpe. Dat zegt weinig over de prestatie op een jaar. Vermenigvuldig altijd met de wortel van het aantal handelsdagen (365 voor crypto, 252 voor aandelen).
Stap 3: Integreren in je Backtest Engine
Nu koppelen we dit aan je trading bot. In backtesting.py draait je strategy class.
In de `run()` methode krijg je een result object. Daar zitten de 'equity' of 'portfolio value' data in.
Die haal je eruit. Je berekent de returns van de equity curve. Simpelweg: equity.pct_change().dropna(). Dit geeft je een Serie met dagelijkse procentuele veranderingen.
Dit is de input voor je functie uit Stap 2. Stel je voor: Je bot handelt op de 1-uur grafiek. Je equity curve is daily. Dat is prima. Als je bot meerdere trades per dag doet, is de daily return de som van de hourly returns.
De optimizer gaat nu zoeken naar parameters die deze Sharpe maximaliseren. Je kunt de Sharpe Ratio ook direct in de `init` van je strategy stoppen als een metric die je live wilt zien tijdens de run.
Veelgemaakte fout: Over-optimizen op Sharpe. Je bot haalt een Sharpe van 4.0 op een testperiode van 6 maanden.
Dit is bijna te mooi om waar te zijn. Het betekent waarschijnlijk dat je te veel parameters hebt (overfitting). De Sharpe is een strengere meester dan pure winst. Accepteer een lagere Sharpe (rond de 1.0 - 1.5) voor een realistischer beeld.
Stap 4: De Optimizer loslaten (Grid Search of Bayesian)
Hier gaat het gebeuren. Je wilt weten welke instellingen voor je bot de beste Sharpe geven.
Je kunt een 'Grid Search' doen: je test elke mogelijke combinatie. Bijvoorbeeld: Fast SMA van 10 tot 20, Slow SMA van 50 tot 70. Stapgrootte 1. Dit duurt lang, soms uren.
Een betere manier voor complexere bots is Bayesian Optimization (via libraries als Optuna). Dit is slimmer. Door strategie optimalisatie toe te passen, onthoudt de bot waar goede resultaten liggen en zoekt hij daar gerichter verder.
Je geeft Optuna een doel: "Maximaliseer de Sharpe Ratio" en een zoekruimte voor je parameters.
Stel je parameters in. Voor een trendvolgende bot op S&P500 futures (via IBKR API) zou je kunnen zoeken naar de optimale Stop Loss (SL) en Take Profit (TP). Bijv. SL tussen 0.5% en 2.0%, TP tussen 1.0% en 5.0%. De optimizer draait en geeft je de top 5 combinaties.
Veelgemaakte fout: Data Leakage. Je optimaliseert parameters op de hele dataset, terwijl de kracht van minder parameters vaak wordt onderschat.
Je bot presteert perfect. In de live markt faalt hij. Voorkom daarom dat je te maken krijgt met over-optimization. De oplossing: Walk-Forward Optimization.
Deel je data op in stukken. Optimaliseer op stuk A, test op stuk B.
Verplaats het venster, herhaal. Zo simuleer je de echte wereld.
Stap 5: Analyseer de resultaten (en kijk naar Max Drawdown)
Je hebt een set parameters met een hoge Sharpe. Geweldig. Maar stop niet hier.
Kijk naar de Max Drawdown. Een bot met een Sharpe van 2.0 maar een drawdown van 50% is onbruikbaar voor de meeste mensen.
Je raakt je mentale kapitaal kwijt en stopt op het dieptepunt. Check de 'win rate' en de 'profit factor'. Een hoge Sharpe kan komen door een lage win rate (bijv.
30%) met hele grote winsten en kleine verliezen. Dat is okay, zolang de verliezen klein blijven.
Check dit in je resultaten overzicht. Als je een bot hebt die draait op een broker als XTB of Plus500, onthoud dan dat de spread en swaps je Sharpe hard kunnen verlagen. In je backtest moet je kosten meenemen! Zet een realistische transactiekost in (bijv. 0.08% per trade). Zonder kosten ziet elke bot er goed uit.
- Sharpe > 1.0 is acceptabel.
- Sharpe > 1.5 is goed.
- Sharpe > 2.0 is uitstekend (maar check overfitting!).
Verificatie Checklist
Voordat je live gaat, loop deze lijst af. Geen excuses. Als je hier allemaal 'ja' op kunt zeggen, heb je een solide basis.
- Data: Is je data schoon, zonder toekomstige informatie (look-ahead bias), en beslaat deze minimaal 2 jaar?
- Costs: Zijn transactiekosten, spreads en (indien van toepassing) financieringskosten meegenomen in de return berekening?
- Risk-Free Rate: Is de juiste rente (bijv. 4.5%) verwerkt en geannualiseerd?
- Robuustheid: Is de bot getest op een aparte 'out-of-sample' dataset (bijv. de laatste 3 maanden van je data die je nooit hebt aangeraakt tijdens het optimaliseren)?
- Drawdown: Is de maximale drawdown acceptabel voor jouw emoties (meestal onder de 20%)?
- Logica: Begrijp je waarom de optimizer die parameters heeft gekozen? Als het niet logisch voelt (bijv. een Stop Loss van 0.01%), vertrouw er dan niet op.
De Sharpe Ratio is je kompas, maar jij bent de kapitein. Veel succes met het tunen van je bot!
