Martingale/consecutive win count works in tester but not live?

 

Hi,

My code for adding Martingale money management to include in the lotsize calculation works in the tester but doesn't appear to work in a live account.

(Please note my code isn't the prettiest, or possible the most efficient, but it did seem to work in tester, so appologese for posting so much code)

I have two Martingale esq techniques which can be selectable.

0= start at 2% increase by 1% if win to a max of 10%. If there is a loss return to 2%

1= start at 2% increase by 1% if win to a max of 10%. If there is a loss decrease by 1%

I do not include this code in the Start area, instead they are functions, which are only called by the Lotsize() which only runs if the entry criteria is met. My reason (rightly or wrongly) for doing this was that this would not be then calculated every tick, which would slow down my testing.

I will attempt to try to rewrite this today, to see if I can get it to work, but it would be useful to know if there is something that I am doing which is fundamentally wrong. My initial thoughts are there is something wrong with the getlastorderstatus function so will start here.

thanks

Simon

First part of code shows the Lotsize function being called when entry criteria is met - this is in the expert start function.

if (Trend == UpTrend)
    {
    if(MarketInfo(Symbol(),MODE_SPREAD) < MaximumSpread)
    if (OrderOpened <1)
    if (BarCheck() == true)
      if (LowestPrice > SL)
         if (DTOSCCheck ()== true)
         if ((EL+UsePoint) - buyprice < Point/2)
         
               OpenBuyOrder(LotSize(),SL,TP);
         
   
    if (TotalOrderCount(Symbol(), MagicNumber)>0){OrderOpened=1;}
    }

then here is the Lotsize function

//////Lotsize function

double LotSize()
{
     if (MartingaleType == 0)
      {
      totalConsectiveWins = totalConsectiveWins + getLastClosedOrderStatus();
              totalConsectiveWins = MathMin(totalConsectiveWins,10-EquityPercent);
              totalConsectiveWins = MathMax(totalConsectiveWins,0);


              if (totalConsectiveWins > 0 && (LastOrder < 0))  // this resets the consecutive wins back to zero if there is a loss
              {totalConsectiveWins = 0;}
              else totalConsectiveWins = totalConsectiveWins;
         
        
              if (AgressiveEquityIncrease) MaxPctLoss = EquityPercent+totalConsectiveWins;
              else MaxPctLoss = EquityPercent;

      // Lot size calculation
      // sets the dynamic lotsize
      if(DynamicLotSize == true)
      {
       RiskAmount = (AccountFreeMargin() * (MaxPctLoss / 100));
      double TickValue = MarketInfo(Symbol(),MODE_TICKVALUE);
      if(Point == 0.001 || Point == 0.00001) TickValue *= 10;
      stoploss = SL_Pips / UsePoint;
      if ( stoploss != 0)
      {CalcLots = NormalizeDouble(RiskAmount / stoploss / TickValue,2);}
      else
            { Alert("WARNING: stoploss == 0 !"); } //-  -turned off for optimization
      LotSize = CalcLots;
      }
      else LotSize = FixedLotSize;


      // Lot size verification based on brokers

      if(LotSize < MarketInfo(Symbol(),MODE_MINLOT))
      {
      LotSize = MarketInfo(Symbol(),MODE_MINLOT);
      }
      else if(LotSize > MarketInfo(Symbol(),MODE_MAXLOT))
      {
      LotSize = MarketInfo(Symbol(),MODE_MAXLOT);
      }
      if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.1)
      {
      LotSize = NormalizeDouble(LotSize,1);
      }
      else LotSize = NormalizeDouble(LotSize,2);
      //Print(StringConcatenate(" |CalcLots = ",CalcLots," |Lotsize = ",LotSize," |stoploss=",DoubleToStr(stoploss,4)," |EquityPercent = ",
      //  DoubleToStr(EquityPercent/100,5)," |RiskAmount = ",DoubleToStr(RiskAmount,2)," |Max%Loss = ",DoubleToStr(MaxPctLoss,2)," 
      // |AccountFreeMargin = ",AccountFreeMargin()));


      //Sets the Martingale esque / agressive lotsize
      // Percentage increases 1 % at a time for a maximum of 10 percent if consecutuve wins keeps increasing.

        
              //Print (" totalConsectiveWins = ",totalConsectiveWins," LastOrder= ",LastOrder);
        
      ///Check Lotsize against the initial margin required. This has to be done as if increasing the percentage used
      // often you will run out of margin. So Lotsize can only be as big as the margin allows.
      // On a broker using 50:1 leverage this can be quite restrictive to the Agressive lotsizing.

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;

      return (LotSize);
      }
      
      else if (MartingaleType == 1)
      {
      totalConsectiveWins = totalConsectiveWins + getLastClosedOrderStatus();
           totalConsectiveWins = MathMin(totalConsectiveWins,10-EquityPercent);
           totalConsectiveWins = MathMax(totalConsectiveWins,0);

        
        if (AgressiveEquityIncrease) MaxPctLoss = EquityPercent+totalConsectiveWins;
        
        //Print (" totalConsectiveWins = ",totalConsectiveWins," LastOrder= ",LastOrder);
        
///Check Lotsize against the initial margin required. This has to be done as if increasing the percentage used
// often you will run out of margin. So Lotsize can only be as big as the margin allows.
// On a broker using 50:1 leverage this can be quite restrictive to the Agressive lotsizing.

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;
      
      if (AgressiveEquityIncrease) MaxPctLoss = EquityPercent+totalConsectiveWins;
              else MaxPctLoss = EquityPercent;

      // Lot size calculation
      // sets the dynamic lotsize
      if(DynamicLotSize == true)
      {
         RiskAmount = (AccountFreeMargin() * (MaxPctLoss / 100));
          TickValue = MarketInfo(Symbol(),MODE_TICKVALUE);
      if(Point == 0.001 || Point == 0.00001) TickValue *= 10;
      stoploss = SL_Pips / UsePoint;
      if ( stoploss != 0)
      {CalcLots = NormalizeDouble(RiskAmount / stoploss / TickValue,2);}
      else
            { Alert("WARNING: stoploss == 0 !"); } //-  -turned off for optimization
      LotSize = CalcLots;
      }
      else LotSize = FixedLotSize;


      // Lot size verification based on brokers

      if(LotSize < MarketInfo(Symbol(),MODE_MINLOT))
      {
      LotSize = MarketInfo(Symbol(),MODE_MINLOT);
      }
      else if(LotSize > MarketInfo(Symbol(),MODE_MAXLOT))
      {
      LotSize = MarketInfo(Symbol(),MODE_MAXLOT);
      }
      if(MarketInfo(Symbol(),MODE_LOTSTEP) == 0.1)
      {
      LotSize = NormalizeDouble(LotSize,1);
      }
      else LotSize = NormalizeDouble(LotSize,2);
      //Print(StringConcatenate(" |CalcLots = ",CalcLots," |Lotsize = ",LotSize," |stoploss=",DoubleToStr(stoploss,4)," |EquityPercent = ",
      // DoubleToStr(EquityPercent/100,5)," |RiskAmount = ",DoubleToStr(RiskAmount,2)," |Max%Loss = ",DoubleToStr(MaxPctLoss,2)," 
      // |AccountFreeMargin = ",AccountFreeMargin()));


      //Sets the Martingale esque / agressive lotsize
      // Percentage increases 1 % at a time for a maximum of 10 percent if consecutuve wins keeps increasing.

   
  
  
  
  
   
        
              //Print (" totalConsectiveWins = ",totalConsectiveWins," LastOrder= ",LastOrder);
        
      ///Check Lotsize against the initial margin required. This has to be done as if increasing the percentage used
      // often you will run out of margin. So Lotsize can only be as big as the margin allows.
      // On a broker using 50:1 leverage this can be quite restrictive to the Agressive lotsizing.

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;

      return (LotSize);

      }

}

