In dit artikel
Na dit artikel kun je…
- Signaal- en prijslabels controleren vóór indexverwijdering.
- Publicatie, voltooide bar en uitvoeringsmoment afzonderlijk vastleggen.
- Orders en kosten met gedeeld rekeningkapitaal aansluiten.
Begrippen uitgelegd binnen het artikel
Backtesting Orderuitvoering Commissie Drawdown Stop loss Take profit (TP)Een Python-backtest vraagt een controleerbare keten van data naar toen beschikbare informatie, besluiten, fills en administratie. Bewaar record-ID’s naast tijdstempels. Een snelle equitygrafiek toont niet of een latere publicatie, onvoltooide bar of onmogelijke uitvoeringsprijs is gebruikt.
Kies de omgeving vanuit de onderzoeksvraag
MT5 Strategy Tester ondersteunt multicurrency-EA’s, tests en optimalisatie. Python is een andere manier om eigen data en berekeningen te organiseren, geen noodzakelijke ontsnapping aan een één-paargrens. Vergelijk contract, gegevens en uitvoeringsvereisten met dezelfde bevroren dataset en regels.
Kies de kleinste bruikbare stack en bewaar versies, licentie, gegevensrechten en ondersteunde omgeving. Onderzoek en deployment kunnen aparte kosten hebben. Geen bibliotheeknaam garandeert realistische uitvoering, een vast snelheidsvoordeel of handelskwaliteit.
Bewaar data én betekenis
Leg product, provider, tijdzone, prijszijde, interval en downloadbereik vast. Controleer dubbele ID’s, volgorde en ontbrekende perioden. Een gesloten markt is niet automatisch corrupt; forwardfill kan juist waarnemingen verzinnen. Bewaar origineel en iedere transformatie afzonderlijk. Gaten in backtestdata: CSV-dekking, conflicten en tijdstempels controleren controleert een afgebakend tijdrooster zonder prijzen te herstellen.
MetaTrader 5 copy_rates_range levert onder meer tijd, OHLC, tickvolume, spread en reëel volume. Dat is geen complete historische commissie- of swaptarieftabel. Ontvangst hangt van beschikbare terminalhistorie en instellingen af; gevraagde periode betekent niet volledig teruggegeven. Tijdargumenten en ontvangen tijden gebruiken UTC. Converteer sessies expliciet per datum naar bijvoorbeeld Europe/Amsterdam.
pandas en NumPy ondersteunen gegevensberekeningen. Backtrader organiseert een eventgedreven workflow. Vectorbt verwerkt eveneens order-, signaal- of customorderfunctiemodi en werkt kas- en activatoestand bij. Vectorinvoer betekent niet dat iedere uitvoering onafhankelijk van eerdere toestand is.
Het indexlabel weglaten kan het signaal aan een andere bar koppelen
Gelijke lengte bewaart geen identiteit. Controleer labels vóór to_numpy en daarna de informatietijd.
- Prijzen
- A100, B102, C104 – Op volgorde A, B, C.
- Flags
- C1, A0, B0 – Andere volgorde, zelfde unieke ID’s.
- Series op label
- A0, B0, C104 – Kandidaat is C.
- Arrays op positie
- 100,0,0 – Teruggeplakt op A, B, C selecteert onjuist A.
Het fictieve bronbestand heeft voltooide prijsrecords A100, B102, C104, in die volgorde. Een afzonderlijke flag-Series staat in volgorde C:1, A:0, B:0. Flag 1 betekent slechts kandidaat voor verder onderzoek, geen order of fillprijs.
pandas koppelt Series op label: prices * flags geeft A0, B0, C104. Beide naar arrays converteren en op positie vermenigvuldigen geeft 100,0,0. Terugplakken op A, B, C selecteert dan onjuist A. De reekslengte klopt nog steeds. Controleer ID’s vóór to_numpy(); juiste koppeling vraagt daarnaast juiste beschikbaarheidstijd.
Bepaal wanneer een record bruikbaar wordt
Een H1-bar met opening 10.00 heeft niet al om 10.00 zijn volledige OHLC. Bij resampling bepaalt closed welke rand in het interval valt en label het weergegeven randlabel. Een ander label maakt de aggregatie niet eerder beschikbaar.
Koppel macrodata op publicatietijd van de toen beschikbare versie, niet alleen de beschreven maand. merge_asof vereist gesorteerde tijdsleutels. backward kiest vroeger of gelijk; nearest kan later kiezen. Geen van beide kent revisies vanzelf. Leg tolerantie en volgorde bij gelijke tijdstempels vast. EA met API offline backtesten: beschikbare versies en null controleren scheidt versie en observatieperiode.
De eigen broncontrole beslist om 10.04 UTC. Er zijn alleen releases 10.00 met 50 en 10.05 met 60. Zonder tolerantie kiest backward 50, vier minuten oud. nearest kiest 60, één minuut dichtbij maar in de toekomst. Met inclusieve backwardtolerantie twee minuten bestaat geen match. Bewaar dat ontbreken; de toekomst invullen verandert de informatieverzameling.
Het aparte gesloten-barmodel heeft eerste twintig High-waarden 100 tot 119, met steeds Open=High−0.5, Low=High−2, Close=High−1. Bar 21 heeft O120/H121/L118/C120.5; bar 22 O120.6/H122/L119/C121. Dit zijn willekeurige niet-marktprijzen, geen FX-trade.
previous_high = bars["high"].shift(1).rolling(20).max()
signal = bars["close"] > previous_high
next_bar_signal = signal.shift(1, fill_value=False)
Op bar 21 is de vorige twintigbarstop 119, dus 120,5>119 waar. De huidige High meenemen maakt drempel 121 en conditie onwaar. De laatste coderegel plaatst het waargenomen signaal op bar 22, maar levert geen fillprijs, orderacceptatie, hoeveelheid of exit. Gebruik alleen voltooide invoer en definieer die overige fasen apart.
Signaal, fill en kosten afzonderlijk modelleren
Backtrader beschrijft voor zijn gewone Market-model een order na huidige barverwerking op de opening van de volgende beschikbare bar. Andere instellingen of modellen kunnen timing wijzigen. Als stop en target binnen dezelfde OHLC-bar vallen, bepaalt OHLC alleen hun waarnemingsvolgorde niet.
Het fictieve een-trademodel koopt 10.000 EUR op toegewezen EUR/USD-Ask 1,1002 bij Bid 1,1000. Later sluit het alles op Bid 1,1012 bij Ask 1,1014. Pip 0,0001 geeft tienpipsfillverschil, USD 10. Commissie USD 1 per zijde geeft netto USD 8; financiering en extra slippage zijn hier nul aangenomen.
Nogmaals twee entryspreadpips aftrekken maakt USD 6 en telt een al opgenomen prijsverschil dubbel. Definieer echte financiering, conversie, contractgrootte, marge en geweigerde orders voor het onderzochte product. Een willekeurig slippagemodel vraagt verdeling, seed en bibliotheekversie.
Nieuw afzonderlijk EUR-tegenvoorbeeld: een zelfgemaakt allocatiemodel begint met EUR 1.000 beschikbaar voor twee gelijktijdige orders. A reserveert exact EUR 700 marge; B EUR 400. Geen andere blootstelling, kosten of waardeverandering tijdens de allocatie. Beide volledig uitvoeren vraagt EUR 1.100 en is onmogelijk onder deze modelgrens.
Met “alles of niets” per order wordt bij A-eerst B geweigerd; bij B-eerst A. Ken alleen ter illustratie aan een uitgevoerde A EUR 70 en aan uitgevoerde B EUR 40 later nettoresultaat toe. Dan zijn de twee scenariototalen 70 of 40, niet de onafhankelijk opgetelde 110. Margeregels en latere uitkomsten zijn toegewezen, geen actuele brokerformule of voorspelling. Een gedeelde rekening heeft gedeelde beperkingen; onafhankelijke equitycurves optellen kan onfinancierbare orders verbergen.
Een grootboek maakt de uitkomst herleidbaar
Het afzonderlijke gelijk-R-model heeft precies veertig winsten+2R en zestig verliezen−1R:80R positief,60R verlies, netto 20R, PF80/60≈1,33, gemiddelde 0,2R. Kosten 0,1R op iedere trade geven veertigmaal+1,9R en zestigmaal−1,1R:76R positief,66R verlies, netto 10R, PF76/66≈1,15 en gemiddelde 0,1R. R heeft overal hetzelfde geldbedrag; dit is rekenwerk, geen echte backtest.
De eigen herinstapcase heeft vijf condities waar, waar, waar, onwaar, waar. Beide procedures openen op bar 1; de stop sluit op bar 2 vóór instapbeoordeling. Er zijn geen verdere exits. “Flat en waar” opent direct weer op bar 2. “Eerst een nieuwe onwaar afwachten” blijft wachten op 2 en 3, activeert weer op 4 en opent op 5.
Beide tellen twee instappen maar op andere momenten. Dit is een eigen gekozen toestandsmachine, geen standaardclaim over een bibliotheek. Bewaar instap-ID’s en toestandovergangen, niet alleen tradeaantal. Houd open-equity en gesloten resultaten apart, beginvermogen als piekreferentie en externe stromen buiten tradingrendement.
Selectie en onbekende evaluatie niet verwarren
Leg trainings- en testvensters chronologisch vast vóór voorkeursregels worden gekozen. Bewaar alle instrumenten, parameters, filters, splits en verworpen versies. Weinig zichtbare parameters betekent niet weinig onderzochte hypotheses. Bailey en mede-auteurs bespreken backtestoverfitting; uit onze fictieve cases wordt geen PBO berekend.
Het andere toegewezen honderd-trademodel heeft 75 winsten+0,2R en 25 verliezen−1R. Winrate 75%, winstsommen 15R/verliessom 25R, netto−10R en PF0,6 vóór kosten. Geen hitrate- of PF-drempel diagnosticeert alleen een bug. Controleer informatietijd, afhankelijkheid, uitvoering en sensitiviteit vóór een oorzaak wordt ingevuld.
Een offline onderzoek zonder echte order starten
- Maak een geïsoleerd project en bewaar ongewijzigde data met ID’s, bron, UTC, prijszijde en versie. Voor dit leren zijn geen live credentials nodig.
- Werk enkele volledig opgegeven records door: wanneer is het signaal bekend, welk volgend event mag uitvoeren en wat bij ontbreken of revisie?
- Definieer toevoegen, omkeren, herinstappen of opnieuw activeren expliciet. Controleer verwachte entry-ID’s.
- Sluit iedere fill en kostenregel aan en leid rapportmaten uit het grootboek af. Bewaar geen Sharpe of drawdown die niet uit gedateerde reeksen volgt.
- Vergelijk dezelfde bevroren regels onder beschreven alternatieve uitvoering en bewaar proeven, vensters en beperkingen. Een vaste daling in prestatie identificeert haar oorzaak niet.
Test wat je hebt geleerd
Ongeveer 2 minuten oefenen.
Antwoord en uitleg bekijken
De enige flag 1 hoort bij IDC. De volgorde van de Series verandert die identiteit niet.
Andere vragen
Hoeveel Pythonkennis is nodig?
Begin met data lezen, functies en index tegenover arraypositie. Reproduceer een klein volledig model vóór opschalen. Dertig regels of een vaste leertijd bewijzen geen gereedheid; timing, state, exits en uitvoering blijven apart.
Backtrader of vectorbt?
Vergelijk de echte simulatiemodus met je taak. Backtrader heeft een standaard Market-model met uitvoering op de volgende bar. Vectorbt heeft meerdere order-/signaalfuncties en cash-state. Geen naam garandeert snelheid of realistische defaults; controleer dezelfde bekende records.
Waar vind ik betrouwbare historie?
Controleer product, bron, prijszijde, UTC en dekking. MT5 copy_rates_range hangt van terminalhistorie af en geeft geen complete kostenhistorie. yfinance is een onafhankelijke tool met Yahoo-gebruiksmeldingen; CCXT ontsluit beursdata. Een toolnaam certificeert geen geschikte FX-dataset.
Hoe onderzoek ik te mooie resultaten?
Controleer labels, toen beschikbare informatie, fills, kosten en alle selectieproeven.75 winsten van 0,2R tegenover 25 verliezen van 1R geven−10R. Hitrate of PF alleen bewijst geen specifieke bias. Bewaar vooraf gekozen onbekende vensters en bronversies.
Bronnen en controle
- pandas — Series-labelkoppeling
Primaire Series-operaties 284–321 gelezen: labels koppelen, geen garantie op juiste informatietijd. De A/B/C-case is ons eigen datamodel.
- pandas — merge_asof
Primaire sortering, backward/nearest en tolerantie 57–137 gelezen. Geen automatische kennis van revisies; 10.04 voorbeeld is fictief.
- pandas — Resampling
Primaire closed/label-parameters 252–258 gelezen. Veranderde labels vervroegen de beschikbaarheid van OHLC niet.
- MetaQuotes — Python copy_rates_range
Primaire historiegrens en UTC109–111 gelezen; retourvelden uit de documentatie gecontroleerd. Geen complete historische fee-/swaptarieftabel verondersteld.
- Backtrader — Orderuitvoering
Primaire standaardMarket-timing 359–371 gelezen. Geen algemene garantie voor andere instellingen, live fills of intrabarvolgorde.
- Vectorbt — Portefeuillesimulatie
Primaire stateupdates 463–469 en order-/signaal/custommodus 480–507 gelezen. Vectorinvoer betekent geen afwezigheid van tijdsafhankelijke cash-state.
De berekeningen gebruiken expliciete aannames. Ze vervangen geen actuele marktgegevens of voorwaarden van de aanbieder.
