Hoe ga je om met 'Missing Data' in je Pandas DataFrame?

Portret van Alex de Vries, Quantitatief Analist & Algo-Trading Expert
Alex de Vries
Quantitatief Analist & Algo-Trading Expert
Data Acquisitie & Opschonen · 2026-02-15 · 7 min leestijd

Stel je voor: je hebt een backtest gedraaid voor je Python trading bot, je data van je broker API zit vol hiaten, en je risicomanagement model begint te sputteren.

Missing data is een onvermijdelijk monster in algoritmische trading, maar je kunt het temmen. In deze handleiding pakken we dat monster bij de lurven en zetten we Pandas in als je beste wapen. We doen dit praktisch, zonder poespas, en meteen toepasbaar op je trading data.

Waarden beschouwd als "missing"

Missing values in Pandas zijn niet zomaar lege plekken. Ze hebben specifieke identiteiten die je moet herkennen om ze correct te verwerken.

Herken je ze niet, dan loop je risico’s in je backtests en risicomanagement. Pandas gebruikt np.nan voor standaard numerieke datatypen, NaT voor datetime en timedelta, en NA voor moderne types zoals StringDtype, Int64Dtype, Float64Dtype, BooleanDtype en ArrowDtype. Sinds pandas 1.0 is NA een experimentele singleton-waarde die een consistente missing-value representatie biedt.

Propagatie in reken- en vergelijkingsoperaties

Voor tijdreeksen is NaT de missing value die je tegenkomt bij onvolledige datums of tijdzones. Missing values gedragen zich anders dan normale getallen.

Een operatie met np.nan of NA levert altijd een missing value op, ook als je verwacht een getal.

Logische operaties

In een backtest betekent dit dat een enkele missing prijs een heel signaal kan verpesten als je niet oppast. Gebruik dus nooit == om te checken of een waarde np.nan, NA of NaT is. Pandas heeft hiervoor speciale methoden. Doe je het toch, dan mis je de missing values en krijg je onbetrouwbare resultaten.

Logische operaties met missing values zijn tricky. Een vergelijking als x > np.nan geeft altijd False.

NA in een boolean context

Als je in je bot een filter toepast op prijzen en er zit een missing value tussen, dan verdwijnt die regel ongemerkt uit je selectie. Dat verstoort je portefeuille-berekeningen. Voor logische combinaties werkt NA in veel gevallen als een onbekende waarde.

Gebruik isna() om te bepalen welke waarden je moet uitsluiten of vóór je logica gaat.

Gebruik NA nooit direct in een if-voorwaarde. Een uitspraak als if NA: is ongeldig en levert fouten op. Check altijd met isna() of notna() voordat je een logische branch instelt. Dit voorkomt subtiele bugs in je risicomanagement scripts, waar een enkele verkeerde boolean-check je drawdown onderschat.

Missing values detecteren

Voordat je kunt vullen of verwijderen, moet je weten waar je missing values hebt. In trading data zie je ze vaak als hiaten in ticks of OHLCV-reeksen, of als lege velden in orderboek data.

Gebruik de Pandas methoden die hiervoor bedoeld zijn. Ze zijn snel, betrouwbaar en werken met alle datatype-varianten.

isnull() en isna()

isnull() en isna() zijn synoniemen en detecteren missing values inclusief None. Voor een DataFrame van 100.000 rijen met prijsdata loop je deze check in een fractie van een seconde uit. Gebruik deze methoden om een masker te maken: df.isna() geeft een boolean DataFrame dat je direct kunt gebruiken om rijen te tellen of te filteren.

notnull() en notna() zijn het omgekeerde: ze geven True voor geldige waarden. Handig voor het selecteren van complete rijen voordat je ze in je model stopt. Een praktische stap: df.notna().sum() per kolom geeft je snel inzicht in hoeveel bruikbare data er overblijft voor je backtest.

notnull() en notna()

Missing values vullen

Missing values vullen hangt af van je doel. Voor prijsdata wil je geen toekomstige informatie lekken, maar voor het verrijken van je strategie kun je kijken naar externe datasets en alternative data.

Voor indicators kun je soms lineair interpoleren. Kies altijd een strategie die bij je broker data en je bot past. Stapsgewijs bepaal je welke kolommen je aanpakt, welke methode je kiest, en of je een limiet instelt om vervalsing te voorkomen.

fillna() methoden

fillna() vervangt missing values met een specifieke waarde. Gebruik een vaste waarde zoals 0 voor volumes die ontbreken, of de vorige slotkoers voor een prijsgat in een tijdreeks.

Voor trading data is ffill() vaak logisch: je vult een missing value met de vorige geldige waarde. Dit voorkomt sprongen in je equity curve die niet in de markt hebben voorgedaan. Gebruik bfill() alleen als het echt nodig is, bijvoorbeeld bij de allereerste candle van een sessie.

Pro tip: gebruik de limit-parameter bij bfill() voor gecontroleerde vulling. Bijvoorbeeld df['close'].bfill(limit=1) vult alleen één volgende waarde, zodat je niet te ver doorschiet.

interpolate() gebruiken

interpolate() vult missing values met interpolatietechnieken, zoals de lineaire methode. Handig voor nauwkeurige schattingen tussen twee geldige prijzen, bijvoorbeeld bij een enkele missing candle in een 1m-grafiek.

Een voorbeeld voor een backtest op 5m data: df['close'].interpolate(method='linear') geeft een soepele curve zonder abrupte gaten, zonder toekomstige data te gebruiken. Let op: bij grote gaten of schokkerige markten is lineair interpoleren soms te optimistisch. Overweeg een rolling median voor robuustere vulling.

Missing values verwijderen

Soms is verwijderen de beste optie. Vooral als een rij te veel missing kolommen heeft of als een candle onbruikbaar is voor je strategie.

Verwijderen is sneller en voorkomt vervorming van je statistieken. Doe dit wel bewust: te veel verwijderen kan je sample size kleiner maken en je risicometrieken vertekenen.

dropna() voor rijen en kolommen

dropna() verwijdert rijen of kolommen met NaN-waarden. Gebruik thresh om te bepalen hoeveel niet-missing waarden er minimaal over moeten blijven. Voor een DataFrame met 20 kolommen kun je thresh instellen op 15, zodat rijen met meer dan 5 missing values worden verwijderd.

Een concrete stap voor een backtest: df.dropna(subset=['close', 'volume'], thresh=2) houdt alleen rijen over die zowel een slotkoers als volume hebben. Timing: voor een dataset van 1 miljoen rijen duurt dropna() enkele seconden op een moderne laptop. Test dit eerst op een subset van 10.000 rijen voordat je de volledige pipeline draait.

Praktische workflow voor trading data

Begin met een stevige voorbereiding. Verzamel je data via je broker API, vraag Order Book data (Level 2) op via Python, sla op in Parquet of CSV, en laad in Pandas. Controleer datatype consistentie: prijzen als float, datums als datetime, volumes als int.

Stap 1: definieer een missing-value strategie per kolom. Voor close: ffill met limit 1. Voor volume: fillna(0).

Voor technische indicators: interpolate lineair. Stap 2: detecteer missing values met isna().sum() per kolom en visualiseer gaten met een simpele plot.

Zie je grote gaten, overweeg dan de data opnieuw op te halen bij je broker. Stap 3: pas vulling toe met de gekozen methoden. Gebruik df['close'] = df['close'].ffill(limit=1) en df['volume'] = df['volume'].fillna(0).

Check na elke stap met df.isna().sum(). Stap 4: verwijder onbruikbare rijen met dropna() waar nodig.

Gebruik thresh om te voorkomen dat je te veel data verliest. Stap 5: verifieer je resultaat. Draai een snelle backtest op een subset van 10.000 rijen en controleer of je equity curve er logisch uitziet. Check of je risicomanagement statistieken (max drawdown, Sharpe ratio) stabiel zijn.

Tijdsindicatie: voor een dataset van 500.000 rijen duurt deze workflow 5 tot 10 minuten op een standaard laptop. Voor grotere datasets reken je 15 tot 30 minuten.

Veelgemaakte fouten en hoe je ze vermijdt

Een klassieke fout is het vergelijken van een kolom met np.nan via df['close'] == np.nan. Dit werkt niet.

Gebruik df['close'].isna() in plaats daarvan. Een andere valkuil is het onbedoeld gebruiken van toekomstige informatie. bfill() zonder limiet kan data uit de toekomst in het verleden trekken, wat je backtest onrealistisch maakt. Beperk bfill() tot één stap of vermijd het waar mogelijk. Gebruik NA nooit in een boolean context.

Controleer altijd met isna() of notna() voordat je logische branches instelt. Dit voorkomt subtiele bugs in je risicomanagement code.

Let op de datatypen. Een kolom als Int64Dtype behandelt missing values anders dan float64.

Gebruik het juiste dtype voor je data en pas je vullingsstrategie daarop aan. Test altijd op een subset. Een backtest op een volledige dataset kan lang duren en fouten verbergen. Een subset van 10.000 tot 50.000 rijen is genoeg om je pipeline te valideren.

Verificatie-checklist

Gebruik deze checklist voordat je je trading bot live zet. Elk punt controleert een aspect van missing data verwerking. Met onze 10 stappen voor het opschonen van je trading data zit je missing data onder controle en blijft je algoritmische trading bot stabiel draaien, van backtest tot live orderuitvoering.

  • Alle kolommen hebben het juiste dtype: prijzen als float, datums als datetime, volumes als int.
  • isna() en notna() werken correct op elke kolom en tonen geen onverwachte resultaten.
  • fillna() strategie is per kolom gedefinieerd en toegepast zonder toekomstige data te lekken.
  • ffill() gebruikt limit waar nodig, bfill() is beperkt of vermeden.
  • interpolate() is alleen toegepast op geschikte kolommen en niet op volumes of categorical data.
  • dropna() is toegepast met thresh om te voorkomen dat te veel data verloren gaat.
  • Backtest op een subset toont een logische equity curve en stabiele risicometrieken.
  • Geen == vergelijkingen met np.nan, NA of NaT in je code.
  • Geen NA in boolean context zoals if-condition.
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.