Rejoindre la communauté
banner_forum
Devenez membre de la plus grande
communauté francophone sur le Forex
Partagez, échangez et apprenez en gagnant des crédits sur votre compte de trading

BOLLINGER_BANDS_RSI_ATR_EA.....MQL4

  • lefeuvr3

    A signaler
    Ajout d'un take profit et d'un stop loss dynamique
    Correction d'une erreur constatée sur l'ensemble des robots programmes jusqu'ici.

    Code
    //+------------------------------------------------------------------+ //| BOLLINGER_BANDS_RSI_ATR_EA.mq4 | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict //+------------------------------------------------------------------+ //BOLLINGER_BANDS_EA ...EURUSD ...1MN //+------------------------------------------------------------------+ extern int MagicNumber=07112020; extern int atrMultipleSL=45; //extern int atrMultipleTP=36; extern int atrMultipleTS=11; extern int PeriodATR=1; extern int ShiftATR=0; //extern double StopLoss=72; //extern double TakeProfit=79; //extern int TrailingStop=36; extern int Slippage=3; extern int Indicatorperiod=39; extern int BBDeviation=2; extern double LotFactor =155; //lotsize factor double lot; double MarginFree; // Free margin in percentage extern double MinMarginLevel = 100; // Lowest allowed Margin level for new positions to be opened. extern double Lowlevel=49; extern double Highlevel=84; extern int Periode=12; //+------------------------------------------------------------------+ // expert start function //+------------------------------------------------------------------+ int start() { double MyPoint=Point; if(Digits==3 || Digits==5) MyPoint=Point*10; double TheStopLoss=0; double TheTakeProfit=0; //+------------------------------------------------------------------+ double atr = iATR(NULL, 0, PeriodATR, ShiftATR); double StopLoss = (atr * atrMultipleSL / Point); double TakeProfit =(atr * atrMultipleSL / Point);//(atr * atrMultipleTP / Point); double TrailingStop=(atr * atrMultipleTS / Point); //+------------------------------------------------------------------+ //Calculate and check spread double MaxSpreadInPoints = 30; double Spread = Ask - Bid; if(Spread>MaxSpreadInPoints*Point) return(false); //+------------------------------------------------------------------+ double am = 0.000000001; // Set variable to a very small number double marginlevel; // Get the Free Margin MarginFree = AccountFreeMargin(); // Calculate Margin level if ( AccountMargin() != 0 ) am = AccountMargin(); marginlevel = AccountEquity() / am * 100; // Free Margin is less than the value of MinMarginLevel, so no trading is allowed if ( marginlevel < MinMarginLevel ) { Comment ( "Warning! Free Margin " + DoubleToStr ( marginlevel, 2 ) + " is lower than MinMarginLevel!" ); Alert ( "Warning! Free Margin " + DoubleToStr ( marginlevel, 2 ) + " is lower than MinMarginLevel!" ); return(0); } //+------------------------------------------------------------------+ if( TotalOrdersCount()==0 ) { int result=0; if((iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,1)<iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_LOWER,1))&&(iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,0)>iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_LOWER,0))) // Here is your open buy rule if((iRSI(NULL,0,Periode,PRICE_CLOSE,1)<Lowlevel)&&(iRSI(NULL,0,Periode,PRICE_CLOSE,0)>Lowlevel)) { if (!IsTradeContextBusy() && IsTradeAllowed()) result=OrderSend(Symbol(),OP_BUY,NR(Lot_Volume()),Ask,Slippage,0,0,"BOLLINGER_BANDS_RSI_ATR_EA",MagicNumber,0,Blue); if(result>0) { TheStopLoss=0; TheTakeProfit=0; if(TakeProfit>0) TheTakeProfit=Bid+TakeProfit*MyPoint; if(StopLoss>0) TheStopLoss=Bid-StopLoss*MyPoint; if(OrderSelect(result,SELECT_BY_TICKET)) bool modif1=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green); } return(0); } if((iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,1)>iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_UPPER,1))&&(iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,0)<iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_UPPER,0))) // Here is your open Sell rule if((iRSI(NULL,0,Periode,PRICE_CLOSE,1)>Highlevel)&&(iRSI(NULL,0,Periode,PRICE_CLOSE,0)<Highlevel)) { if (!IsTradeContextBusy() && IsTradeAllowed()) result=OrderSend(Symbol(),OP_SELL,NR(Lot_Volume()),Bid,Slippage,0,0,"BOLLINGER_BANDS_RSI_ATR_EA",MagicNumber,0,Red); if(result>0) { TheStopLoss=0; TheTakeProfit=0; if(TakeProfit>0) TheTakeProfit=Ask-TakeProfit*MyPoint; if(StopLoss>0) TheStopLoss=Ask+StopLoss*MyPoint; if(OrderSelect(result,SELECT_BY_TICKET)) bool modif2= OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green); } return(0); } } for(int cnt=0;cnt<OrdersTotal();cnt++) { if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)) if(OrderType()<=OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber ) { if(OrderType()==OP_BUY) { if(TrailingStop>0) { if(Bid-OrderOpenPrice()>MyPoint*TrailingStop) { if(OrderStopLoss()<Bid-MyPoint*TrailingStop) { bool modif3=OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,Green); return(0); } } } } else { if(TrailingStop>0) { if((OrderOpenPrice()-Ask)>(MyPoint*TrailingStop)) { if((OrderStopLoss()>(Ask+MyPoint*TrailingStop)) || (OrderStopLoss()==0)) { bool modif4=OrderModify(OrderTicket(),OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,Red); return(0); } } } } } } return(0); } int TotalOrdersCount() { int result=0; for(int i=0;i<OrdersTotal();i++) { if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES)) if (OrderMagicNumber()==MagicNumber) result++; } return (result); } //+------------------------------------------------------------------+ //Calculates Lot Size based on balance and factor //+------------------------------------------------------------------+ double NR(double thelot) { double maxlots=MarketInfo(Symbol(),MODE_MAXLOT), minilot=MarketInfo(Symbol(),MODE_MINLOT), lstep=MarketInfo(Symbol(),MODE_LOTSTEP); double lots=lstep*NormalizeDouble(thelot/lstep,0); lots=MathMax(MathMin(maxlots,lots),minilot); return (lots); } //+------------------------------------------------------------------+ double Lot_Volume() { lot=AccountBalance() * 0.01 /LotFactor ; return(lot); } //+------------------------------------------------------------------+ //| //+------------------------------------------------------------------+
    lefeuvr3 a joint une image
    bollingerbandsrsiatrea-mql4-12508
  • Mikiburger

    Merci pour le partage.
    Je viens de le lancer sur un compte démo.
  • Mikiburger

    Comme promis je vous reviens avec les résultats du trading de la semaine sur un compte démo (en temps réel via un VPS).
    Pour valider le backtesting j'ai également fait un backtest sur cette semaine.
    Le compte à un capital d'environs 10 000€. Ce qui détermine la taille des positions grâce au money management intégré au robot.

    Résultats:
    La stratégie à réalisé 6 trades sur la semaine (gain 218€) alors que le backtesting en a réalisé 7 (gain 352€).
    Autant en temps réel qu'en backtesting, tout les trades ont été gagnants.
    Il y a actuellement le dernier trade qui est encore ouvert.
    > La stratégie a donc été rentable cette semaine. Mais il faut confirmer la validité du backtest pour confirmer la rentabilité globale.

    Validation du backtest:
    Les 5 premiers trades sont tout à fait identiques entre le temps réel et le backtesting (gain de 147€)
    Ensuite il y a un trade que le backtest réalise mercredi à 11h47 qui n'a pas été réalisé par la stratégie en temps réel.
    Je ne sais pas pourquoi.
    Cette différence explique le décalage ensuite observé entre le temps réel et le backtest puisque la stratégie n'autorise pas d'ouvrir un deuxième trade si le précédent n'est pas fermé.
    La stratégie en temps réel a ouvert un trade mercredi à 21h00 qui n'a pas été réalisé en backtest car le trade ouvert n'était pas fermé.
    > Globalement on peut tout de même considérer le backtest comme représentatif de la réalité pour cette stratégie. (Ce qui n'est pas une généralité pour tous les robots, notamment les scalpers)

    La stratégie est donc globalement rentable.

    Proposition d'amélioration:
    Autoriser les trades multiple à chaque signal d'entrée.
    Mikiburger a joint une image
    bollingerbandsrsiatrea-mql4-12518
  • R231

    Backtest sur 10 ou 20 ans ça donne quoi ?
  • lefeuvr3

    Mikiburger
    Merci beaucoup pour ce retour de test
    Pour autoriser les trades multiples ,il suffirait ,au plus simple, d'ouvrir un autre graphe et d'y placer cet expert advisor
    Il faudrait supprimer ,dans les programme ,les deux lignes
    Code
    if (!IsTradeContextBusy() && IsTradeAllowed())
    On pourrait même,qui sait , decaler les prises de position en n'installant pas les experts au même moment.
    Bon week end
    Modifié le 2020-12-20 07:27:35 par lefeuvr3
  • Mikiburger

    Bonjour Gérard,

    J'ai peur d'avoir trop de trades si l'on procède aussi simplement.
    Il faudrait une variable de temps (optimisable) qui détermine le temps minimal entre chaque trades.
    Vu la fréquence des trades je vois bien un ordre de grandeur de 30 minutes ou d'une heure.

    Bonne journée,

    Mik
  • lefeuvr3

  • lefeuvr3

    Nouvelle version avec une pause après les trades...j'ai mis une pause de 2 secondes(... qui me semble la plus optimale)

    Code
    //+------------------------------------------------------------------+ //| BOLLINGER_BANDS_RSI_ATR_PAUSE.mq4 | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict //+------------------------------------------------------------------+ //BOLLINGER_BANDS_EA ...EURUSD ...1MN //+------------------------------------------------------------------+ extern int MagicNumber=07112020; extern int atrMultipleSL=19; extern int atrMultipleTP=11; extern int atrMultipleTS=12; extern int PeriodATR=1; extern int ShiftATR=0; extern int Slippage=3; extern int Indicatorperiod=39; extern int BBDeviation=2; extern double LotFactor =155; //lotsize factor double lot; double MarginFree; // Free margin in percentage extern double MinMarginLevel = 100; // Lowest allowed Margin level for new positions to be opened. extern double Lowlevel=49; extern double Highlevel=84; extern int Periode=12; datetime LastTradeTime = 0; extern int seconds=2; //+------------------------------------------------------------------+ // expert start function //+------------------------------------------------------------------+ int start() { double MyPoint=Point; if(Digits==3 || Digits==5) MyPoint=Point*10; double TheStopLoss=0; double TheTakeProfit=0; //+------------------------------------------------------------------+ double atr = iATR(NULL, 0, PeriodATR, ShiftATR); double StopLoss = (atr * atrMultipleSL / Point); double TakeProfit =(atr * atrMultipleTP / Point);//(atr * atrMultipleTP / Point); double TrailingStop=(atr * atrMultipleTS / Point); //+------------------------------------------------------------------+ //Calculate and check spread double MaxSpreadInPoints = 30; double Spread = Ask - Bid; if(Spread>MaxSpreadInPoints*Point) return(false); //+------------------------------------------------------------------+ double am = 0.000000001; // Set variable to a very small number double marginlevel; // Get the Free Margin MarginFree = AccountFreeMargin(); // Calculate Margin level if ( AccountMargin() != 0 ) am = AccountMargin(); marginlevel = AccountEquity() / am * 100; // Free Margin is less than the value of MinMarginLevel, so no trading is allowed if ( marginlevel < MinMarginLevel ) { Comment ( "Warning! Free Margin " + DoubleToStr ( marginlevel, 2 ) + " is lower than MinMarginLevel!" ); Alert ( "Warning! Free Margin " + DoubleToStr ( marginlevel, 2 ) + " is lower than MinMarginLevel!" ); return(0); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ if(LocalTime() - LastTradeTime < seconds) { Comment("Less than x seconds have elapsed after the last trade!", " The expert won't trade!"); return(-1); } // memorize the time of the last trade LastTradeTime = LocalTime(); //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ if( TotalOrdersCount()==0 ) { int result=0; if((iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,1)<iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_LOWER,1))&&(iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,0)>iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_LOWER,0))) // Here is your open buy rule if((iRSI(NULL,0,Periode,PRICE_CLOSE,1)<Lowlevel)&&(iRSI(NULL,0,Periode,PRICE_CLOSE,0)>Lowlevel)) { if (!IsTradeContextBusy() && IsTradeAllowed()) result=OrderSend(Symbol(),OP_BUY,NR(Lot_Volume()),Ask,Slippage,0,0,"BOLLINGER_BANDS_RSI_ATR_EA",MagicNumber,0,Blue); if(result>0) { TheStopLoss=0; TheTakeProfit=0; if(TakeProfit>0) TheTakeProfit=Bid+TakeProfit*MyPoint; if(StopLoss>0) TheStopLoss=Bid-StopLoss*MyPoint; if(OrderSelect(result,SELECT_BY_TICKET)) bool modif1=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green); } else return(0); } if((iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,1)>iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_UPPER,1))&&(iMA(NULL,PERIOD_M1,1,0,MODE_EMA,PRICE_CLOSE,0)<iBands(NULL,PERIOD_M1,Indicatorperiod,BBDeviation,0,PRICE_OPEN,MODE_UPPER,0))) // Here is your open Sell rule if((iRSI(NULL,0,Periode,PRICE_CLOSE,1)>Highlevel)&&(iRSI(NULL,0,Periode,PRICE_CLOSE,0)<Highlevel)) { if (!IsTradeContextBusy() && IsTradeAllowed()) result=OrderSend(Symbol(),OP_SELL,NR(Lot_Volume()),Bid,Slippage,0,0,"BOLLINGER_BANDS_RSI_ATR_EA",MagicNumber,0,Red); if(result>0) { TheStopLoss=0; TheTakeProfit=0; if(TakeProfit>0) TheTakeProfit=Ask-TakeProfit*MyPoint; if(StopLoss>0) TheStopLoss=Ask+StopLoss*MyPoint; if(OrderSelect(result,SELECT_BY_TICKET)) bool modif2= OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(TheStopLoss,Digits),NormalizeDouble(TheTakeProfit,Digits),0,Green); } else return(0); } } for(int cnt=0;cnt<OrdersTotal();cnt++) { if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)) if(OrderType()<=OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber ) { if(OrderType()==OP_BUY) { if(TrailingStop>0) { if(Bid-OrderOpenPrice()>MyPoint*TrailingStop) { if(OrderStopLoss()<Bid-MyPoint*TrailingStop) { bool modif3=OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,Green); return(0); } } } } else { if(TrailingStop>0) { if((OrderOpenPrice()-Ask)>(MyPoint*TrailingStop)) { if((OrderStopLoss()>(Ask+MyPoint*TrailingStop)) || (OrderStopLoss()==0)) { bool modif4=OrderModify(OrderTicket(),OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,Red); return(0); } } } } } } return(0); } int TotalOrdersCount() { int result=0; for(int i=0;i<OrdersTotal();i++) { if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES)) if (OrderMagicNumber()==MagicNumber) result++; } return (result); } //+------------------------------------------------------------------+ //Calculates Lot Size based on balance and factor //+------------------------------------------------------------------+ double NR(double thelot) { double maxlots=MarketInfo(Symbol(),MODE_MAXLOT), minilot=MarketInfo(Symbol(),MODE_MINLOT), lstep=MarketInfo(Symbol(),MODE_LOTSTEP); double lots=lstep*NormalizeDouble(thelot/lstep,0); lots=MathMax(MathMin(maxlots,lots),minilot); return (lots); } //+------------------------------------------------------------------+ double Lot_Volume() { lot=AccountBalance() * 0.01 /LotFactor ; return(lot); } //+------------------------------------------------------------------+ //| //+------------------------------------------------------------------+
    lefeuvr3 a joint une image
    bollingerbandsrsiatrea-mql4-12520
  • Mikiburger

    Bonjour Gérard,

    Pour moi 2 secondes est beaucoup trop insuffisant, nous sommes dans le même état du marché.
    Par exemple hier il y a eu une ouverture de trade à 10:49:24 et à 10:49:30 et après à 21:21:34 et 21:21:36.
    Ouvrir deux trades à 0,63 lots à si peu d'interval de temps revient à peu prêt à ouvrir un trade avec 1,26 lot.
    Tu doubles donc ton risque (ou + si il y a + d'ouvertures de trades). Donc ta perte latente sera d'autant plus grande et la claque aussi en cas de stop loss.
    Le money management prévu n'est plus respecté.
    Je pense vraiment qu'une période de 30 minutes entre chaque ouvertures de trade est un grand minimum.
  • lefeuvr3

    Salut Mikburger
    Pour obtenir cette latence de 30 minutes,que tu souhaites, il suffit de mettre les 1800 secondes qui correspondent à 30 minutes
    Code
    extern int seconds=1800;
    Bonne journée
    gerard