Unexplained Exit and Entry on the Same Day with MaxOpenPositions = 1

Hello,

Don't want to over-use the forum for help, but I ran into a situation for which I just cannot find an answer on the forum or in the manual.

Below find code for a mean reversion system that enters on a limit order the day after a RSI reading below 20. It then exits on the close once the RSI exceeds 55. I have simplified the code to illustrate the problem with as little effort as possible.

I ran into a situation where a sell and a buy occur on the same day. Given that I am not buying at the close, but before at the limit price (or open, if the open is below the limit price), this should not happen for a setting of MaxOpenPositions = 1.

Is there an explanation that I am overlooking? Could it be that once I set a "non-standard" BuyPrice, different from Close or Open, this forces me to loop through all bars and "clean up" any buys that occurr on sell dates?

Thanks

Robert

SetOption("MaxOpenPositions", 1);
SetPositionSize(100, spsPercentOfEquity);
SetOption("AllowPositionShrinking", True);
SetOption("AllowSameBarExit", False);

Buy = False;
Sell = False;

// Check if limit price was hit the day after a buy signal
BuySignal = RSI(2) < 20;
BuyLimitPrice = Ref(Close, -1) * 0.98;
Buy = Ref(BuySignal, -1) AND (L < BuyLimitPrice);
PositionScore = Random();

// If open is below the limit price, then we enter at the open
BuyPrice = Min( Open, BuyLimitPrice );

Sell = RSI(2) > 55;
SellPrice = Close;

Filter = True;
AddColumn(RSI(2),"RSI");
AddColumn(BuySignal,"Next Day Buy", 1.0);
AddColumn(L < BuyLimitPrice, "L < BLimit", 1.0);
AddColumn(Buy,"Buy", 1.0);
AddColumn(Open, "Open");
AddColumn(Close, "Close");
AddColumn(Low, "Low");
AddColumn(BuyPrice, "Buy Price");

Since you did not tell where you ran the code and since you posted Exploration code... Explorer is not backtester. SetOptions such as "AllowSameBarExit" and "MaxOpenPositions" are backtester settings and are not applied in Explorer.

What you see in Explorer are raw signals.

Show a trade in actual backtester that is on same day/bar. Are there any?

Other than that please take a look here
https://www.amibroker.com/guide/h_portfolio.html

Thanks for looking. Yes there are two trades in an actual backtest with a watchlist containing symbols EWW, EWZ and XRT. They occur on 11/15/18 (sells EWZ and buys XRT) and 11/26/18 (sells XRT and buys EWW). This is the trade list for a backtest running from Jun-Dec 2018 (Data source: Norgate, unadjusted prices).

Symbol Trade Date Price Ex. date Ex. Price % chg Profit % Profit Shares Position value
EWZ Long 06/07/2018 33.73 06/08/2018 34.14 1.22% 1215.24 1.22% 2964 99975.72
EWZ Long 08/09/2018 35.182 08/14/2018 34.7 -1.37% -1386.23 -1.37% 2876 101183.44
EWZ Long 08/21/2018 32.4184 08/27/2018 32.81 1.21% 1205.74 1.21% 3079 99816.26
XRT Long 10/02/2018 49.7056 10/12/2018 47.42 -4.60% -4644.34 -4.60% 2032 101001.78
EWW Long 10/22/2018 46.6774 11/01/2018 43.84 -6.08% -5859.23 -6.08% 2065 96388.84
EWZ Long 11/08/2018 39.5626 11/15/2018 39.87 0.78% 703.33 0.78% 2288 90519.23
XRT Long 11/15/2018 46.4814 11/26/2018 45.76 -1.55% -1415.39 -1.55% 1962 91196.51
EWW Long 11/26/2018 38.9256 11/28/2018 40.1 3.02% 2709.34 3.02% 2307 89801.36
XRT Long 12/06/2018 44.345 12/26/2018 40.65 -8.33% -7707.77 -8.33% 2086 92503.67

OK, you are talking about multi symbol positions.
This can be solved via mid level CBT for sure.

See:

Without applying CBT code
10


And with applying CBT code
9

You count number of open positions and if it exceed max. setting then you skip signal
via

// .....
    // CBT code snippet!
    if ( cnt >= maxpos )	
        sig.PosSize = 0; // mark signal to be skipped
// .....

Maybe Tomasz has solution without requiring CBT. But upper one is one of them.

@fxshrat: thanks a lot for pointing this out. I will give it a shot.

Typically (in 99% of cases) there is no reason to use CBT.

The problem is NOT reading instructions, specifically NOT reading tutorial on backtesting http://www.amibroker.com/guide/h_portfolio.html especially the chapter

RESOLVING SAME BAR, SAME SYMBOL SIGNAL CONFLICTS

This is extremely important, so read it. Carefully.

Also there is a SetOption("SettlementDelay", 1) http://www.amibroker.com/f?setoption that makes sure that funds from closing one position are NOT available till next bar. And that option you should use instead of CBT to prevent entering other symbol using funds that you got from selling another.

@Tomasz: Thanks for pointing out "SetOption("SettlementDelay", 1). Adding this statement to "SetOption("AllowSameBarExit", 0), allowed me to get rid of the same day exits and entries.

But -at least in my specfic case- what is written in the RESOLVING SAME BAR, SAME SYMBOL SIGNAL CONFLICTS does not seem to work at the portfolio level. The original code I posted already contained (for this very purpose) the line "SetOption("AllowSameBarExit", False) ", in accordance with:

Scenario 1. Only one signal per symbol is taken at any bar

This scenario is used when AllowSameBarExit option is set to False (turned off).

In this case it does not really matter whether exit or entry was the first within single bar. It is quite easy to understand: ON ANY BAR ONLY ONE SIGNAL IS ACTED UPON

From what is written further down I concluded that is also works for the portfolio case:

How does it work in portfolio case?

The mechanism is the same regardless if you test on single symbol or multiple symbols. First same-bar conflicts are resolved on every symbol separately the way described above. Then, when you test on multiple symbols, resulting trade candidates are subject to scoring by PositionScore described in earlier part of this document.

But, for the portfolio case, maybe same-bar conflicts are only resolved symbol by symbol, and not across symbols, and you need in fact the additional statement "SetOption("SettlementDelay", 1).

Could you possibly clarify?

It works on porfolio level but on symbol-by symbol basis.
"Resolvig same bar, same symbol signal conflicts" applies to specific symbol. Each symbol conflict is solved on symbol-by-symbol basis. It does NOT apply to cross-symbol relationships. Signals on different symbols are totally independent. If one trade ends on monday and another trade (on different symbol) begins on monday it does NOT count as two simultaneous (parallel) positions. These positions are SEQUENTIAL, not parallel.
If you don't want to open new position till the end of the bar, you need to use settlement delay. And it just works regardless if it is the same or different symbol.

Thanks a lot Tomasz, it's clear for me now.

But this would work only if the cash is less than the required size for the new position.
That is, if cash before the close of the current position is $10,000, the settlement delay will not stop the opening of a new position of value $10,000 or less.
Is this correct ?