Bonjour à tous,
Voici un petit codage simple sur une approche du « London Open Breakout ».
La stratégie est très simple, le codage est très simple…
Et pourtant, comme je le montre dans la vidéo, je me trouve confronté à 2 bugs :
- Le breakeven ne fonctionne pas sur les shorts. Et pourtant il fonctionne sur les longs !
- Certaines entrées shorts ne se font pas.
Je vous montre le code. Je ne vois pas où j’ai pu commettre une erreur…
Moralité :
A tous ceux qui pensent que le codage est chose simple… Voyez comment parfois on peut galérer sur quelque chose de simple en apparence !
Alors imaginez si en plus on doit coder des entrées à plusieurs niveaux, des sorties partielles, etc.
Il y aussi des choses qu’on ne peut pas coder, comme le passage au breakeven en cours de bougie (à l’heure actuelle, à ma connaissance il faut encore attendre que la bougie clôture).
Et même si le codage aboutit, rien ne dit pour autant que la stratégie soit efficace.
Voilà pourquoi j’avais dit que plus de 90% des codages n’aboutissent pas. C’est comme en recherche, rien n’assure qu’on va trouver…
Si quelqu’un d’entre vous a la solution, ce serait très appréciable de me la communiquer par email, afin que je puisse terminer / publier ce code. Je pourrai aussi lui livrer mes paramètres spécifiques à cette stratégie, qui m’ont permis de gagner en trading manuel (mais encore une fois, il m’était impossible de le coder !).
A vos claviers !
Voici le code du BACKTEST (A AMELIORER) :
Defparam cumulateorders = false // Timeframe : M15 IF TIME = 080000 THEN HAUT = highest[8](high) BAS = lowest[8](low) achatjour = 0 ventejour = 0 amplitude = haut-bas ENDIF Ctime = time >= 080000 AND time <= 170000 Ccanal = close < haut and close > bas IF Ctime and Ccanal THEN IF achatjour = 0 THEN buy at HAUT stop ELSIF ventejour = 0 THEN sellshort at BAS stop ENDIF ENDIF IF longonmarket THEN achatjour = 1 ENDIF IF shortonmarket THEN ventejour = 1 ENDIF set stop loss amplitude set target profit 2* amplitude // BREAKEVEN IF high > HAUT + amplitude THEN sell at HAUT stop ENDIF IF low < BAS - amplitude THEN exitshort at BAS stop ENDIF
MISE A JOUR : 30/11/2020
Vous êtes formidables !
Vous avez été une dizaine à me proposer votre tentative d’amélioration !
Il fallait en effet se rendre compte que les conditions d’ordre n’étaient valables que pour une bougie, pas pour les suivantes.
Malheureusement, j’ai pu constater que sur toutes, il subsiste des anomalies : pas de déclenchement de certaines positions (notamment les shorts récemment, allez savoir pourquoi ?).
Je vous libre ici la version qui semble la meilleure pour le moment : celle d’Alain.
Elle fonctionne bien… SAUF lorsque le stop loss est au niveau de la bougie d’entrée : en ce cas le trade n’est pas comptabilisé et il peut y en avoir un autre dans la journée :
Exemple sur le 26/10/2020 :
Il semble d’ailleurs que cette journée soit toujours problématique, quelle que soit la version testée.
Voici donc le code du BACKTEST provisoire (celui d’Alain) :
Defparam cumulateorders = false // Timeframe : M15 IF TIME = 080000 THEN HAUT = highest[8](high) BAS = lowest[8](low) achatjour = 0 ventejour = 0 amplitude = haut-bas ENDIF IF time > 170000 THEN // plus d'autres prises de positions achatjour = 1 ventejour = 1 ENDIF If AchatJour = 0 and close < haut then buy at HAUT stop endif If VenteJour = 0 and close > bas then sellshort at BAS stop endif IF longonmarket and NOT longonMarket[1] THEN achatjour = 1 BreakEvenLong = 0 ENDIF IF shortonmarket and NOT shortonMarket[1] THEN ventejour = 1 BreakEvenShort = 0 ENDIF set stop loss amplitude set target profit 2* amplitude // BREAKEVEN IF high > HAUT + amplitude THEN BreakEvenLong = 1 ENDIF IF BreakEvenLong Then sell at HAUT stop endif IF low < BAS - amplitude THEN BreakEvenShort = 1 ENDIF If BreakEvenShort then exitshort at BAS stop endif IF time >= 190000 THEN sell at market exitshort at market ENDIF
MISE A JOUR : 05/12/2020
Merci à « Aurélien » d’avoir trouvé la solution !
Etonnamment, le résultat n’est pas meilleur… mais cela permettra peut-être de coder la suite de ma stratégie.
Voici le code du BACKTEST :
Defparam cumulateorders = false // Timeframe : M15 IF TIME = 080000 THEN HAUT = highest[8](high) BAS = lowest[8](low) achatjour = 0 ventejour = 0 amplitude = haut-bas ENDIF IF time > 170000 THEN // plus d'autres prises de positions achatjour = 1 ventejour = 1 ENDIF If AchatJour = 0 and (high<haut or (high=haut and time=080000)) then buy at HAUT stop endif If VenteJour = 0 and (low>bas or (low=bas and time=080000)) then sellshort at BAS stop endif if high-haut>=2* amplitude then achatjour=1 elsif bas-low>=2* amplitude then ventejour=1 elsif high>=haut and low<=bas then achatjour=1 ventejour=1 endif IF longonmarket and NOT longonMarket[1] THEN achatjour = 1 BreakEvenLong = 0 ENDIF IF shortonmarket and NOT shortonMarket[1] THEN ventejour = 1 BreakEvenShort = 0 ENDIF set stop loss amplitude set target profit 2* amplitude // BREAKEVEN IF high > HAUT + amplitude THEN BreakEvenLong = 1 ENDIF IF BreakEvenLong Then sell at HAUT stop endif IF low < BAS - amplitude THEN BreakEvenShort = 1 ENDIF If BreakEvenShort then exitshort at BAS stop endif IF time >= 190000 THEN sell at market exitshort at market ENDIF
MISE A JOUR le 05/12/2020 :
VARIANTE
Voici la contribution de Jean-Christophe.
Bonjour Marc,
Voici le résultat de ma modeste contribution à ton « London Open Breakout », le backtest n’est pas très beau (petite perte en 2014 car peu de positions cette année-là) mais les résultats sont acceptables pour une « mise en production » de la stratégie. Les backtests ont été effectués sur le GBPUSD mini avec 200 kbars (8 ans) et un spread de 0.9, j’ai effectué quelques modifications et ajouté ma touche personnelle, cela pourrait te donner de bonnes idées (ou pas) pour tes algorithmes.
En détail:
– ouverture 8h (inchangé)
– range des 32 dernières bougies (au lieu des 8 dernières)
– plus de positions après 15h (au lieu de 17h)
– pas de position à moins de 0.1% des points pivots, supports et résistances mensuels
– filtre de volatilité minimale et maximale
– filtre sur les moyennes mobiles (on peut aussi utiliser les momentums et cela donne à peu près les mêmes résultats globaux)
– filtre sur la hauteur du range
– filtre sur un macd d’un timeframe custom afin d’avoir la tendance sur une échelle supérieure
– revue des conditions d’ouverture (l’ajout du macd permet d’éviter une double position simultanée à la hausse et à la baisse interdite pour les comtes à risque limité)
– SL et TP réajustés (cela donne un Risk Reward > 2)
– clôture des positions à 20h
– remplacement du breakeven par un stop suiveur basé sur la volatilité
Cordialement,
Jean-Christophe
NB : ceci a été un peu modifié dans la version mise à jour, que je vous livre ci-dessous.
Je n’ai pas vérifié le bon fonctionnement dans les détails, notamment le stop suiveur. Mais je vous livre le code plus bas, si vous souhaitez essayer / améliorer cette stratégie.
Voici le code du BACKTEST :
(version mise à jour)
Defparam cumulateorders = false DEFPARAM Preloadbars = 10000 // POSITION SIZE n = 1 // Timeframe : M15 IF TIME = 080000 THEN HAUT = highest[32](high) BAS = lowest[32](low) achatjour = 0 ventejour = 0 amplitude = haut-bas ENDIF IF time > 150000 THEN // plus d'autres prises de positions achatjour = 1 ventejour = 1 ENDIF // MONTHLY PIVOT POINT, SUPPORT & RESISTANCE ONCE monthlyHigh = undefined ONCE monthlyLow = undefined ONCE monthlyPP = undefined ONCE monthlyR3 = undefined ONCE monthlyR2 = undefined ONCE monthlyR1 = undefined ONCE monthlyS1 = undefined ONCE monthlyS2 = undefined ONCE monthlyS3 = undefined If Month<>Month[1] then monthlyHigh = Highest[BarIndex - lastMonthBarIndex](High)[1] monthlyLow = Lowest[BarIndex - lastMonthBarIndex](Low)[1] lastMonthBarIndex = BarIndex monthlyPP = (close[1] + monthlyHigh + monthlyLow) / 3 monthlyR3 = monthlyR1 + (monthlyHigh - monthlyLow) monthlyR2 = monthlyPP + (monthlyHigh - monthlyLow) monthlyR1 = 2*monthlyPP - monthlyLow monthlyS1 = 2*monthlyPP - monthlyHigh monthlyS2 = monthlyPP - (monthlyHigh - monthlyLow) monthlyS3 = monthlyS1 - (monthlyHigh - monthlyLow) Endif // DISTANCE MONTHLY PIVOT POINT, SUPPORT & RESISTANCE DistPP = 100 * (max(close, monthlyPP) / min(close, monthlyPP) - 1) > 0.1 DistR3 = 100 * (max(close, monthlyR3) / min(close, monthlyR3) - 1) > 0.1 DistR2 = 100 * (max(close, monthlyR2) / min(close, monthlyR2) - 1) > 0.1 DistR1 = 100 * (max(close, monthlyR1) / min(close, monthlyR1) - 1) > 0.1 DistS1 = 100 * (max(close, monthlyS1) / min(close, monthlyS1) - 1) > 0.1 DistS2 = 100 * (max(close, monthlyS2) / min(close, monthlyS2) - 1) > 0.1 DistS3 = 100 * (max(close, monthlyS3) / min(close, monthlyS3) - 1) > 0.1 // DISTANCE MONTHLY PIVOT POINT, SUPPORT & RESISTANCE FILTER FilterDistPPSR = DistPP and DistR3 and DistR2 and DistR1 and DistS1 and DistS2 and DistS3 // VOLATILITY FILTER FilterVolatility = AverageTrueRange[14](close) > 100/100000 and AverageTrueRange[14](close) < 500/100000 // MOVING AVERAGES FILTER FilterMMLong = average[52](close) > average[84](close) and average[32](close) > average[72](close) FilterMMShort = average[112](close) < average[216](close) and average[144](close) < average[200](close) and average[144](close) < average[184](close) // MININUM RANGE FILTER FilterRange = amplitude > 0.15 / 100 * close // MACD 18-hours 15-minutes FILTER factor=73 FilterMACD = MACD[12*factor,26*factor,9*factor](close) < ExponentialAverage[9*factor](MACDline[12*factor,26*factor,9*factor](close)) // MA 200 1-hour FILTER MA200 = average[800](close) FilterMA200 = 100 * (max(close, MA200) / min(close, MA200) - 1) > 0.05 If AchatJour = 0 and close < haut and FilterVolatility and FilterDistPPSR and FilterRange and FilterMMLong and not FilterMACD and FilterMA200 and not onmarket then buy n contracts at HAUT stop endif If VenteJour = 0 and close > bas and FilterVolatility and FilterDistPPSR and FilterRange and FilterMMShort and FilterMACD and FilterMA200 and not onmarket then sellshort n contracts at BAS stop endif IF longonmarket and NOT longonMarket[1] THEN achatjour = 1 ENDIF IF shortonmarket and NOT shortonMarket[1] THEN ventejour = 1 ENDIF set stop loss 0.85 * amplitude set target profit 1.85 * amplitude IF time >= 200000 THEN sell at market exitshort at market ENDIF // VARIABLES STOP SUIVEUR ONCE trailingStopType = 1 // Trailing Stop - 0 OFF, 1 ON ONCE trailingStopLong = 80 // Trailing Stop Atr Relative Distance ONCE trailingStopShort = 80 // Trailing Stop Atr Relative Distance ONCE minStop = 0 // Minimum Trailing Stop Distance // TRAILINGSTOP ATRTrail = AverageTrueRange[14](close*pipsize) TrailingStartLong = ATRTrail*trailingStopLong TrailingStartShort = ATRTrail*trailingStopShort if trailingStopType = 1 THEN if not onmarket then MAXPRICE = 0 MINPRICE = close CLOSEPRICE = 0 ENDIF if longonmarket then MAXPRICE = MAX(MAXPRICE,close) if MAXPRICE-tradeprice(1)>=TrailingStartLong*pointsize then if MAXPRICE-tradeprice(1)>=MINSTOP then CLOSEPRICE = MAXPRICE-TrailingStartLong*pointsize ELSE CLOSEPRICE = MAXPRICE - MINSTOP*pointsize ENDIF ENDIF ENDIF if shortonmarket then MINPRICE = MIN(MINPRICE,close) if tradeprice(1)-MINPRICE>=TrailingStartShort*pointsize then if tradeprice(1)-MINPRICE>=MINSTOP then CLOSEPRICE = MINPRICE+TrailingStartShort*pointsize ELSE CLOSEPRICE = MINPRICE + MINSTOP*pointsize ENDIF ENDIF ENDIF if onmarket and CLOSEPRICE>0 then if longonmarket then SELL AT CLOSEPRICE STOP endif if shortonmarket then EXITSHORT AT CLOSEPRICE STOP endif ENDIF ENDIF