Portfolio Design

Advanced concepts in stock investment portfolio design.  Fundamentals, technical analysis and many other related topics are discussed.

Market Timer: Business Cycle Approach

In the last few posts I have described a market timer, implemented using Portfolio123, that should give reasonable results going forward. If you, the reader, have followed along and constructed you own version, then you have earned a Yellow Belt in market timing.

Now I am going to skip colors orange through brown and "we", yes you and I, are going to start preparing for a Black Belt. Our next project is to create a business cycle market timer. I have to warn you that this task is two orders of magnitude more sophisticated than the basic market timer. 

I have tried to develop some primitive business cycle indicators in the past but haven't been particularly successful.  Will this time be different?  Who knows, but I am optimistic enough to give it a try. I could fall flat on my face, but I won't learn anything if I don't try.

Lets start with a diagram of the "business cycle". I've seen many over the years but this one from Fidelity covers it nicely.

Diagram of the typical economic business cycle.

I'm going to simplify the above by combining the Mid and Late expansion periods.  These are kind of blurry anyways. Later on,  if necessary these phases can be separated to get better results. The first task in order to get started is to create four custom formulas as shown below. I should actually be creating a few more but it is getting late, and I want to get this post out.

Custom formula: Business Cycle State

Custom formula: Market Status

Custom formula: Ticker for ETF symbol RSP

Custom formula: Ticker for ETF symbol IEF

Ranking System General Setup

The next task is to copy the ranking system that was created previously and name the new ranking system "Business Cycle Timer".  Now I am about to describe a fairly extensive modification to the existing ranking system, so pay attention and do exactly what I am doing. Everything has to be copied precisely or it won't work.  Below is a screen shot of the Business Cycle Timer ranking system.

Screenshot of the general setup for the Business Cycle Timer

The first thing to note is the new structure under the Def True condition. There are now six items:  Lib, Recovery, Expansion, Contraction, Business Cycle State, and Market Status. They must be defined in exactly the same order as above, the reason being that some nodes are referenced by NodeRank("xxx") and you want to avoid error messages when you try to run your ranking system.


Lib, short for Library, is a depository for your market timing indicators that you developed during the last project. You may or may not use these indicators but keep them here just in case you need them.  New indicators that you may develop should be saved in this area as well. It provides some organization and makes such things easier to find. 

Recovery, Expansion, Contraction

These are the three phases of the business cycle that are of interest. Within each composite node, are two more composite nodes, one for economic indicators, and one for market timer indicators.  The job of the economic indicators is to map out target zones identifying where to look for market timing.  The market timer indicators are customized for each transition as per stock market action. For example, the economic indicator(s) may identify that we are in the business cycle recovery state.  The corresponding market timer will look for the start of a new bull cycle, timed as precisely as possible.

The indicators for both economics and timing should be defined in Lib and referenced here using NodeRank("xxx").

For now, do not worry about what should be in the indicator and timer nodes. I will cover that later.

Business Cycle State

This is where the current business cycle phase is resolved, based on the indicators from the three business cycle phases. 

Market Status

Depending on the identified business state above, the market status will pull in one of the three timer states from the corresponding business cycle phase. The equation is:

Eval($BCState > 10 & $BCState < 40, NodeRank("Recovery_Timer"), Eval($BCState < 80, NodeRank("Expansion_Timer"), NodeRank("Contraction_Timer")))


The formula for ranking system output node InMarket should be set to the following:

Eval($BCState > 10 & $BCState < 40, Eval($MktStatus > 50, $RSP, $IEF),Eval($BCState < 80, 
Eval($MktStatus > 50, $RSP, $IEF),Eval($MktStatus > 50, $RSP, $IEF)))

Specific Setup Required For Developing Recovery Indicators

The first mini-task is to develop Recovery Indicators.  In order to allow the ranking system to run without errors, perform the following modifications to the ranking system.

Screenshot of special preparation needed in order to develop and test recovery indicators.


Enter the Recovery1 formula:

Eval(EMA(100, 0, $SP500PG) / EMA(200, 0, $SP500PG) > EMA(100, 0, $SP500PV) / EMA(200, 0, $SP500PV), Ticker("IEF"), Ticker("RSP"))

This formula compares growth stock performance to value stock performance.  It is a placeholder only to allow me/us to get started. This indicator will be replaced by real economy indicators once I/we get started. I also just realized that this indicator should have been put in Lib and referenced here using NodeRank("xxx"). But that will have to wait for another day.


Set the binary node to TRUE as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.


Set the binary node to NodeRank("Recovery_Indicator") as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.


Set the binary node to FALSE as shown in the screen shot.

Test the Ranking System

Everything should be ready within the ranking system now for developing Recovery Indicators. Lets test the ranking system to make sure there are no errors.

Click on the Ranks button then select the custom universe and click on RUN as shown below.

Screenshot of Ranks page.

Screenshot of Ranks page.

There should be no errors as a result of running Ranks.  If there are errors then you have to go back to the Factors page and debug the ranking system.  Usually the error messages are quite good and will give you a clue as to where to look. Once the Ranks Run works without error, then you should see something similar to the screenshot below.

Screenshot of typical ranking results.

Now go to the portfolio simulation, same as the Market Timer simulation except for two changes. First, select the new ranking system. Second add a buy rule as shown below.  The purpose of this rule is to block the ticker IEF from producing backtest results.  We only want to see the time periods when the Recovery Indicator is active.  Every other indicator and timer is dummied out.

Screenshot of simulation buy rules

Now run the simulation.  It should look exactly like, or very close to, the results shown below.  If not, then you need to review the ranking system setup and of course the changes to the simulation that should have been made.

Screenshot of simulation backtest results.

Screenshot of simulation backtest results.

The chart below shows the target zones for the Recovery Indicator(s). We want to cover these areas... you can recognize what is being covered by running the simulation and looking at the performance graph at the areas where is no flat line (see above).

Target zones for the recovery indicators.

Target zones for the recovery indicators.

Now if that weren't enough.  I'm tying one hand behind your back.  Use only the economic indications for early recovery identified below, at least as best as you can.

Recovery indicators should try to cover these economic factors.

Final words for today

Remember to:

(1) replace the Recovery1 indicator with economic indicators from the list above

(2) try to cover the target zones generally

(3) do not try for exact timing. That is the job of the Recovery Timer! 

Good luck