Coding for ETF Model

Folks,

I’ve been tinkering with a few things and I seem to be stuck on the coding. I’m trying to test Asset Rotation: The Demise of Modern Portfolio Theory and the Birth of an Investment Renaissance by Matthew P. Erickson. It’s an interesting book. The research appears to be sound and might become a part of my core holdings.

The idea behind the model is to take the following tickers (sectors): IDU, XLY, XLP, XLF, IYE, IYH, IYJ, IYW, XLB, and TLT. Track their rate of change once a month. Buy the top 5 equally (20% each) and hold for 30 days. If TLT is one of the selected ETFs, no other ETFs are selected for below its percentage gain. So if the gain on TLT had it ranked at number 3 this month, TLT would take the place of the third, fourth, and fifth ETF for that month. It would have a 60% weight. The top two ETFs would still receive a 20% allocation each.

It seems like it should be rather simple, but I’m missing something in the code.

Thanks for any feedback.

Tom Marshall

The system only supports the same sizes for each ETF. Therefore TLT cannot be > 20%. A workaround is to substitute funds that are similar to TLT when needed.

What is the ranking system?

Tom,

The ETF’s can be put in a custom universe or custom ticker list. (I suggest universe).
Ticker(“IDU, XLY, XLP, XLF, IYE, IYH, IYJ, IYW, XLB, TLT”)

A ranking system can be built using one momentum factor.

Sell rules can be set to ‘1’ and ‘buy previous holdings’ set to yes.

You can do the rotation portion easily. The TLT conditional variable weighting piece likely can’t be done in P123 and would have to be manually backtested and / or run. You could do a ‘poor man’s workaround’ with Eval Rules and more ‘TLT’ like ETF’s (as Chipper notes above).

Where if TLT is ranked higher than top 30%, it’s the only ETF that can be bought unless others are outperforming it.

So Eval(Ticker(“TLT”) and Frank(“close(0)/close(30)”)>=70,1,close(0)/close(30)>=close(0,Getseries(“TLT”))/close(30,Getseries(“TLT”)))

You’d still have to do the manual overweight yourself. Although you might be able to come up with a book based workaround. A fairly simple way to get close is to set holdings to ‘5’, but allow weight deviation from target of 50%.

Chipper’s right in that you can just add another two ‘TLT’ options into the mix and let them get bought.

Not exact, but close.

REVISION: I haven’t checked the above eval rule and you would likely need to nest eval’s, but that should get your started.

Best,
Tom

Here is a simulation that does something similar by substituting the following treasury ETFs for TLT (in order of preference): TLT TLO TLH PLW IEF. Each ETF can be up to 20% of the weight.

Chipper,

Nice! Looks good. Have to add some filters to weed out rising interest rates…or could be all long-dated Treasuries, but not bad.

Best,
Tom

Can you share your formula for $EOM?

Sorry about that.

EOM:
InSet(Month,1,3,5,7,8,10,12)*31 + InSet(Month,4,6,9,11)*30 + ((Month=2)*28)

It assumes that February is always 28 days.

Chipper6,

that’s a smart combination of formulae that you put together.

Why did you let the sim start at 10/30/09?
Is that the date of the last inception date of all the funds in the universe?

Best,
fips

Here is a better version of this simulation that goes back to the end of 2007 and uses true daily ranking and not Monday’s prices.

“Access denied.” :wink:

So is it the ETF inception dates that are the limiting time constraints?

Best,
fips

The sim should be public now. Sorry.

10/30/09 is five years. I figured that the data should go back until then.

The new sim goes back until 2007 because the substitute long bond data exists at least until then.

Just for fun I substituted #NOTE3YR for the bond benchmark. I also monkeyed with the some of the transaction cost parameters.

https://www.portfolio123.com/port_summary.jsp?portid=1240029

Very nice! How many other changes did you try before coming across the results for #NOTE3YR?

Not many since I stuck to the TBILL, NOTE and BOND series. The 2YR note does slightly better, too.

#NOTE3YR is the yield of three year treasuries; not the price appreciation. In other words this new sim is going out of equities and into Treasuries whenever equities are not going up as fast as interest rates. This means that it buys Treasuries whenever treasury prices have not gone up too much. Your simulation is actually doing conceptually the opposite of the original system! It’s strange that it worked. Does anyone have a theory why this should work?

Another interesting thing about the #NOTE3YR series is that it is a monthly series; not a daily series like stock prices. That means that Close(63,#NOTE3YR) represents what interest rates were 63 months ago. 63 months is more than five years. There must be a reason why this simulation worked. If we figure it out why it worked in the past then we may have a clue if it will continue to work.

EDIT: Looking at a Macro chart of #NOTE2YR, change compared to 63 bars ago here, we see some correlation between short term interest rates and equity prices. Perhaps it’s a risk on risk off signal. The signal is not perfect but there seems to be some correlation.

I guess I shouldn’t be monkeying around late at night!

This is my first use of #NOTE3YR so I’m not surprised that I confused yield w/ price. Sorry about that!

I’m going to need some coffee before I think about this one.

Can somebody explain where the number 24182 comes from in Close(0,24182)/Close(63,24182). This should be a series in Close(barsAgo [,series]).
Also #NOTE3YR does not work for a 5 year backtest.

Chipper,

Where did you get the custom code for TLT? Same question as Geov. I have always used tickers, but this is a useful trick to get around formula nesting problems.

This feels to me like a spurious correlation. But can play around with it here:
https://www.portfolio123.com/app/screen/summary/1130?mt=8

  1. Just turn on rule 4 and then run and can see that the 3 Yr. Yield tended to track stock index movements until 2/2009. Then is stopped. Historically, we know that bond/stock correlations have varied widely over different subperiods. This is an expression of that.
  2. If you turn on rule 1, can see the difference between the average SP500 stock and the 5 Year yield change in 3 year note. Anytime it’s positive it would be ‘long.’ Can go through and check this sector by sector (i.e. industrials, util, etc).
  3. If turn on rule 5 only, get a potential market timing rule (3 month change of 10 year note vs. 3 month change of average stocks). Would have to play with it, but this is one way of ranking the market (likely smoothed with longer term average).
  4. Rule six is a variation on the timing rule that looks at 3 month average SP500 change vs. 3 month synthetic 10 year note change.

Best,
Tom

Are we seeing here the effects of QE supressing bond yields at the start of 2009?