{"id":1201,"date":"2015-09-26T18:23:05","date_gmt":"2015-09-26T23:23:05","guid":{"rendered":"http:\/\/www.amibroker.com\/kb\/?p=1201"},"modified":"2015-10-02T18:41:11","modified_gmt":"2015-10-02T23:41:11","slug":"limit-number-of-trades-per-day-in-a-backtest","status":"publish","type":"post","link":"https:\/\/www.amibroker.com\/wordpress\/kb\/2015\/09\/26\/limit-number-of-trades-per-day-in-a-backtest\/","title":{"rendered":"Limit number of trades per day in a backtest"},"content":{"rendered":"

NOTE: The codes presented below are for intraday data only.<\/em><\/p>

The scenario is as follows: we are intraday traders and we want to limit the number of trades made per day per symbol.<\/p>

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.<\/p>

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:<\/p><\/span>\/\/ trades limit
<\/span>N <\/span>= <\/span>2<\/span>;

<\/span>Plot<\/span>( <\/span>Close<\/span>, <\/span>"Close"<\/span>, <\/span>colorDefault<\/span>, <\/span>styleBar <\/span>);

<\/span>\/\/ identify new day
<\/span>dn <\/span>= <\/span>DateNum<\/span>();
<\/span>newDay <\/span>= <\/span>dn <\/span>!= <\/span>Ref<\/span>( <\/span>dn<\/span>,-<\/span>1<\/span>);

<\/span>\/\/ buy and sell signals
<\/span>Buy <\/span>= <\/span>Cross<\/span>( <\/span>MACD<\/span>(), <\/span>Signal<\/span>() );
<\/span>Sell <\/span>= <\/span>Cross<\/span>( <\/span>Signal<\/span>(), <\/span>MACD<\/span>() );

<\/span>\/\/ visualize signals with yellow arrows
<\/span>PlotShapes<\/span>(<\/span>Buy<\/span>*<\/span>shapeUpArrow<\/span>, <\/span>colorYellow<\/span>, <\/span>0<\/span>, <\/span>Low<\/span>);
<\/span>PlotShapes<\/span>(<\/span>Sell<\/span>*<\/span>shapeDownArrow<\/span>, <\/span>colorYellow<\/span>, <\/span>0<\/span>, <\/span>High<\/span>);

<\/span>\/\/ modify Buy array and allow only first N signals
<\/span>Buy <\/span>= <\/span>Buy <\/span>AND <\/span>Sum<\/span>( <\/span>Buy<\/span>, <\/span>BarsSince<\/span>( <\/span>newDay<\/span>) +<\/span>1 <\/span>) <= <\/span>N<\/span>;

<\/span>\/\/ visualize modified signals with green triangles
<\/span>PlotShapes<\/span>(<\/span>Buy<\/span>*<\/span>shapeUpTriangle<\/span>, <\/span>colorGreen<\/span>, <\/span>0<\/span>, <\/span>Low<\/span>, -<\/span>24<\/span>)<\/code>

\"Price<\/p>

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:<\/p><\/span>\/\/ trades limit
<\/span>N <\/span>= <\/span>2<\/span>;

<\/span>Plot<\/span>( <\/span>Close<\/span>, <\/span>"Close"<\/span>, <\/span>colorDefault<\/span>, <\/span>styleBar <\/span>);

<\/span>\/\/ identify new day
<\/span>dn <\/span>= <\/span>DateNum<\/span>();
<\/span>newDay <\/span>= <\/span>dn <\/span>!= <\/span>Ref<\/span>( <\/span>dn<\/span>, -<\/span>1 <\/span>);

<\/span>\/\/ buy and sell signals
<\/span>Buy <\/span>=  <\/span>MACD<\/span>() > <\/span>Signal<\/span>(); <\/span>\/\/ sample repeated signals
\/\/ exit on signal vs macd crossover or last bar of the day
<\/span>Sell <\/span>= <\/span>Cross<\/span>( <\/span>Signal<\/span>(), <\/span>MACD<\/span>() ) OR <\/span>Ref<\/span>( <\/span>newday<\/span>, <\/span>1 <\/span>); 

<\/span>\/\/ visualize signals with yellow arrows
<\/span>PlotShapes<\/span>( <\/span>Buy<\/span>*<\/span>shapeUpArrow<\/span>, <\/span>colorYellow<\/span>, <\/span>0<\/span>, <\/span>Low <\/span>);
<\/span>PlotShapes<\/span>( <\/span>Sell<\/span>*<\/span>shapeDownArrow<\/span>, <\/span>colorred<\/span>, <\/span>0<\/span>, <\/span>High <\/span>);

<\/span>\/\/ remove redundant signals
<\/span>Equity<\/span>( <\/span>1 <\/span>);

<\/span>\/\/ modify Buy array and allow only first N signals
<\/span>Buy <\/span>= <\/span>Buy <\/span>AND <\/span>Sum<\/span>( <\/span>Buy<\/span>, <\/span>BarsSince<\/span>( <\/span>newDay <\/span>) + <\/span>1 <\/span>) <= <\/span>N<\/span>;

<\/span>\/\/ visualize modified signals with green triangles
<\/span>PlotShapes<\/span>( <\/span>Buy<\/span>*<\/span>shapeUpTriangle<\/span>, <\/span>colorGreen<\/span>, <\/span>0<\/span>, <\/span>Low<\/span>, -<\/span>24 <\/span>)<\/code>

\"Price<\/p>

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. <\/p><\/span>\/\/ trades limit
<\/span>N <\/span>= <\/span>2<\/span>;

<\/span>Plot<\/span>( <\/span>Close<\/span>, <\/span>"Close"<\/span>, <\/span>colorDefault<\/span>, <\/span>styleBar <\/span>);

<\/span>\/\/ identify new day
<\/span>dn <\/span>= <\/span>DateNum<\/span>();
<\/span>newDay <\/span>= <\/span>dn <\/span>!= <\/span>Ref<\/span>( <\/span>dn<\/span>, -<\/span>1 <\/span>);

<\/span>\/\/ buy and sell signals
\/\/ sample repeated signals
<\/span>Buy <\/span>=  <\/span>MACD<\/span>() > <\/span>Signal<\/span>();
<\/span>\/\/exit on signal vs macd crossover or last bar of the day
<\/span>Sell <\/span>= <\/span>Cross<\/span>( <\/span>Signal<\/span>(), <\/span>MACD<\/span>() ) OR <\/span>Ref<\/span>( <\/span>newday<\/span>, <\/span>1 <\/span>); 

<\/span>\/\/ visualize signals with yellow arrows
<\/span>PlotShapes<\/span>( <\/span>Buy<\/span>*<\/span>shapeUpArrow<\/span>, <\/span>colorYellow<\/span>, <\/span>0<\/span>, <\/span>Low <\/span>);
<\/span>PlotShapes<\/span>( <\/span>Sell<\/span>*<\/span>shapeDownArrow<\/span>, <\/span>colorred<\/span>, <\/span>0<\/span>, <\/span>High <\/span>);

<\/span>tradeCount <\/span>= <\/span>onBuy <\/span>= <\/span>0<\/span>;

for( <\/span>i <\/span>= <\/span>0<\/span>; <\/span>i <\/span>< <\/span>BarCount<\/span>; <\/span>i<\/span>++ )
{
    <\/span>\/\/ reset trade counter on the new day
    <\/span>if( <\/span>newDay<\/span>[ <\/span>i <\/span>] ) <\/span>tradeCount <\/span>= <\/span>0<\/span>;

    <\/span>\/\/ keep buy signal if there is no trade and trade count did not hit the limit
    <\/span>if( <\/span>Buy<\/span>[ <\/span>i <\/span>] AND <\/span>tradeCount <\/span>< <\/span>N <\/span>AND <\/span>NOT onBuy <\/span>)
    {
        <\/span>OnBuy <\/span>= <\/span>1<\/span>;
        <\/span>TradeCount<\/span>++;
    }
    else
        <\/span>Buy<\/span>[ <\/span>i <\/span>] = <\/span>0<\/span>; <\/span>\/\/ ignore other buy signals


    <\/span>if( <\/span>onBuy <\/span>AND <\/span>Sell<\/span>[ <\/span>i <\/span>] )
    {
        <\/span>onBuy <\/span>= <\/span>0<\/span>; <\/span>\/\/ reset onBuy flag on exit
    <\/span>}
}

<\/span>\/\/ visualize modified signals with green triangles
<\/span>PlotShapes<\/span>( <\/span>Buy<\/span>*<\/span>shapeUpTriangle<\/span>, <\/span>colorGreen<\/span>, <\/span>0<\/span>, <\/span>Low<\/span>, -<\/span>24 <\/span>)<\/code>","protected":false},"excerpt":{"rendered":"

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 […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[],"_links":{"self":[{"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/posts\/1201"}],"collection":[{"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/comments?post=1201"}],"version-history":[{"count":2,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/posts\/1201\/revisions"}],"predecessor-version":[{"id":1205,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/posts\/1201\/revisions\/1205"}],"wp:attachment":[{"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/media?parent=1201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/categories?post=1201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.amibroker.com\/wordpress\/kb\/wp-json\/wp\/v2\/tags?post=1201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}