and here is the getlastorder status function

/////////////////////Agressive Lot Size - Martingale

int getLastClosedOrderStatus()
{
      if (MartingaleType == 0)
      {
      int last_closed_order_ticket;
      bool local_result;

      int last_closed_time = 0;


      for(int k=OrdersHistoryTotal();k>=0;k--) // Check the  orders in history

      {
        
              if(OrderSelect(k,SELECT_BY_POS,MODE_HISTORY))

              {
            if (OrderMagicNumber()!=MagicNumber) continue;
                      if(OrderCloseTime()>last_closed_time)

                      {
        
                      last_closed_time=OrderCloseTime();
        
                      last_closed_order_ticket=OrderTicket();
                      local_result = OrderProfit()>0;

                      }

              }

         }

         if(LastClosedTradeTicket == last_closed_order_ticket) return(0);

         LastClosedTradeTicket = last_closed_order_ticket;

         if(local_result) LastOrder=1;
         else LastOrder = -1;
         return (LastOrder);
         }
      else if (MartingaleType == 1)
      {
       
      

       last_closed_time = 0;


      for( k=OrdersHistoryTotal();k>=0;k--) // Check the  orders in history

      {
        
              if(OrderSelect(k,SELECT_BY_POS,MODE_HISTORY))

              {
            if (OrderMagicNumber()!=MagicNumber) continue;
                      if(OrderCloseTime()>last_closed_time)

                      {
        
                      last_closed_time=OrderCloseTime();
        
                      last_closed_order_ticket=OrderTicket();
                      local_result = OrderProfit()>0;

                      }

              }

      }

      if(LastClosedTradeTicket == last_closed_order_ticket) return(0);

      LastClosedTradeTicket = last_closed_order_ticket;

      if(local_result) return(1);
      else return(-1);

            }

}
 

