Merging rotational with non-rotational strategies

Hello Everyone

I wish I have bought Amibroker the first day of my trading career.
Incredible piece of software. Loving it.

Quick question:

Say we divide bull/bear market with a simple 150d sma on SPY.
How can we merge a rotational long only strategy for the bull market with a non rotational one for the bear market with specific buy and sell rules?

Reference:
http://www.amibroker.com/kb/2016/04/17/long-only-rotational-back-test/
“Since there are no signals used, only PositionScore assigned to given symbol matters.”

Not trying to alter the position score here, but to have two separate strategies so that we can control the buy and sell signals in the non-rotational one.

Can we merge them both? How?
Here are the code samples:

Market definition / Strategy Switch:

Index = Foreign("SPY","C",True);
IndexMA = MA(Index, 150);
BullMarket = Index >= IndexMA; 
BearMarket = Index < IndexMA; 

Strategy 1: Long Only Rotational

SetBacktestMode( backtestRotational );
SetOption("MaxOpenPositions",5);
SetOption("WorstRankHeld",5);
SetPositionSize( 20, spsPercentOfEquity );
PositionScore = 1000 + ROC( Close, 252 ); // make sure it is positive by adding big constant

Strategy 2: Bear Only Non-Rotational

if( Name() == "TLT" )
{
PositionSize = -100;
Buy = Cross( IndexMA, Index );
Sell = Cross( Index, IndexMA );
}
1 Like

What is your desired precedence rule for those two strategies? If “bear” strategy is entered should it:
a) exit all “long” positions?
b) keep existing positions ?
c) do something else?

In simplest case (just enter short on TLT) it would be just a matter of adding this to first strategy:

if( Name() == "TLT" )
{
  EnterShort = Cross( IndexMA, Index );
  ExitShort = Cross( Index, IndexMA );
 
  InPosition = Flip( EnterShort, ExitShort );

  PositionScore = IIF( InPosition, -2000, 0 ); 
}
4 Likes

Hello Tomasz, nice to meet you and thank you very much.

Made a mistake: both strategies are long only.

Ok, got this now:

Index = Foreign("SPY","C",True);
IndexMA = MA(Index, 150);
BullMarket = Index >= IndexMA; 
BearMarket = Index < IndexMA; 

//Strategy 1 (Long only - BullMarket)
SetBacktestMode( backtestRotational );
SetOption("MaxOpenPositions",5);
SetOption("WorstRankHeld",10);
SetPositionSize( 20, spsPercentOfEquity );
PositionScore = 1000 + ROC( Close, 252 ); // make sure it is positive by adding big constant

//Incompatible with strategy 2
//PositionScore = IIf( Index <= IndexMA, scoreExitAll, PositionScore ); 

//Strategy 2 (Long only - BearMarket)
if( Name() == "TLT" )
{
  EnterLong = Cross( IndexMA, Index );
  ExitLong = Cross( Index, IndexMA ) ;
  PositionSize = -100; // Not working
  InPosition = Flip( EnterLong, ExitLong );
  PositionScore = IIF( InPosition, 2000, 0 ); 
}

Ideally we´re looking to use the first code to switch.

  1. If BullMarket: activate the Strategy 1
    Exiting all positions when the BullMarket conditions are no longer true.

  2. If BearMarket: activate the Strategy 2
    The signals here would only be considered if the BearMarket condition is true.
    (The buy and sell signals here are independent, not necessarily the same as the switch.)
    Also the positionsize is independent.

Is it possible?

1 Like

Hi Nick

You can make PositionScore dependent on whether the BullMarket condition is true by using it in an IIF function. This will make it zero when BullMarket is not true, which will liquidate your holdings at that point. Also, rather than adding 1000, you can use the Max function to assign zero to the PositionScore when the ROC is less than zero.

For position sizing, you should call SetPositionSize only once (PositionSize is a legacy command that does the same thing, so you’re trying to define it twice). So create a variable which holds the symbol specific position size and pass it to SetPositionSize once afterwards.

To only enter Strategy 2 when BearMarket is true, use it as a condition in the entry criteria.

// Strategy 1
// If Not BullMarket set PositionScore to 0
// If ROC < 0 set PositionScore to 0
PositionScore = IIf(BullMarket, Max(ROC( Close, 252 ), 0), 0); 
PosPercent = 20;  // Universal position size

// Strategy 2
if (Name() == "TLT")
{
	PosPercent = 100; // TLT specific position size

    // Only enter when BearMarket is True
    EnterLong = BearMarket AND Cross( IndexMA, Index ); 

    // ...
}
	
SetPositionSize( PosPercent, spsPercentOfEquity );
16 Likes

Ahh Perfect! You solved it elegantly.
I just had to think it a bit more.
Thank you so much Helix and Tomasz of course.

5 Likes