Limit consecutve losses per month on portfolio level

Gooda day!

Been trying to use this line of codes by sir @Tomasz on achieving properly my goal but i cant find correct solution.

What i am trying to achieve is to :

Limit consecutive losses per month on portfolio level and reset counter of losses at last day of month.

dn= Datenum();
tn= Timenum();
newday = dn != Ref(dn, -1);

//within the same month , if 4 consecutive losses on any symbol
//skip the following entry signal after consecutive losses of 4 and by
//every last day of month reset counting of consecutive losses to 0.
//resume counting of consloss on fisrtday of month and so on and so forth.

fisrtdayofmonth = month() != Ref(Month(), -1);
lastdayofmonth = TimeFrameExpand(1, inMonthly, ExpandPoint);


SetCustomBacktesterProc("");

if( Status("Action") == actionPortfolio ){
  
bo.GetBacktesterObject();
bo.PreProcess();

for(i = 0; i < BarCount; i++) {

  if( inNewMonth[i] ) {

        losses = 0; //initialize here or outside bar
        prevprofit = 0;

    for(trade=bo.GetFirstTrade();trade;trade=bo.GetNextTrade()){
        
        profit = trade.GetProfit();

      if( losses < 4 ){
          

        if( profit > 0 ) losses = 0;
        else
        {
          if( prevprofit > 0  AND  ) losses = 0;
          else
          losses++;    
          if( lastdayofmonth )
              losses  = 0;
        }
        prevprofit = profit;
      }
    }
   
  for(sig=bo.GetFirstSignal(i);sig;sig=bo.GetNextSignal(i) ){
      
     if( sig.IsEntry() AND losses >= 4 ) 
         sig.Price = -1;// this line totally skip all entry signal after 4 consecutive losses.
         /* how can i reset "consloss" counter to 0 at every firstday of month and start 
         counting consloss until end of month ? */
    
  }
  bo.ProcessTradeSignals(i);
}
bo.PostProcess();

}



For starters, your code never defines the variable inNewMonth, so it wouldn't run even if you had included some Phase 1 logic to set Buy and Sell signals and prices. If you want help, please post complete working code. See #3 here: How to ask a good question

1 Like

Hi Matt , Thanks for pointing out. here are the few lines of code i am using to test the idea.
By the i am testing it on norgate data.

SetSortColumns(5);
ma20 = MA( C , 20 );
ma50 = MA(C, 50 );

//sample buy&sell rule for testing idea only
Buy = RSI(14) > 70;
Sell = Cross( ma20, ma50 ); 

ApplyStop( stopTypeLoss , stopModePercent, 5 );

newmonth = Month() != Ref(Month(), -1 );
lastdayofmonth = TimeFrameExpand( 1, inMonthly, expandPoint );
inNewMonth = Flip( newmonth , lastdayofmonth );

SetCustomBacktestProc("");

if (Status("action") == actionPortfolio) 
{
    bo = GetBacktesterObject();	
    bo.PreProcess();	
    dt = DateTime();
    
    for (i = 0; i < BarCount; i++)	
    {
        consLoss = 0;
        prevProfit = 0;
        cnt = 0;
        
        if( inNewMonth[i] ){
        
		  for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
		  {
		  
		  
		   if( consLoss < 3 )
		    {
			   profit = trade.GetProfit();
			   
			   if( profit >= 0 )  consLoss = 0;
			   else
			   {
				 if( prevProfit >= 0 ) consLoss = 0;
				 else  
				 consLoss++;
				}
				prevProfit = profit;
			}	  	
		  }
		}
		else
		consLoss = 0;
		
		_TRACE( "Date&Time: " + DateTimeToStr(dt[i]) +" inNewMonth: "+ Nz( inNewMonth[i] ) + " lastdayofmonth: " + Nz( lastdayofmonth[i] ) + "  consLoss: " + consLoss + 
                " SkiP Signals count: " + cnt ); 
                
        if(lastdayofmonth[i])
        _TRACE( "Date&Time: " + DateTimeToStr(dt[i]) +" inNewMonth: "+ Nz( inNewMonth[i] ) + " lastdayofmonth: " + Nz( lastdayofmonth[i] ) + "  consLoss: " + consLoss + 
                " SkiP Signals count: " + cnt );

        for (sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
        {	

			if( consLoss >= 3 AND sig.IsEntry() ) 
			    
			    if( consLoss >= 3  )
			    sig.Price = -1; // SKIP signal
			    cnt++; //counting skip signals for info only
					  
			 //   _TRACE("Date&Time: " + DateTimeToStr(dt[i]) + "  consLoss: " + consLoss + " SkiP Signals count: " + cnt );
        }	
      
        bo.ProcessTradeSignals( i );	
    }	  
      
    bo.PostProcess();	
} 

This code is not perfect, but it gets you close. It only counts consecutive losses for the "current" month and year, i.e. the month and year corresponding to the bar indicated by the index "i" in your outer loop.

I say it's not perfect because it will allow a new entry on the day that the 3rd loss occurs. The only way to prevent that would be to write a low level CBT and handle your own entries and exits.

SetSortColumns(5);
ma20 = MA( C , 20 );
ma50 = MA(C, 50 );

//sample buy&sell rule for testing idea only
Buy = RSI(14) > 70;
Sell = Cross( ma20, ma50 ); 

ApplyStop( stopTypeLoss , stopModePercent, 5, 1, False, 1 );

newmonth = Month() != Ref(Month(), -1 );
lastdayofmonth = TimeFrameExpand( 1, inMonthly, expandPoint );
inNewMonth = Flip( newmonth , lastdayofmonth );

dn = DateNum();
maxConsLoss = 3;

SetCustomBacktestProc("");

if (Status("action") == actionPortfolio) 
{
    bo = GetBacktesterObject();	
    bo.PreProcess();	
    dt = DateTime();
    
    prevMonthYear = floor(dn[0]/100);
    isTradingAllowed = True;
    
    for (i = 0; i < BarCount; i++)	
    {
		currMonthYear = floor(dn[i]/100);
      
        bo.ProcessTradeSignals( i );
        
   		if (isTradingAllowed OR currMonthYear != prevMonthYear)
		{
			consLoss = 0;
			isTradingAllowed = True;
			
			for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
			{
				tradeMonthYear = floor(DateTimeConvert(0, trade.ExitDateTime) / 100); 
				if (tradeMonthYear == currMonthYear)
				{
					profit = trade.GetProfit();
					if (profit >= 0)
					{
						consLoss = 0;
					}
					else
					{
						++consLoss;
						_TRACE(NumToStr(dn[i],8.0,False)+": "+trade.Symbol+" consLoss="+consLoss);
						if (consLoss >= maxConsLoss)
						{
							isTradingAllowed = False;
							_TRACE(NumToStr(dn[i],8.0,False)+": isTradingAllowed = False");
							break;
						}
					}
				}
			}
		}
		
		if (!isTradingAllowed)
		{
			cnt = 0;
			for (sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
			{	
				if(sig.IsEntry()) 
				{
					sig.Price = -1; // SKIP signal
					cnt++; //counting skip signals for info only
				}	  
				 //   _TRACE("Date&Time: " + DateTimeToStr(dt[i]) + "  consLoss: " + consLoss + " SkiP Signals count: " + cnt );
			}	
		}
				
        prevMonthYear = currMonthYear;	
    }	  
      
    bo.PostProcess();	
}
2 Likes

Many Thanks sir @mradtke , will try this and understand more deeper as i get back to home later.