Hoe simuleer je 'Bad Data' om de robuustheid van je bot te testen?

Portret van Alex de Vries, Quantitatief Analist & Algo-Trading Expert
Alex de Vries
Quantitatief Analist & Algo-Trading Expert
Foutmeldingen & Debugging Live Bots · 2026-02-15 · 7 min leestijd

Een bot die in de backtest een rockstar is, maar in het live veld meteen door het ijs zakt? Herkenbaar. Meestal is het geen logica-fout, maar schuldige: bad data.

Een enkele vreemde candle, een gat in de historie of een API die even later aan komt zetten. Die rotzooi moet je simuleren vóórdat je echt geld inlegt. Anders test je alleen je geluk.

Deze guide leert je hoe je jouw Python-bot op een hoop rommel traint.

We stoppen expres fouten in de data, gooien er hiaten tegenaan en kijken of je risicomanagement het overleeft. Zo bouw je een bot die niet omvalt bij de eerste de beste data-hiccup.

Wat je nodig hebt (je stack)

Hou dit klaar. Niets exotisch, wel scherp.

  • Een werkende Python-bot: denk Backtrader, Lean (QuantConnect), of je eigen Pandas/Numpy-strategie.
  • Data: een CSV met OHLCV van je broker (Interactive Brokers, Binance, Bybit) of via CCXT. Minimaal 1 jaar 1m- of 5m-data.
  • API-simulator: mock je broker-connector (denk ccxt.mock of een simpele classe die data van een CSV serveert).
  • Monitoring: een notebook (Pandas) en een simpele logger naar JSON of CSV voor later analyse.
  • Rekenmachine voor risico: een scriptje dat drawdown, winrate en expectancy op basis van je trades berekent.
  • Hardware: laptop met minimaal 8 GB RAM. Je hoeft geen server.

Extra check: zorg dat je live broker-keys gescheiden staan van je test-omgeving. Geen API-keys in je test-script!

Stap 1: Zet je baseline neer

Voordat je rommel toevoegt, moet je weten wat ‘normaal’ is. Run je bot op schone data en noteer de belangrijkste cijfers. Wees specifiek.

  1. Run de backtest op schone data. Sla op: totaal rendement, max drawdown, winrate, gemiddelde win/loss ratio en aantal trades. (bijv. +42%, -8% DD, 54% winrate, 1.4 W/L, 217 trades).
  2. Check slippage en kosten. Neem realistische fees: 0.1% per trade (spot) of 0.05% (futures maker). Tel spread erbij (0.02% tot 0.1% afhankelijk van liquiditeit).
  3. Bewaar deze cijfers. Maak een baseline-JSON: baseline.json met die getallen. Dit is je referentie.
  4. Check de dataverdeling: gemiddelde candle-grootte, ATR(14), en aantal trades per week. Als je geen enkele trade hebt in rustige periodes, weet je dat je data al niet perfect is.

Veelgemaakte fout: te lage fees nemen en slippage vergeten. Resultaat: bot lijkt winstgevend, maar lekt in live kleingeld.

Stap 2: Bouw een data-rotzooi-generator

We gaan een script maken dat schone data op brute wijze onbruikbaar maakt. Noem het mess_it_up.py. Doel: realistische data-fouten. Veelgemaakte fout: dataset opschonen na het toevoegen van rommel.

  1. Laad je CSV in Pandas: df = pd.read_csv('data/BTCUSDT_1m.csv'). Zorg dat kolommen timestamp, open, high, low, close, volume heten.
  2. Verdubbel een paar candles: pick 0.5% van de rijen en vermenigvuldig de prijzen met 1.05 (5% pump). Doe dit random.
  3. Verwijder een blok: drop 10 tot 50 opeenvolgende rijen (simuleert API-downtime of een onderbroken feed). Doe dit op drie plekken in je dataset.
  4. Vervorm volumes: zet voor 1% van de data het volume op 0 of extreem hoog (10x). Dit test je volumefilters.
  5. Voeg spread toe: maak een kolom spread met een random getal tussen 0.01% en 0.2% van de close. Pas dit later toe op je entry/exit.
  6. Sla op als messy_data.csv. Zorg dat je timestamp uniek blijft; verwijder duplicates of zet ze op één lijn.

Zo test je niets. Laat de rotzooi zitten en forceer je bot ermee om te gaan.

Stap 3: Simuleer API-fouten en latency

Een bot die alles perfect synchroniseert bestaat niet. Simuleer vertraging en errors om je error-handling te testen. Voorkom geheugenproblemen als je bot wekenlang draait: bouw dit in een middag.

  1. Wrap je broker-API calls met een vertraging. Gebruik time.sleep(random.uniform(0.05, 0.5)) voor elke request. Zo test je of je bot orders kwijtraakt of dubbel plaatst.
  2. Injecter HTTP-fouten: gooi af en toe een 429 (rate limit) of 500 (server error). Simuleer dit met een mock die af en toe een fout gooit (bijv. 5% van de calls).
  3. Order fills: simuleer partial fills. Stel je bot in om 50% van een order te vullen en de rest later. Kijk of je positie-management dit goed afhandelt.
  4. Out-of-sequence data: shuffle een paar rijen in tijd (bijv. wissel 2 candles van plek). Test of je bot de volgorde forceert of doorgaat met verkeerde data.
  5. Slippage simulatie: bij elke market-order tel je slippage toe: slip = random.uniform(0.01, 0.15) / 100. Pas dit toe op je entry- en exit-prijs.

Test het op een subset van 1000 candles voor snelheid. Veelgemaakte fout: alleen een globale latency toevoegen.

In werkelijkheid zijn sommige momenten trager dan andere. Maak het variabel.

Stap 4: Test edge-cases in je data

