Using OR in a Sell Condition allows Mutliple entries on same Symbol

I was attempting to code a strategy that uses multiple exit conditions, and came across what appears to be a bug.
The Strategy is to allow entry and exit on the same bar, but to only ever allow 1 open postion in the same symbol at any time. Here is working code WITHOUT an OR in the sell condition:

SetOption("AllowSameBarExit", True );  
SetOption("SettlementDelay", 1 );

Buy = C > MA(C,10);
Sell = C > O;

// trade on todays open
SetTradeDelays( 0, 0, 0, 0 );
BuyPrice = Open; 
SellPrice = Close;

SetPositionSize( 20, spsPercentOfEquity );

This works exactly as it should - it allows entering and exiting on the same day, but only allows 1 open symbol at any time. However as soon as we add an OR into the sell condition like:

Sell =  C > O OR C < MA(C,10);

the Backtester allows the same symbol to be entered on the same day of the exit:

Capture (Which when buying at the open and selling on close would allow more than 1 open position on a symbol)
Is there any workaround when using multiple sell conditions and same bar entry exit, while still only ever allowing 1 open trade per symbol per day?

1 Like

@DaleCam I did a short test with your code snippet and in my backtest report, I got the same result (a symbol entered again on the same day of the exit) both using the condition with and without the OR.

In any case, I suggest you look at this thread that seems to have a solution for your issue.

2 Likes

No I did not fix it, only to some extend for an AFL that had a lot of buys on open and sell on close of 1 bar conditions.
I am still trying to find a solution that always works.
Sometimes predicting the current bar has good results so I find it an interesting case.

https://forum.amibroker.com/t/not-working-at-all/6883

1 Like

I did an update see link before.

First of all you have a future leak in your code!

047

So either you have to set trade delay to 1 for Buys

SetOption( "AllowSameBarExit", 1 );
SetOption( "MaxOpenPositions", 1 );
SetOption( "SettlementDelay", 1 );

SetPositionSize( 20, spsPercentOfEquity );

SetTradeDelays( 1, 0, 0, 0 );

BuyPrice = O; // trade on todays open
SellPrice = C;

Buy = C > MA(C,10);
Sell = C > O;

Short = Cover = 0;

Or using Ref() with SetTradeDelays to zero

SetOption( "AllowSameBarExit", 1 );
SetOption( "MaxOpenPositions", 1 );
SetOption( "SettlementDelay", 1 );

SetPositionSize( 20, spsPercentOfEquity );

SetTradeDelays( 0, 0, 0, 0 );

BuyPrice = O; // trade on todays open
SellPrice = C;

Buy = Ref(C > MA(C,10), -1);
Sell = C > O;

Short = Cover = 0;

As for cases of entering trade at Open price and exiting trade at Close price of same bar and only allowing max. one position at bar...
The only way I see accomplishing that is... via custom backtest interface...

8 Likes

Sorry I made a mistake, this link was private.

You specifically ASKED backtester to allow same bar trades including re-opening the same bar, by writing:

SetOption("AllowSameBarExit", True ); // you ASKED to allow exits AND entries the same bar

This option in the Settings dialog has elaborate name of "allow same bar exit / entry signal". And you specifically asked backtester to do what it does.

image

If this option is turned on it means that BOTH exit AND entry on the same bar is allowed.

The trade was possible because only 20% of funds were used for first trade so even if there was settlement delay set to 1, the remaining equity allowed to enter such trade.

So if you don't want same bar entry-exit and exit-entry you need to
Turn OFF / Remove that option / line from the code

Consult the manual regarding supported scenarios:
http://www.amibroker.com/f?applystop
http://www.amibroker.com/guide/h_portfolio.html

Only scenarios described in the manual are supported ones.

Also you guys need to understand that assigning anything to *price arrays does NOT change the ordering of events. The order of handling signals is controlled by options, not by assigning something to *price arrays.

1 Like

Hi and thaks for your reply Tomasz. Please note that I/WE DO want to exit on the same bar, we just dont want to be allowed to OPEN a same SYMBOL on the bar that it exits.
I specifically constructed this based on the sample in http://www.amibroker.com/guide/h_portfolio.html
There under the subheading: RESOLVING SAME BAR, SAME SYMBOL SIGNAL CONFLICTS, i chose scenario 2 which states:
both signals are used and entry signal precedes exit signal, so trade that begins on bar 1 ends on bar 1, then text trade opens on bar 2 and ends on bar 2, and so on (we have single-bar trades and we are out of market between bars)

So in your opinion what is the best way to be able to Enter and Exit on the same bar, but to prevent the same symbol from entering on the day it has an Exit?

Sorry that last sentence is meant to say:
So in your opinion what is the best way to be able to Enter and Exit on the same bar, but to prevent the same symbol from entering on the day it already had an open postion from the day before?
A Custom Backtester?

Thank you all for your replies - it really is appreciated.

As I wrote this setting controls both same bar entries and exits. Either both are allowed or both are disallowed.
The example from the manual is different because it always exits the same bar. If your system did the same it would work just fine

Sell = Buy; // exit same bar

For what you are trying to do there are three ways:

  1. using custom backtester as proposed earlier in this thread, or
  2. using 100% invested method and settlement delay, or
  3. using simple loop that removes buys you don't want to act upon

Regarding method 2 - there are three things required for this to work: you need to set position size to 100% of equity, you need to set settlement delay to 1 and the stock you are trading is liquid enough to open desired position otherwise per-bar volume limit is hit. APT is NOT liquid enough.
On July 20, 2017 the volume was only 35600 shares. With the default per-bar volume limit of 10% it means that trade will be size-limited at 3560 shares only which with $3.4 dollar price may be way too small to be able to use 100% of your account equity.

So to ensure that 100% is allocated for thinly traded stock as APT you would need disable trade size limit:

image

The code that you used is "almost there". With slight modifications shown below it would do what you wanted:

SetPositionSize( 100, spsPercentOfEquity ); // the default setting 100% investment

SetOption("AllowSameBarExit", True );
SetOption("SettlementDelay", 1 );

BuyPrice = Open;
SellPrice = Close;

Buy = Ref( Close > MA( Close, 10 ), -1 );
Sell =  Close > Open OR Close < MA( Close,10);

Resulting trade list:

image

Third method is to simply remove buys you don't want to act upon. Using this method you don't need to be 100% invested. An example code is shown below.


SetOption("AllowSameBarExit", True );

BuyPrice = Open;
SellPrice = Close;

Buy = Ref( Close > MA( Close, 10 ), -1 );
Sell =  Close > Open OR Close < MA( Close,10);

// removing buys you don't want
intrade = False;
for( i = 0; i < BarCount; i++ )
{
	if( NOT intrade )
	{
		if( Buy[ i ] ) 
		{
			intrade = True;
		
			// same bar sell
			if( Sell[ i ] ) intrade = False;
		}
	}
	else
	{
		if( Sell[ i ] ) 
		{
			intrade = False;
			Buy[ i ] = False; // remove buy if exited this bar
		}
	}
}  
10 Likes

Thank you very much Tomasz, great and easy to understand answer. I can see know clearly that the issue was simply because I was holding overnight in some instances, therefore allowing a single sell and buy on the next bar is valid due to the same bar setting. Let me try out method 3!

Thank you so much Tomasz - the third method (using the loop) worked perfectly for me (with a portfolio of stocks too)!

1 Like

@DaleCam,

Have you looked carefully because Tomasz's 2nd code is more suited for single security backtests?

See example backtest result below with

SetOption( "MaxOpenPositions", 1 );

You have per symbol entry exit at same bar (e.g first 5 ones below) but also have cases of entry of additional position at very same bar (see yellow markers).

156


On the other hand Custom Backtest Interface method will work with single security backtests and with portfolios backtests. So if you look for one-for-all method to always ensure max. 1 position at same bar if "Buyprice = Open" and "SellPrice = Close" then using CBT interface is way to go (AFAICS).

1 Like

Hi fxshrat - yes the Single security backtest was simply for an example to demonstrate the issue. My real trading systems all trade a basket/watchlist of stocks. So for me - the best approach was the third approach.
Thank you for your words of advice and concern though!

I was referring to the third approach (second code).That one will still have cases of two positions at same bar (two different symbols).

SetOption("AllowSameBarExit", True );
SetOption( "MaxOpenPositions", 1 );

BuyPrice = Open;
SellPrice = Close;

Buy = Ref( Close > MA( Close, 10 ), -1 );
Sell =  Close > Open OR Close < MA( Close,10);

// removing buys you don't want
intrade = False;
for( i = 0; i < BarCount; i++ )
{
	if( NOT intrade )
	{
		if( Buy[ i ] ) 
		{
			intrade = True;
		
			// same bar sell
			if( Sell[ i ] ) intrade = False;
		}
	}
	else
	{
		if( Sell[ i ] ) 
		{
			intrade = False;
			Buy[ i ] = False; // remove buy if exited this bar
		}
	}
}  


Are we talking about the same?
I am not talking about sequential single security backtests but true portfolio backtest.

1 Like

Im talking about his third approach as per his comment:
3. using simple loop that removes buys you don't want to act upon

so specifically his last piece of code (the loop)

Again, re-read my posts... I am talking about the very same looping code!
Please upload APX file (analysis project file with file extension .apx).

1 Like

@fxshrat - you misunderstood. As per original request third solution allows only 1 position per 1 symbol at any given time. Opening 2 positions on 2 different symbols is perfectly OK (scroll up to the very first post).

1 Like

Fxsrat - you need to remove the line:
SetOption( "MaxOpenPositions", 1 );

If you look at Tomasz last loop code it doesnt include that line.