Walk Forward Exiting at the end of each OOS period

Hi All,

I am using a walk forward with an ISS of 10 years and an OSS of one year. Looking at the trades I see that all open positions are closed at the end of the OSS period in preparation for the next.

Is there a way to continue these trades until my sell signal activates as most of my trades are held longer than the 1 year period? I have found that closing the trades prematurely decreases performance.


Yes, change your entry (buy/cover) signals from signal (PULSE) form, to STATE form.
PULSE is when True appears on single bar only. STATE form is when True appears on all bars when trade is active. To convert from pulse to state you can use Flip function

Buy = Flip( Buy, Sell ); // from pulse to state

Doing so will re-open trade that was previously open.


Thanks for your prompt reply Thomasz

I have two further questions:

  1. Does this work for delisted shares? I am using Norgate premium ASX data and have included their code (see below) to ensure that delisted stocks are closed when there is no activity. It seems that the delisted stocks are still exiting at the end of the OSS when the listed are not.
  2. Doesn’t creating a STATE signal then produce a BUY signal after the initial setup has occurred if there are less than the maximum positions open? This would mean that my system would be entering into a position after the ideal entry point.


Norgate code (https://www.premiumdata.net/support/amibroker.php):

// For backtesting, we never want to be left holding a delisted stock, 
// however not all versions of AmiBroker allow us to detect whether a security is delisted
// To simulate this we will provide a sell signal on the
// second last bar only if the last bar's date is >= 30 days from today's date.
// Also, we will not enter on the second or last bar of the trade
// as we will then be unable to exit the position if trade delay is set to 1 day.
// This code has been collaboratively developed by Norgate Investor Services
// www.premiumdata.net and its users and is made freely available to the AmiBroker community.
// Known issue: For highly illiquid securities that trade very infrequently will be considered to
// be inactive. This is probably fine for the purposes of backtesting as you would not want to be
// attempting to trade a rarely-traded security.

NonTradedPeriod = 30; //in calendar days
SecurityIsInactive = LastValue(DateTimeDiff(Now(5),DateTimeAdd(DateTime(), NonTradedPeriod, inDaily))) >= 0;

OnSecondLastBarOfInactiveSecurity = BarIndex() == (LastValue(BarIndex()) -1) AND SecurityIsInactive;
OnLastTwoBarsOfInactiveSecurity = BarIndex() >= (LastValue(BarIndex()) -1) AND SecurityIsInactive;

Buy = Buy AND NOT OnLastTwoBarsOfInactiveSecurity;
Sell = Sell OR OnSecondLastBarOfInactiveSecurity;

// If you have a short selling system you will also need to include the following:

Short = Short AND NOT OnLastTwoBarsOfInactiveSecurity;
Cover = Cover OR OnSecondLastBarOfInactiveSecurity;
1 Like

Sorry Thomasz

I have misinterpreted the problem of the STATE BUY.

The stocks are re-entering again at the end of the OSS but are then holding for another sell period (my sell is a applystop with a 255 bar count.) until the end of the second OSS.

This is much in line with my second question above.

I'm trying understand this better too.
If you have state signals, that's fine so far.

However, if you have 1000 stocks, the entry will be ranked using positionscore. The positions score is obviously different when the entry occurs as opposed to being closed out when the OOS ends. In other words, is the positionscore of entry remembered in walkforward so that the same trades are taken again?

Any thoughts?

Maybe I have been really overthinking this issue, yet I m still in doubt.

  1. My code has a state signal for Buy/Sell like below
  2. Database with 100 symbols (say stocks, same Pointvalue, MarginDeposit, etc.)
  3. Max Open Pos = 5
  4. EXAMPLE: (NON-Anchored)
    IS 01/01/2000 - 01/01/2003
    OOS 01/01/2003 - 01/01/2004
Buy = C > MA(C,parameter);
Sell = C< MA(C,parameter);

When Walk Forward is now run, OPEN POSITIONS have to be "exited" / "accounted" for after the FIRST OOS ends (lets call it OOS1). Here after 01/01/2004. When the next run continues (OOS2), say 01/02/2004 (2nd of Jan 2004) the positionscore has changed. It's a must. It can't be the same.
So technically, the question boils down to this:

When the above code is run in Walk Forward analysis, it's actually like this:

Buy = C > MA(C,paramter);
Sell = C< MA(C,parameter OR Year()!=Ref(Year(),-1);

Did I get that correctly?

i hope the question is clear... no thoughts on this?

I have been struggling with this for years. This Flip statement solved everything.