De bot moet overweg kunnen met extreme situaties. Dit is waar de meeste live-fails gebeuren.

  1. Gaps: sluit de markt 10% lager open. Verwijder een candle en zet de volgende open 10% lager. Check of stop-losses correct uitvoeren (slippage kan groot zijn).
  2. Spikes: een candle met 20x volume en 1% prijsbeweging. Zorg dat je bot dit niet als trend ziet. Test je filter: ATR(14) > 2x gemiddelde? Dan skippen.
  3. Flat periods: zet 500 candles met een range van 0.1%. Jouw bot mag hier niet eindeloos trades openen. Test met een minimum ATR-filter.
  4. Corrupte timestamps: voeg 2-3 rows toe met een timestamp in de toekomst of verleden. Jouw bot moet deze filteren op df['timestamp'] < now().
  5. Wisselende tijdzones: mix UTC en exchange-local time in je data. Forceer alles naar UTC. Kijk of je bot aligneert met de broker-tijd.
  6. Monetaire limieten: simuleer een order die groter is dan de liquiditeit. Test of je bot het maximum volume per candle respecteert (bijv. max 1% van 24h volume).

Veelgemaakte fout: alleen happy-path testen. Je bot faalt zodra de markt extreem wordt, tenzij je je trading bots grondig debugt voordat je ze live zet.

Stap 5: Pas slippage, fees en spread toe

Zonder correcte kosten is elke backtest een sprookje. Maak een realistisch model.

  1. Base fee: neem 0.1% voor spot, 0.05% maker / 0.02% taker voor futures (afhankelijk van exchange). Reken dit per trade: cost = (entry + exit) * fee.
  2. Spread: tel spread op bij entry en trek het af bij exit. Gebruik een verdeling: 50% van de trades heeft 0.02% spread, 30% 0.05%, 20% 0.1%.
  3. Slippage: market-orders krijgen extra slippage. Bij sterke beweging (bijv. ATR > 1.5%) tel je 0.1% extra toe. Limiet-orders mogen minder, bijv. 0.02%.
  4. Funding rates (als je futures gebruikt): voeg elke 8 uur een funding-check toe. Simuleer positief en negatief funding (bijv. +0.01% of -0.01%).
  5. Minimum notional: als je order onder de broker-minimum zit (bijv. $5), skip de trade. Test dit met kleine account-sizes.
  6. Schrijf een simpele functie: def apply_costs(price, side, volume, volatility): ... en pas deze toe op elke trade. Zorg dat je bot deze kosten NIET in de strategie gebruikt, maar wel in de performance-metrics. Veelgemaakte fout: fees vergeten op compound-niveau. Over 1000 trades maakt 0.1% een enorm verschil.

    Stap 6: Monitor, log en vergelijk

    Zonder data ben je blind. Log alles wat misgaat en wat het kost.

    1. Log elke order met timestamp, type, price, size, slippage, fee en exit. Sla op in CSV of JSON.
    2. Log elke error: {"timestamp": "...", "type": "api_timeout", "severity": "warning"}. Telt hoe vaak elk type voorkomt.
    3. Bereken na de run de metrics: totaal rendement, drawdown, winrate, expectancy, slippage-kosten, error-impacts. Trek deze af van je baseline.
    4. Maak een eenvoudige grafiek: equity curve baseline vs. messy-data run. Zo zie je snel waar de bot afhaakt.
    5. Stel acceptatiegrenzen op: bijv. drawdown mag maximaal 20% stijgen, winrate mag maximaal 5% dalen. Als het erover is, pas strategie of filters aan.

    Timing: analyseer direct na de run. Wacht niet tot je 10 runs hebt; kijk per run en verbeter. Veelgemaakte fout: alleen totaalrendement bekijken.

    Een bot met lage winrate maar hoge expectancy kan nog steeds goed zijn.

    Kijk naar het complete plaatje.

    Verificatie-checklist

    Loop deze lijst af voordat je ook maar één euro live inzet.

    • Baseline-run is opgeslagen (baseline.json) met realistische fees.
    • Minimaal 3 runs op messy_data.csv gedaan en resultaten vergeleken.
    • Drawdown-stijging beperkt tot max 20% vs. baseline.
    • Winrate-daling beperkt tot max 5% vs. baseline.
    • Slippage en spread toegevoegd; kosten zijn apart zichtbaar in logs.
    • API-fouten (429/500) en timeouts getest; bot herstelt zonder dubbele orders.
    • Gaps en spikes verwerkt; geen verkeerde entries op extreme candles.
    • Volume-filter actief; 10x-volume-candles worden genegeerd.
    • Flat periods (lage ATR) resulteren in geen of weinig trades.
    • Order- en error-logs compleet; te herleiden per trade.
    • Latency-simulatie actief; bot loopt niet vast bij 0.5s vertraging.
    • Minimum notional en liquiditeitslimieten gerespecteerd.
    • Geen API-keys in de code; omgeving is gescheiden.
    • Live broker fees en limits gecontroleerd op site van broker (bijv. Binance, Bybit, IBKR).

    Als je deze checklist roodloos afvinkt, is je bot klaar voor de volgende stap: papertrading of een mini-account. En onthoud: goede bots overleven geen perfecte data, ze overleven de rotzooi. Vergeet ook niet je trading logs veilig te stellen.

Portret van Alex de Vries, Quantitatief Analist & Algo-Trading Expert
Over Alex de Vries

Alex is een ervaren quantitatief analist en Python-ontwikkelaar die complexe trading concepten vertaalt naar begrijpelijke, praktische handleidingen voor zowel beginners als gevorderden.

Volgende stap
Bekijk alle artikelen over Foutmeldingen & Debugging Live Bots
Ga naar overzicht →