hi simoncs, im also a fan of martingale but i cant understand the concept of martingale u using as u know im a beginner so many of ur code i cant understand. can u tell me in simple english how is ur martingale concept works?

2. im also experience some problem when i backtest it in demo account. my code is ok no problem. Most of the time it work but sometimes it just didnt work it suppose to. I wonder why? :(

 
simoncs:

Hi,

My code for adding Martingale money management to include in the lotsize calculation works in the tester but doesn't appear to work in a live account.

(Please note my code isn't the prettiest, or possible the most efficient, but it did seem to work in tester, so appologese for posting so much code)

You didn't actually say what doesn't work that should work or what it does that it shouldn't . . . you just said it doesn't work . . . . does it place trades ? you need to be specific about what the issue is . . . Strategy Tester to live issues are usually an ECN issue.

Validate your lot size properly, what you have will not work for all symbols, do it properly once, this thread will help: https://www.mql5.com/en/forum/146040

This is wrong:

for( k=OrdersHistoryTotal();k>=0;k--) // Check the  orders in history

If you have 5 orders in your History Pool their positions are 0, 1, 2, 3, 4 you start at OrdersHistoryTotal(), 5, and decrement to 0 so you have 5, 4, 3, 2, 1, 0 that is 6, how does that work ?

 

Sorry, you're right I didn't...

trades are taken as expected, but even if there are consecutive wins the MaxPctLoss stays at 2% (the EquityPercent ext variable). Therefore the Lotsize is calculated only at 2% instead of being 3% for the next trade and so on. However in Tester, it was increasing as it should.

I have made a start at rewriting this, as the code is very messy, but I haven't finished yet - once I have I will repost.

I will look closer at my Lotsize calc - were you referring to WHR's post specifically? https://www.mql5.com/en/forum/137741

I will also look at the loop for the ordershistorytotal.

Can you confirm that I can use these in functions though and only call them when the trade criteria is met? I want to be able to shut down the ea and restart it with it remembering the correct totalconsecutivetrade count. So i don't need to have all this code in the Start function?

@springyard - I use martingale in the loosest of definitions - essentially it would fall into an anti martingale technique. Sing if your winning so to speak :) Martingale is usually used to increment your lotsize by a factor for each losing trade. I am increasing my risk each time I win. May seem odd, but if you have an EA with a very high win rate then it seems to work (in backtesting).

 
simoncs:

Sorry, you're right I didn't...

trades are taken as expected, but even if there are consecutive wins the MaxPctLoss stays at 2% (the EquityPercent ext variable). Therefore the Lotsize is calculated only at 2% instead of being 3% for the next trade and so on. However in Tester, it was increasing as it should.

I have made a start at rewriting this, as the code is very messy, but I haven't finished yet - once I have I will repost.

I will look closer at my Lotsize calc - were you referring to WHR's post specifically? https://www.mql5.com/en/forum/137741

I will also look at the loop for the ordershistorytotal.

Can you confirm that I can use these in functions though and only call them when the trade criteria is met? I want to be able to shut down the ea and restart it with it remembering the correct totalconsecutivetrade count. So i don't need to have all this code in the Start function?

No, I wasn't specifically referring to WHRoeder's post . . .

There is no problem at all putting your code into functions, it's good practice and it can help with testing and code reuse.

The loop is wrong, there is no question about that, it may well be causing your issue . . . you might want to fix it on your existing code and test before re-writing and finding new issues to address.

 
RaptorUK:

No, I wasn't specifically referring to WHRoeder's post . . .

There is no problem at all putting your code into functions, it's good practice and it can help with testing and code reuse.

The loop is wrong, there is no question about that, it may well be causing your issue . . . you might want to fix it on your existing code and test before re-writing and finding new issues to address.


thanks, i tried to fix the existing loop but it didn't seem to work. I have now rewritten the code - much neater, and far less of it. And most importantly it seems to work now.

so in particular i changed the loop to - for(int i=OrdersHistoryTotal()-1;i>=0;i--) - - adding -1 as a starting point for the most recent order - is this what you meant?

i also cut down the LotSize function so that code wasn't duplicated for each Martingale type, and amended the minlot/lotstep part - does that look better?

////Total Consecutive Trade

int TotalConsecutiveWins ()
{
int WinCount=0;
   for(int k=OrdersHistoryTotal()-1;k>=0;k--)
   {
   OrderSelect(k,SELECT_BY_POS,MODE_HISTORY);
   if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      {
      if(OrderProfit() > 0) WinCount++;
      if (OrderProfit() < 0) WinCount--;
      }
   }
   return (WinCount);
}


/////////////////////Agressive Lot Size - Martingale

int getLastClosedOrderStatus()
{

for(int i=OrdersHistoryTotal()-1;i>=0;i--)
 {
 int last;
   OrderSelect(i, SELECT_BY_POS,MODE_HISTORY);  
   if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
    {
       
       if(OrderProfit() > 0) last=1;
       if(OrderProfit() < 0) last=-1;
       break;
    }
}
return(last);
}

Lotsize function

//////Lotsize function

double LotSize()
{
   if(AgressiveEquityIncrease)
   {
     if (MartingaleType == 0)
      {
      if (getLastClosedOrderStatus() ==-1)MaxPctLoss = EquityPercent; //if loss then return to EquityPercent
      else if (getLastClosedOrderStatus() ==1) MaxPctLoss = MathMin(EquityPercent+TotalConsecutiveWins (),10); // if win, increase by 1% - can never exceed 10% risk
           }
           
            else if (MartingaleType == 1)
       {
       MaxPctLoss = MathMin(EquityPercent+TotalConsecutiveWins (),10); //can never exceed 10% risk
       }
      if (MaxPctLoss < EquityPercent) MaxPctLoss = EquityPercent;  //Risk can never be less than the EquityPercent - even if series of losing trades
         }
         else MaxPctLoss = EquityPercent;    
              
              

      // Lot size calculation
      // sets the dynamic lotsize
      if(DynamicLotSize == true)
      {
       RiskAmount = (AccountFreeMargin() * (MaxPctLoss / 100));
      double TickValue = MarketInfo(Symbol(),MODE_TICKVALUE);
      if(Point == 0.001 || Point == 0.00001) TickValue *= 10;
      stoploss = SL_Pips / UsePoint;
      if ( stoploss != 0)
      {CalcLots = NormalizeDouble(RiskAmount / stoploss / TickValue,2);}
      else
            { Alert("WARNING: stoploss == 0 !"); } //-  -turned off for optimization
      LotSize = CalcLots;
      }
      else LotSize = FixedLotSize;


      // Lot size verification to account for different brokers
   double minLot = MarketInfo(Symbol(), MODE_MINLOT);
   double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   LotSize = MathFloor(LotSize/lotStep)*lotStep;
   if (LotSize<minLot)LotSize=minLot;    
   
      
        
      ///Check Lotsize against the initial margin required. This has to be done as if increasing the percentage used
      // often you will run out of margin. So Lotsize can only be as big as the margin allows.
      // On a broker using 50:1 leverage this can be quite restrictive to the Agressive lotsizing.

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;

      return (LotSize);
}

Whilst going through a number of the threads you suggested I saw there are issues with using tickvalue, so I think I should include that too?

thanks for your help!!!

 
simoncs:


Lotsize function

OK, so you do this to validate your LotSize . . .

      // Lot size verification to account for different brokers
   double minLot = MarketInfo(Symbol(), MODE_MINLOT);
   double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   LotSize = MathFloor(LotSize/lotStep)*lotStep;
   if (LotSize<minLot)LotSize=minLot;   

great !!

And then do this which may balls it all up again . . .

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;

Put the validation in just before where you intend to use LotSize in a trading function or, in this case, just before you return the value from the function.

 
simoncs:


thanks, i tried to fix the existing loop but it didn't seem to work. I have now rewritten the code - much neater, and far less of it. And most importantly it seems to work now.

so in particular i changed the loop to - for(int i=OrdersHistoryTotal()-1;i>=0;i--) - - adding -1 as a starting point for the most recent order - is this what you meant?

Yes that is what I was referring to.

Your comment and function naame says . . .

////Total Consecutive Trade

int TotalConsecutiveWins ()

. . . implying that what you are trying to do is count the number of consecutive wins . . . but what you are actually doing is calculating the difference between number of wins and losses regardless of any of them being consecutive or not, is that what you wanted ?

 
RaptorUK:


Your comment and function naame says . . .

. . . implying that what you are trying to do is count the number of consecutive wins . . . but what you are actually doing is calculating the difference between number of wins and losses regardless of any of them being consecutive or not, is that what you wanted ?


hmmm - yup you're right - i can see a flaw in my code now with the Martingaletype = 0. I hadn't fully tested it yet (only on a small amount of data - as waiting for an optimization to finish). The Martingaletype =1 should work as expected as Wincount increases or decreases with profit or loss trades and therefore so does the MaxpctLoss. I will revisit the first one though and do some more testing.....
 
simoncs:

hmmm - yup you're right - i can see a flaw in my code now with the Martingaletype = 0. I hadn't fully tested it yet (only on a small amount of data - as waiting for an optimization to finish). The Martingaletype =1 should work as expected as Wincount increases or decreases with profit or loss trades and therefore so does the MaxpctLoss. I will revisit the first one though and do some more testing.....


so i think i fixed the issues with the martingale now, and put the lotsize qualification at the end of the function.

//////Lotsize function

double LotSize()
{
   if(AgressiveEquityIncrease)
   {
     if (MartingaleType == 0)
      
      {
         if (getLastClosedOrderStatus() ==-1)
         {
         MaxPctLoss = EquityPercent; //if loss then return to EquityPercent
         ConsecutiveWinReset=0;
         }
         else if (getLastClosedOrderStatus() ==1) 
         {
         ConsecutiveWinReset=ConsecutiveWinReset + getLastClosedOrderStatus() ;
         MaxPctLoss = MathMin(EquityPercent+ConsecutiveWinReset,10); // if win, increase by 1% - can never exceed 10% risk
         }
           }
           
            else if (MartingaleType == 1)
       {
       MaxPctLoss = MathMin(EquityPercent+TotalConsecutiveWins (),10); //can never exceed 10% risk
       }
      if (MaxPctLoss < EquityPercent) MaxPctLoss = EquityPercent;  //Risk can never be less than the EquityPercent - even if series of losing trades
      if (EquityPercent+TotalConsecutiveWins ()>=10)MaxPctLoss=10;
      if (EquityPercent+TotalConsecutiveWins ()>=10 &&getLastClosedOrderStatus() ==-1 )MaxPctLoss--;
         }
         else MaxPctLoss = EquityPercent;    
              
              

      // Lot size calculation
      // sets the dynamic lotsize
      if(DynamicLotSize == true)
      {
       RiskAmount = (AccountFreeMargin() * (MaxPctLoss / 100));
      TickValue = PipValuePerLot(Symbol());
      stoploss = SL_Pips() / pips2dbl;
      if ( stoploss != 0)
      {CalcLots = NormalizeDouble(RiskAmount / stoploss / TickValue,2);}
      else
            { Alert("WARNING: stoploss == 0 !"); } //-  -turned off for optimization
      LotSize = CalcLots;
      }
      else LotSize = FixedLotSize;
      
      
      ///Check Lotsize against the initial margin required. This has to be done as if increasing the percentage used
      // often you will run out of margin. So Lotsize can only be as big as the margin allows.
      // On a broker using 50:1 leverage this can be quite restrictive to the Agressive lotsizing.

      MaxMarginLotSize = (AccountFreeMargin() - RiskAmount) / MarketInfo(Symbol(),MODE_MARGINREQUIRED);

      if (LotSize > MaxMarginLotSize) 
      {LotSize = MaxMarginLotSize;}
      else LotSize = LotSize;


      // Lot size verification to account for different brokers
   double minLot = MarketInfo(Symbol(), MODE_MINLOT);
   double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   LotSize = MathFloor(LotSize/lotStep)*lotStep;
   if (LotSize<minLot)LotSize=minLot;                                                                                                                                                                                             
   
      
        

      return (LotSize);
}
Reason: