Wat is 'Order Flow Trading' en hoe lees je de 'Tape' met een bot?
Je zit tegenover een scherm vol cijfers en je hoofd maakt overuren. Waarom beweegt de prijs nu zo agressief?
Het antwoord ligt vaak niet in die ene candlestick, maar in de kracht erachter: de order flow. Stel je voor dat je een bot hebt die deze stroom van orders voor je leest, net als een ervaren pokerspeler die de tics van zijn tegenstanders doorheeft. Dit is geen magie; het is een technisch verhaal van data, API's en slimme code. We gaan bouwen aan een systeem dat de 'tape' analyseert, de onzichtbare handel die de markt stuurt.
De Bouwstenen: Je Arsenaal aan Data en Tools
Voor we beginnen, moet je gereedschap klaarstaan. Je hebt meer nodig dan alleen een broker met een simpele orderknop. We gaan diep en hebben dus toegang tot de echte datastroom nodig, de 'Level 2' of 'Market By Order' data.
Zonder die data is tape reading voor een bot onmogelijk. Je fundament ziet er zo uit:
- Broker met toegang tot Order Flow data (DOM/Tape): Denk aan Interactive Brokers (IBKR) of een specifieke futures broker als NinjaTrader of Amp Futures. Je hebt een abonnement nodig dat 'Depth of Market' (DOM) en tick-by-tick data levert. Reken op €10-€50 per maand voor deze datatoegang, exclusief de commissies per transactie (rond de €0.80 - €2.00 per contract).
- Python omgeving: Gebruik een schone installatie. Minimaal Python 3.8. Zorg dat je pip (de package installer) up-to-date is. We werken in een IDE zoals VS Code of PyCharm.
- Essentiële Python libraries: Je hebt
ib_insyncof de officiëleibapinodig voor de connectie met Interactive Brokers. Daarnaastpandasvoor data manipulatie,numpyvoor snelle berekeningen en eventueelasynciovoor het verwerken van de snelle datastroom zonder je bot te blokkeren. - Een testaccount: Gebruik nooit direct je hoofdaccount. Open een paper trading account bij je broker. Zo leer je de API limieten kennen zonder echt geld te verliezen.
Stap 1: De Connectie Leggen en de Datastroom Ontsluiten
De eerste stap is technisch maar cruciaal. Je bot moet een stabiele verbinding maken met de broker.
We gebruiken hier als voorbeeld de IBKR API via ib_insync, omdat dit de boel een stuk makkelijker maakt dan de rauwe ibapi. Zo zet je de basis neer: Veelgemaakte fout: Vergeten om in TWS bij 'File' -> 'Global Configuration' -> 'API' -> 'Settings' de optie 'Enable ActiveX and Socket Clients' aan te zetten. Zonder dit doet de API niets.
- Start TWS of Gateway: Log in op je Interactive Brokers account. Start de Trader Workstation (TWS) of de IB Gateway. Zorg dat de 'Socket Port' (standaard 7497 voor paper, 7496 voor live) open staat in de instellingen.
- Installeer de library: Open je terminal en draai
pip install ib_insync pandas. Dit duurt een paar seconden. - Schrijf de connectiecode: Maak een nieuw Python bestand, bijvoorbeeld
tape_reader.py. Schrijf de basisconnectie:from ib_insync import *
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1) # Gebruik 7496 voor live!
print(ib.isConnected()) - Test de verbinding: Draai het script. Als je
Trueziet, ben je verbonden. Als je een foutmelding krijgt, check dan of TWS draait en of het juiste poortnummer gebruikt wordt.
Stap 2: De 'Tape' en de DOM begrijpen
Voordat je code schrijft, moet je snappen wat je leest. De 'Tape' (Time & Sales) is een log van elke transactie die op de beurs plaatsvindt.
De DOM (Depth of Market) toont de wachtende koop- en verkooporders rond de huidige prijs.
- De Tape (Time & Sales): Elke regel is een trade. Je ziet: Tijd, Prijs, Volume (hoeveel contracts) en of het een 'Buy' of 'Sell' was (of 'Block' trade). In futures zie je vaak 'uptick' (prijs ging omhoog bij deze trade) of 'downtick'.
- De DOM (Level 2): Dit is de 'order book'. Aan de linkerkant (vaak rood) de bieders (bids), aan de rechterkant (groen) de verkopers (asks). De prijs middenin is de 'Last Price'.
- Volume Profile (VAP): Sommige platforms tonen hoeveel volume er op elke prijs is verhandeld over een periode. Dit is de 'markthandtekening'.
Je bot gaat deze twee combineren. Focus op deze concepten: Jouw doel is om patronen te zien die de menselijke oog niet bijhoudt. Bijvoorbeeld: een 'iceberg order' die steeds weer opnieuw vult bij een bepaalde prijs, of een 'spoof' die de markt probeert te misleiden.
Stap 3: De Bot Laten Luisteren (Live Data Ingestie)
Hier wordt het echt. We gaan een script schrijven die niet stopt, maar continu luistert naar nieuwe trades en updates in de order book.
We gebruiken 'callbacks' om dit efficient te doen. Volg deze code-stappen: Specificatie: De 'tickUpdate' functie moet extreem licht zijn.
- Definieer je contract: Kies een product met voldoende volume, bijvoorbeeld de E-mini S&P 500 futures (ES). De tick size is 0.25 punten (€12.50 per tick).
contract = Index('ES', 'CME') # Of Future('ES', '202406', 'CME') - Abonneer op tickData: Je wilt elke trade zien. Je vraagt data aan via de API.
ticker = ib.reqMktData(contract, snapshot=False)
ib.sleep(1) # Wacht even op de eerste data - Maak een 'Event Handler': Dit is de hersenen van je bot. Deze functie roept de bot aan zodra er een nieuwe tick binnenkomt.
def tickUpdate(ticker):
print(f"Prijs: {ticker.last}, Volume: {ticker.lastSize}")
ticker.updateEvent += tickUpdate # Koppel de functie - Houd de verbinding levend: Gebruik
ib.run()of een simpelewhile True: ib.sleep(10)om je script draaiende te houden.
Zwaar rekenwerk (zoals complexe berekeningen) moet je in een aparte thread of na een bepaalde trigger doen. Anders mis je de volgende tick.
Veelgemaakte fout: Je script crasht omdat je een foutieve data-type verwacht. ticker.last kan soms 'None' zijn als er even geen trade is.
Voeg altijd checks toe: if ticker.last:.
Stap 4: Logica Bouwen: De Tape 'Lezen' en Patroonherkenning
Oké, je hebt een live feed. Nu komt de 'trading edge'.
We gaan tellen wat we zien. De meest simpele, effectieve tape-reading logica is het tellen van 'Buy' versus 'Sell' trades en het gewicht van de volume achter deze trades.
- Initialiseer een teller: Maak variabelen aan zoals
buy_volume = 0ensell_volume = 0. Of een lijst om de laatste 50 trades op te slaan. - Classificeer elke trade: In de
tickUpdatefunctie kijk je naar de 'tickDirection' (als je broker die geeft) of vergelijk je de huidige prijs met de vorige. Alsprice > previous_price, tel dan het volume op bijbuy_volume. - Bepaal de 'dominantie': Bereken de verhouding. Bijvoorbeeld:
ratio = buy_volume / (buy_volume + sell_volume). Als ratio > 0.7, is er sterke koopdruk. - Filter ruis: Een enkele trade van 1 contract zegt niks. Je bot moet een drempel instellen. Alleen trades groter dan 5 contracts meetellen voor je berekening.
- Combineer met de DOM: Kijk tegelijkertijd naar de order book. Zie je dat de koopdruk (tape) hoog is, maar dat de 'Ask' (verkoopkant) in de DOM heel dik wordt? Dan is er waarschijnlijk weerstand en kan de prijs stagneren ondanks de koopdrift.
Hier is een concrete aanpak om een 'Buy/Sell Pressure' indicator te bouwen: Tip voor je bot: Sla de data op in een pandas DataFrame. Elke minuut schrijf je de samengevatte data weg naar een CSV. Dit is goud waard voor backtesting van je momentum strategie later.
Stap 5: Backtesten en Risicomanagement (De Val Kuilen)
Een bot die in live markten draait zonder dat je hem getest hebt, is een ramp. Je moet je tape-reading logica valideren op historische tick-data en begrijpen of je smart order routing moet inzetten.
Helaas is historische tick-data duur (bij IBKR betaal je per GB data), maar het is essentieel. Zo ga je te werk: Veelgemaakte fout: De bot testen op de data waarop hij is 'getraind'.
- Verkrijg historische data: Gebruik de
reqHistoricalTicksfunctie van de API. Vraag de tick-data van de afgelopen 3 dagen aan. Dit zijn gigabytes aan data. Zorg dat je genoeg schijfruimte hebt. - Simuleer de logica: Schrijf een script die deze historische ticks één voor één afloopt en exact dezelfde berekeningen doet als je live bot. Log welke signalen hij had gegeven (Kopen/Verkopen).
- Voeg slippage en kosten toe: Dit is de meest gemaakte fout. Simuleer niet perfecte uitvoering. Tel bij elke 'buy' order €2.50 (commission) en 1 tick slippage (€12.50) op. Als je bot na 100 trades nog steeds positief is, pas dan ga je verder.
- Risico Management in code: Je bot moet een stop-loss kennen. Dit mag geen simpele 'stop' order zijn die de markt kan triggeren (je kunt een 'stop-market' order gebruiken). Beter is een 'hard stop' in je bot code:
if current_price < entry_price - 2.0: submit_order(Sell). Stel een maximaal dagverlies in (bijv. €500). Als dit bereikt is, sluit de bot zichzelf af doorib.disconnect()te roepen.
Je moet de data splitten: test op maandag en dinsdag, kijk of de logica werkte op woensdag en donderdag.
Gebruik de 'Walk-Forward' methode.
Verificatie Checklist: Is Je Bot Klaar?
Voordat je de bot met echt geld (of een groter bedrag in de paper account) loslaat, loop deze checklist na.
- Connectie stabiliteit: Is je script in staat om een connectie te herstellen als deze kort wegvalt? (Test dit door even je internet uit te schakelen).
- Foutafhandeling: Wat doet de bot als
ticker.lasteen uur lang 'None' is? Crasht hij of wacht hij netjes? - Logica validatie: Heb je minimaal 1000 trades gebacktest? Is de winst na kosten positief?
- Risico limieten: Zit er een 'kill switch' in de code die de bot uitschakelt bij een verlies van X bedrag?
- Orde uitvoering: Weet je zeker dat je order types correct zijn? (Bijv. Limit orders om geen 'market order' te slaan).
- Monitoring: Kun je vanaf je telefoon zien wat de bot doet? (Bijv. via een simpele print naar een logbestand of Telegram bot notificatie).
Wees streng voor jezelf. Order Flow trading met een bot is geen 'set it and forget it' strategie. Het is een constante strijd om de markt sneller en slimmer te lezen dan de concurrentie. Jouw voordeel zit 'm in de kwaliteit van je data en de robuustheid van je code. Wil je een grid trading bot inzetten? Ga aan de slag, maar begin klein.
