Bonjour,
Je ne comprends pas l’exécution en PJ de Backtest.
On y voit un premier achat, puis 2 pyramidage.
Lors du premier achat, un stoploss est mis à 2*ATR.
Puis lors de chaque pyramidage, un stoploss est remis au min. entre le précédent 2*ATR et nouvel 2*ATR (vu que l’ATR évolue entre chaque achat).
Dans mon exemple, la distance de mon stoploss ne change pas (car l’ATR augmente).
Sauf que, on voit qu’à la vente, ce n’est pas le stoploss qui est touché, mais un ordre de vente que j’ai codé, basé sur d’autres conditions.
Hors, le stoploss était sensé être plus haut…
C’est comme si le prix correspondant à ma distance de stop loss souhaitée n’était pas recalculé par Prorealtime.
Sauf que moi, je veux qu’il me recalcule mon prix de stop par rapport à mon dernier achat ! 🙁
Voyez-vous une erreur dans l’extrait de code suivant qui expliquerait le phénomène ?
Merci d’avance.
// variables :
// Risk = 2
// S1EntryMAPeriod = 20
// S1ExitMAPeriod = 10
// seuilMACD = 0.1
DEFPARAM CumulateOrders = True // Cumul des positions désactivé
ONCE S1LongN = 0
ONCE S1LongNbPyramid = 0
ONCE S1ShortN = 0
ONCE S1ShortNbPyramid = 0
ONCE S2LongN = 0
ONCE S2LongNbPyramid = 0
ONCE stopDist = 0
capital = CapitalInitial
if REINVEST>0 then
capital = CapitalInitial + strategyprofit
endif
ONCE AdjustedRisk = Risk
N = TR(close)
trendMA = Average[50](close)
macdHisto = MACD[12,26,9](close)
ca1 = (close > highest[S1EntryMAPeriod](high)[1])
// position précédente est gagnante
S1LongFilter = (S1LongN>0 and positionperf(1) > 0)
IF Not LongOnMarket and ca1 and not S1LongFilter THEN
//calcul de la taille de position en fonction du risk et de la volatilité
riskOnTrade = capital * AdjustedRisk / 100
nbSharesToBuy = riskOnTrade / (2*N)
//achat de nbSharesToBuy arrondi inférieur
BUY nbSharesToBuy SHARES ROUNDEDDOWN AT MARKET
// place un Hard Stop loss à 2N
stopDist = 2*N
SET STOP LOSS stopDist
//réinitialise le nb de pyramidage
S1LongNbPyramid=0
//défini à combien on devra pyramider
S1LongN=N
ENDIF
// pyramidage Long
// ne pas pyramider contre-tendance
if LongOnMarket and close > (tradeprice(1)+S1LongN) and S1LongNbPyramid < NbMaxPyramid and Momentum[1](trendMA)>0 then
//calcul de la taille de position en fonction du risk et de la volatilité
riskOnTrade = capital * AdjustedRisk / 100
nbSharesToBuy = riskOnTrade / (2*N)
//achat de nbSharesToBuy arrondi inférieur
BUY nbSharesToBuy SHARES ROUNDEDDOWN AT MARKET
// place un Hard Stop loss au min de l'ancien 2N et du nouveau 2N
stopDist = min(stopDist,2*N)
SET STOP LOSS stopDist
S1LongNbPyramid = S1LongNbPyramid + 1
//défini à combien on devra pyramider
S1LongN=N
endif
// Conditions pour fermer une position acheteuse
cca1 = (close < lowest[S1ExitMAPeriod](low)[1])
IF LongOnMarket and (cca1 or macdHisto < (-1*seuilMACD)) THEN
SELL AT MARKET
ENDIF
GRAPHONPRICE stopDist
À la fin de ton code, lors d’un backtest pour vérifier le niveau calculé par ton code directement sur le graphique. Ça devrait t’aider à trouver le problème.
Bonjour,
En effet, c’est plus visuel.
Mais le SL est bien où je pensais (nouvelle image en PJ). Donc il aurait dû être touché.
Je ne vois vraiment pas ce qui peut clocher 🙁
PS : j’ai mis “GRAPHONPRICE (tradeprice(1)-stopDist)” pour avoir le SL affiché au bon endroit.
J’ai essayé de remplacer, à l’endroit de mon pyramidage, mon SL par un ordre de vente STOP.
Et ça ne change rien…
Du coup, j’ai essayé de supprimer mes conditions de vente, pour voir où le STOP est réellement touché.
En PJ ce que cela donne (STOP loss touché, vente au prix de 12.806).
Mais je n’y compris toujours rien … on dirait que le stop est déplacé plus bas, mais je ne vois pas par quoi !
Cette fois, c’est sûr, il y a un bug.
J’ai mis en commentaire toutes les lignes “SET STOP LOSS” de tout le code, sauf celle qui est dans le IF de pyramidage, et le résultat reste le même qu’initialement.
Si je laisse ma condition d’Exit Long, le stop loss n’est pas touché.
Si je supprime ma condition d’Exit Long, le stop loss est touché, mais vendu à 12.806. Ce qui veut dire mon stop loss qui n’a été mis que 2 fois durant tout le backtest :
- 1 première fois lors du 1er pyramidage à 12.89
- 1 deuxième fois lors du 2ème pyramidage à 13.466
Vu la vente à 12.806, c’est le premier stop loss qui a été touché.
Dit autrement, le second SET STOP LOSS n’est pas pris en compte par Prorealtime…
@Nicolas, de ton expérience, tu confirmes le phénomène ?
J’aimerai tester de mon côté, ça n’est pas clair pour moi pour le moment. Il semble que le code utilise pas mal de variables qui sont dans l’optimiseur, merci de me partager le fichier .itf pour être plus efficace.
A chaque pyramidage, tu pourrais calculer ton nouveau niveau de stop et placer directement un ordre conditionnel de type stop également, comme ceci:
monSL = close-stopDist
SELL AT monSL STOP
Cet ordre conditionnel devrait être aussi placé en continu par la suite si tu es au marché. De cette façon tous les ordres se fermeront à monSL simultanément.
J’ai réussi à avoir les SL là où je voulais en codant avec des ordres de vente type Stop comme tu le mentionnes pour la technique de breakeven, c’est à dire en rajoutant en début de script :
ONCE stopPrice = 0
if Not OnMarket then
stopDist = 0
stopPrice = 0
endif
et en fin de script :
if stopPrice > 0 then
if LongOnMarket then
SELL AT stopPrice STOP
elsif ShortOnMarket then
EXITSHORT AT stopPrice STOP
endif
endif
Et dans mon IF de pyramidage, je calcule le stopPrice = close – stopDist (ou close + stopDist pour le Short)
Enfin, c’est quand même pas top que Prorealtime ne prenne pas en compte correctement les STOP LOSS 🙁
ça serait plus simple que de bidouiller avec des ordres de vente à replacer à chaque bougie…
En tout cas, merci beaucoup Nicolas !
Prorealtime prend en compte correctement les SL. Les solutions proposées sont les plus rapides que j’ai pu te trouver sans tester le code. Il doit y avoir une autre explication au problème que tu as exposé.
Bonjour,
Je serais intéressé par ton analyse dans ce cas.
Ci-joint le fichier ITF, que j’ai un peu allégé pour faciliter ton analyse.
J’ai gardé une seule strategy Long sur 2, et supprimer la Short.
le point qui me pose question est sur l’exécution du stop loss suite à pyramidage (premier ordre début décembre 2017, vente mi-janvier 2018)
Merci d’avance pour ton oeil expert.
Timeframe et instrument svp?
Pardon
AF (AirFrance KLM) en daily
Avec le code suivant, j’utilise donc un SET STOP LOSS stopDist et je graph sur le prix un Close-stopDist que j’update à chaque nouvelle ordre, la clôture du panier se fait correctement au bon niveau (plus ou moins compte tenu que je ne connais pas le prix d’ouverture réel à l’open suivant).
La ligne rouge semble bonne, qu’est ce qui te choque ?