L’énigme « London Open Breakout »

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 : 

  1. Le breakeven ne fonctionne pas sur les shorts. Et pourtant il fonctionne sur les longs !
  2. 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
Share Button