September 26, 2015
Limit number of trades per day in a backtest
NOTE: The codes presented below are for intraday data only.
The scenario is as follows: we are intraday traders and we want to limit the number of trades made per day per symbol.
To simulate such scenario in a backtest, we need to count the signals and remove them accordingly after we reach our limit. There are several methods to do so and the choice depends on the signals that our system generates.
If our trading signals come in a sequence like Buy-Sell-Buy-Sell (without repeated signals in between), then we could just count BUY signals since the beginning of the day and allow first N of these signals, where N is the number of trades we allow. This can be achieved with Sum function:
// trades limit
N = 2;
Plot( Close, "Close", colorDefault, styleBar );
// identify new day
dn = DateNum();
newDay = dn != Ref( dn,-1);
// buy and sell signals
Buy = Cross( MACD(), Signal() );
Sell = Cross( Signal(), MACD() );
// visualize signals with yellow arrows
PlotShapes(Buy*shapeUpArrow, colorYellow, 0, Low);
PlotShapes(Sell*shapeDownArrow, colorYellow, 0, High);
// modify Buy array and allow only first N signals
Buy = Buy AND Sum( Buy, BarsSince( newDay) +1 ) <= N;
// visualize modified signals with green triangles
PlotShapes(Buy*shapeUpTriangle, colorGreen, 0, Low, -24)
If the signals of the same type may get repeated and occur for example in sequence like Buy-Buy-Buy-Sell, then before counting the entry signals we would first need to remove redundant ones. This can be achieved with Equity( 1 ) function call, which will remove repeated signals the way backtester would handle them:
// trades limit
N = 2;
Plot( Close, "Close", colorDefault, styleBar );
// identify new day
dn = DateNum();
newDay = dn != Ref( dn, -1 );
// buy and sell signals
Buy = MACD() > Signal(); // sample repeated signals
// exit on signal vs macd crossover or last bar of the day
Sell = Cross( Signal(), MACD() ) OR Ref( newday, 1 );
// visualize signals with yellow arrows
PlotShapes( Buy*shapeUpArrow, colorYellow, 0, Low );
PlotShapes( Sell*shapeDownArrow, colorred, 0, High );
// remove redundant signals
Equity( 1 );
// modify Buy array and allow only first N signals
Buy = Buy AND Sum( Buy, BarsSince( newDay ) + 1 ) <= N;
// visualize modified signals with green triangles
PlotShapes( Buy*shapeUpTriangle, colorGreen, 0, Low, -24 )
When our trading system uses complex trading rules so we don’t know the order of signals, we can use a loop to process signals and count trades.
// trades limit
N = 2;
Plot( Close, "Close", colorDefault, styleBar );
// identify new day
dn = DateNum();
newDay = dn != Ref( dn, -1 );
// buy and sell signals
// sample repeated signals
Buy = MACD() > Signal();
//exit on signal vs macd crossover or last bar of the day
Sell = Cross( Signal(), MACD() ) OR Ref( newday, 1 );
// visualize signals with yellow arrows
PlotShapes( Buy*shapeUpArrow, colorYellow, 0, Low );
PlotShapes( Sell*shapeDownArrow, colorred, 0, High );
tradeCount = onBuy = 0;
for( i = 0; i < BarCount; i++ )
{
// reset trade counter on the new day
if( newDay[ i ] ) tradeCount = 0;
// keep buy signal if there is no trade and trade count did not hit the limit
if( Buy[ i ] AND tradeCount < N AND NOT onBuy )
{
OnBuy = 1;
TradeCount++;
}
else
Buy[ i ] = 0; // ignore other buy signals
if( onBuy AND Sell[ i ] )
{
onBuy = 0; // reset onBuy flag on exit
}
}
// visualize modified signals with green triangles
PlotShapes( Buy*shapeUpTriangle, colorGreen, 0, Low, -24 )
Filed by Tomasz Janeczko at 6:23 pm under Backtest
Comments Off on Limit number of trades per day in a backtest