Sector Rotation Strategy

I. Introduction

Sector Rotation is an asset allocation strategy which posits that certain sectors outperform others in different stages of the business cycle, and that the market can be outperformed by rotating a portfolio’s sector allocation based on the current phase of the business cycle. The sector rotation model has been around for decades, but bear market investing strategies are as relevant ever with the current volatility and uncertainty in the financial markets. While there have been many positive analyses performed on sector rotation, there have also been studies that fail to find statistically significant differences in sector performance over the business cycle, such as this 2009 study.

II. Data and Study Scope

In this analysis, we will seek to develop a sector rotation trading strategy by utilizing multiple applications across the Palantir Finance platform. The underlying data source for the study will be the National Bureau of Economic Research’s (NBER) US business cycle expansion and contraction data. The NBER describes itself as a “private, nonprofit, nonpartisan research organization dedicated to promoting a greater understanding of how the economy works”.  The organization currently boasts over half of the American Nobel prize winners in Economics as members, and these experts meet periodically to discuss and report on the state of the economy. Based on an analysis of a plethora of key economic indicators, the NBER committee determines “peaks” and “troughs” in the US economy, with recessions running from peak to trough and expansions running from trough to peak.

Figure 1: US business cycles phases visualized in the Palantir Finance Chart application. Light blue bands are early recessions, green bands are late recessions, orange bands are early expansions, and red bands are late expansions (Source:

Using the NBER’s business cycle data as a jumping off point, this study will aim to accomplish the following three goals:

  1. Perform a historical analysis of sector performance over the US business cycle to determine which sectors perform best during different business cycle phases. We will divide the US business cycle into four phases: early recessions, late recessions, early expansions, and late expansions.
  2. Build a historical trading model based on our sector performance analysis to see if excess returns could have been generated over the S&P 500 by rotating sector allocation over the NBER cycles.
  3. Build a real-world trading model that doesn’t rely on the after-the-fact NBER announcements, but instead models the business cycle phases using economic indicator data and rotates sector allocation based on the modeled cycles.

III. Historical Analysis

### Part I – Sector SPDR ETFs

To perform an initial analysis of sector performance, we begin by looking at the performance of the nine sector SPDR ETFs over the past ten years since their inception in 1999. These ETFs split the S&P 500 into nine distinct sectors and are designed to track the performance of their associated S&P 500 sector constituents. To start our analysis in the Palantir platform, we can use the DateSet application to convert the NBER peak and trough data into four unique Palantir Finance ‘DateSet’ objects. To learn more about the DateSet application, check out the Palantir Finance Learning Center.

Figure 2: Converting NBER peak and trough data to DateSets using the Palantir Finance </em>DateSet Application. Static lists of dates are added for each of the four business cycle phases (late expansion phase shown).

With the NBER date data imported and converted into Palantir DateSets, we can use the Strategy application to simulate a simple buy-and-hold trading strategy that rotates which sector ETF is held based on the current business cycle phase. The Strategy application allows us to specify a set of actions to perform on each day over a given date range (such as buying and selling stock) using Palantir’s proprietary Hedgehog language (for those new to Hedgehog, check out the Hedgehog language guide). The following is the code used to execute our buy-and-hold strategy for the sector ETFs:

Setup code:

//These are the NBER DateSets to be traded over
DateSet early_rec = DateSet("Early_Recessions(NBER)");
DateSet late_rec = DateSet("Late_Recessions(NBER)");
DateSet early_exp = DateSet("Early_Expansions(NBER)");
DateSet late_exp = DateSet("Late_Expansions(NBER)");

//These TimeSeries variables are used to set the ETF to trade in each phase
TimeSeries CYCLE1 = XLY;
TimeSeries CYCLE2 = XLP;
TimeSeries CYCLE3 = XLB;
TimeSeries CYCLE4 = XLE;

Loop code:

//First, check for exit conditions, which occur at the end of each cycle
if (hasPosition(CYCLE1) &amp;&amp; !early_rec.containsNow() ||
    hasPosition(CYCLE2) &amp;&amp; !late_rec.containsNow()  ||
    hasPosition(CYCLE3) &amp;&amp; !early_exp.containsNow() ||
    hasPosition(CYCLE4) &amp;&amp; !late_exp.containsNow())
//Now, check for entries into new cycles, and buy the associated ETF w/ 100% of NAV
  else if (!hasPosition(CYCLE1) &amp;&amp; early_rec.containsNow()) {
    buy(CYCLE1, 100, Enum.PERCENT_OF_NAV);
} else if (!hasPosition(CYCLE2) &amp;&amp; late_rec.containsNow())  {
    buy(CYCLE2, 100, Enum.PERCENT_OF_NAV);
} else if (!hasPosition(CYCLE3) &amp;&amp; early_exp.containsNow()) {
    buy(CYCLE3, 100, Enum.PERCENT_OF_NAV);
} else if (!hasPosition(CYCLE4) &amp;&amp; late_exp.containsNow())  {
    buy(CYCLE4, 100, Enum.PERCENT_OF_NAV);
} else if (hasPosition(CYCLE4) &amp;&amp; !late_exp.containsNow())  {

Figure 3: Hedgehog code for ETF buy-and-hold strategy over the NBER DateSets. A series of cascading if-else statements are used to check for exits and entrances into the business cycle phases and to buy or sell the appropriate ETF (CYCLE1 in early recessions, CYCLE2 in late recessions, etc.).

With this simple strategy in place, we can leverage the ‘Twiddle‘ tool within the Strategy application to optimize which sector ETF is held during each phase of the business cycle. The Twiddle tool allows us to simulate the execution of a given strategy for different sets of inputs, and to measure key performance indicators for each combination of parameter inputs.

The results of the Twiddle analysis reveal large differences in sector performance over the business cycle phases, and, as a result, there are massive differences in the performance of our buy-and-hold strategy over the 10-year analysis period for different ETF inputs. The ETF rotation strategy that yields optimal returns is as follows: Early Recessions/Consumer Discretionary (XLY), Late Recessions/Consumer Staples (XLP), Early Expansions/Basic Industry (XLB), and Late Expansions/Energy (XLE). Rotating these sector ETFs over the business cycle phases from 1/1/1999 to 6/30/2009 yields a 13.5% annualized return (compared to -2.73% for the S&P 500), and a net profit of $2,782,180 on an initial $1M investment (compared to a would-be $252,117 loss from holding an S&P 500 index fund).

Figure 4: Sixteen cell Twiddle matrix of various ETF rotation strategies. Each cell reports the net profit and annualized return on a $1M investment for a given set of four sector ETF inputs. The top-left cell yields the highest returns, as indicated by the heat map visualization (dark green indicates highest returns).

This initial test suggests that excess returns can be generated by rotating sector allocation over the NBER business cycle dates. We will now expand upon the scope and time frame of our analysis by using Palantir’s Explorer and Index applications to build custom, sector-based indices to rotate.

Part II – Custom Indices Analysis

The Explorer application allows a user to construct a custom group of objects based on filters, metrics, and properties associated with those objects. To analyze US stock performance by sector, we can start with all stocks, and then add a Country filter for the United States, and a GICS Sector filter to isolate all US Stocks for a given sector. We can then apply a relative position filter to select the top 390 stocks by market capitalization. Our selected group of stocks can then be exported to the Index application, where we will aggregate the group into a dynamic index.

The Index application then allows us to drill down and specify how to weight the component instruments of our custom index, as well as how often (if at all) to re-balance the index based on our weighting specification. For this analysis, we will weight our index equally and re-balance it every year, so that we begin each year holding an equal value of each stock that meets our Explorer Group filters at that time. We will also compute our indices’ dynamic membership back to 1979, so we can perform a longer-term 30-year strategy backtest. The result of this workflow is a set of customized, dynamic, sector-based indices that we can now analyze in other Palantir Finance applications as if they were tradable securities.

Figure 5: Constructing instrument groups using the </em>Explorer application. Filters are added for country (United States), GICS sector (Materials), and relative position (top 390 by market cap). The resulting instrument group can be exported to a dynamic index with the click of a button.

Returning to the Strategy application, we can seamlessly plug our custom indices into our previously-built strategy in place of the sector SPDR ETFs, and perform a similar Twiddle analysis to determine the optimal index rotation strategy. Once again, large and statistically significant differences are found between the performance of the various sector indices depending on the business cycle phase. The optimal configuration is as follows: Early Recessions/Health, Late Recessions/Information Technology, Early Expansions/Materials, and Late Expansions/Energy. If an investor had rotated these four top-performing indices over the NBER cycles from 6/30/1979-6/30/2009, an annualized return of 16.9% would have been generated, along with a $108,206,152 profit on an initial $1M investment. Meanwhile, the S&P 500 only delivered a 7.6% annualized return over the same period and a net profit of $7,930,000.

Figure 6: Strategy application results view for the custom indices backtest. Many out-of-the box statistics and analytics are provided to help dissect the results of the strategy. Trade-by-trade statistics are reported, along with charts, benchmark comparisons, and a log of all trade activity for debugging.

IV. Modeling the Business Cycle

In order to build a trading strategy that can be implemented without relying on the after-the-fact NBER peak and trough announcements, we need to perform an analysis to uncover the key economic factors driving the US business cycle. Common macroeconomic theory states that interest rates, production volumes, and consumer confidence are among the key indicators for the US business cycle. To confirm the validity of these indicators, and to build a model of the US business cycle, we can turn to Palantir’s Regression application—a powerful linear regression tool that lets us model one object (in this case, the business cycle dates) against another set of objects (economic indicators).

To set up our analysis, we can convert our NBER DateSet objects that we built previously into binary time series data by calling the ‘toTimeSeries()’ metric. This metric converts a DateSet object into a ‘TimeSeries’ object consisting of 1s (for dates present in the DateSet) and 0s (for dates not present in the DateSet). We can then utilize the Regression application to perform a Linear Probability Model analysis to model our binary date TimeSeries using economic indicator data available in the Palantir platform.

Different regression models were specified for each of the four business cycle phases, and the following four statistically significant economic indicators were identified: US Interest Rates (short term and long term), US Interest Rate yield spreads, and Consumer Confidence and Industrial Production indices.

Figure 7: Regression analysis results for the early expansion US business cycle phase. Our dependent variable is a binary time series of NBER early expansion dates. Independent variables include measures of consumer confidence (CONCCONF, CONEXP), US Interest Rates (USGG6M), US Interest Rates percent change (USGG10yr.percentChange), and two measures of US Interest Rate spreads (USGG3YR-USGG3M, USGG10YR-USGG2YR). All variables are statistically significant at the 97.5% confidence level.

V. Putting It All Together

Now that we’ve confirmed the key indicators of the NBER business cycle phases, we can convert the results of our regression analysis into model business cycle DateSets, against which we can execute a trading strategy. To perform this conversion, we return to the DateSet application and use a series of conditions based on the economic indicators to specify our model DateSets. We can then calibrate our DateSet specifications using a Custom Metric written in Hedgehog language to compare our model DateSets with the NBER’s official DateSets, and to measure accuracy and false positive and negative rates. Finally, we can visually compare our model DateSets to the NBER’s DateSets in the Chart application.

Figure 8: Using a set of conditions (‘TimeSeries filters’) based on the economic indicators to specify model DateSets for the early expansion US business cycle phase. Conditions used include Consumer Confidence in a mid-range (rising from low to high), rising industrial production (percent change > 0), and a positive interest rate yield spread.

An important distinction to note is that our model DateSets use near-real-time data to determine the business cycle phase at any given point in time (some economic indicator data sets have 30-day lags). The NBER peak and trough announcements, on the other hand, occur with a delay of six months of more, and there is no clear way to predict when the economy has moved from an early to late recession or expansion. As a result, our model DateSets provide a much more realistic framework for a real-world trading model than the NBER’s peak and trough data.

Figure 9: Comparing the NBER DateSets (top plot) to our model DateSets (bottom plot) in the Chart application. Conversion accuracy averaged 80% for the four business cycle phases while false positive and negative rates were kept at the 10-20% level.

Now that we’ve constructed our own model business cycle DateSets, we can return to our buy-and-hold trading strategy to see how a sector rotation strategy performs against these DateSets. To optimize our final trading strategy, we can add in a fixed stop to all trades as well as a minimum holding period (the parameter values for these features can be optimized via a Twiddle analysis). The fixed stop will limit our downside on a given trade, and the minimum holding period will ensure that we don’t enter and exit positions too often as a result of the somewhat jumpy model DateSets. Taking our previously-implemented trading strategy, adding these two optimizations, and substituting in our model DateSets yields the following final strategy code:

Setup code:

//Sector indices to test
TimeSeries ENRG = Index("US_ENERGY_TOP390MKTCAP");
TimeSeries UTIL = Index("US_UTIL_TOP390MKTCAP");
TimeSeries TECH = Index("US_IT_TOP390MKTCAP");
TimeSeries HLTH = Index("US_HEALTH_TOP390MKTCAP");

//Variables used to set which sector index is held in which business cycle phase
TimeSeries CYCLE1 = HLTH;
TimeSeries CYCLE2 = STPL;
TimeSeries CYCLE3 = MATS;
TimeSeries CYCLE4 = ENRG;

//Model DateSets for the business cycle phases
DateSet early_rec = DateSet("Early_rec_Model");
DateSet late_rec = DateSet("Late_Rec_Model");
DateSet early_exp = DateSet("Early_Exp_Model");
DateSet late_exp = DateSet("Late_Exp_Model");

//Boolean flag used to track whether we currently have an open position
Boolean pos = false;

//Trading parameters for fixed stop and holding period
Number stop = 12;       //Fixed stop loss of 12%
Number min_hold = 30;   //Minimum holding period of 30 days

Loop code:

//Update Boolean flag to check for automatic exits that may have occurred
if (!hasPosition(CYCLE1) &amp;&amp; !hasPosition(CYCLE2) &amp;&amp;
    !hasPosition(CYCLE3) &amp;&amp; !hasPosition(CYCLE4)) {
    pos = false;

//Buy if DateSet just entered and Sell if DateSet just exited
//Set Fixed Stop for all buy orders, and check minimum holding period for all sell orders
if (!hasPosition(CYCLE1) &amp;&amp; !pos &amp;&amp; early_rec.containsNow()) {
    pos = true;
    buy(HLTH, 100, Enum.PERCENT_OF_NAV);
} else if (hasPosition(CYCLE1)  &amp;&amp; !early_rec.containsNow()) {
    if (periodsSinceEntry(HLTH) &gt; min_hold) {
        pos = false;
} else if (!hasPosition(CYCLE2) &amp;&amp; !pos &amp;&amp; late_rec.containsNow()) {
    pos = true;
    buy(STPL, 100, Enum.PERCENT_OF_NAV);
} else if (hasPosition(CYCLE2)  &amp;&amp; !late_rec.containsNow()) {
    if (periodsSinceEntry(STPL) &gt; min_hold) {
        pos = false;
} else if (!hasPosition(CYCLE3) &amp;&amp; !pos &amp;&amp; early_exp.containsNow()) {
    pos = true;
    buy(MATS, 100, Enum.PERCENT_OF_NAV);
} else if (hasPosition(CYCLE3)  &amp;&amp; !early_exp.containsNow()) {
    if (periodsSinceEntry(MATS) &gt; min_hold) {
        pos = false;
} else if (!hasPosition(CYCLE4) &amp;&amp; !pos &amp;&amp; late_exp.containsNow()) {
    pos = true;
    buy(ENRG, 100, Enum.PERCENT_OF_NAV);
} else if (hasPosition(CYCLE4)  &amp;&amp; !late_exp.containsNow()) {
    if (periodsSinceEntry(ENRG) &gt; min_hold) {
        pos = false;

Figure 10: Final strategy code that trades dynamic sector-based indices over model DateSets for the business cycle phases, using our buy-and-hold rotation strategy optimized with a fixed stop and minimum holding period for all trades.

VI. Final Results & Conclusions

A Twiddle analysis for our final trading strategy implementation was performed to isolate the optimal index and trading parameter inputs. The top-performing sector indices were as follows: Early Recessions/Health, Late Recessions/Consumer Staples, Early Expansions/Materials, and Late Expansions/Energy. The optimal trading parameters identified were a 12% fixed stop-loss and a minimum holding period of 30 days. Using this set of parameter inputs, the final optimized trading strategy (backtested again from 6/30/1979 through 6/30/2009) generated an annualized return of 18.3% compared to a 7.6% annualized return from just holding the S&P 500. If an investor had put forth an initial investment of $1M in 1979, a net profit of $157,892,083 would have been generated over the 30 year timespan of the backtest. Fifty-eight matched trades were made over the backtest, with a W/L ratio of 66% and an average trade P/L of 12%. These key performance indicators confirm our hypothesis that significant returns over major benchmarks can be generated from implementing a sector rotation strategy over our model DateSets.

Figure 11: Strategy results ‘Trade Chart’ perspective for final trading strategy implementation. The top plot shows our strategy NAV over time, while the four plots below display individual trades for each of the four custom sector indices (from top to bottom: Energy/Late Expansions, Health/Early Recessions, Consumer Staples/Late Recessions, Materials/Early Expansions).

Statistics and metrics aside, there is also a common story emerging from our series of analyses. There are large differences in sector performance over the US business cycle, and a general pattern emerged that aligns nicely with other analyses: the health sector fares the best in early recessions as consumers cut spending to necessities. Similarly, consumer staples are the safest bet in the most difficult late recession periods. In early expansions, materials and basic industry lead the pack as capital investment and expectations rise. Finally, the energy sector booms and greatly outperforms other sectors in late expansion periods, before the whole cycle starts over again.

In this study, we have seen how we can analyze a corpus of data seamlessly and flexibly across the Palantir Finance platform, using the DateSet, Explorer, Index, Regression, Custom Metric, and Strategy applications. Additionally, we have demonstrated how Palantir’s intuitive out-of-the-box analytics streamline the process of verifying an investment hypothesis and implementing an associated trading strategy. To continue our analysis, we could perform a similar investigation of how different asset classes perform over the business cycle, and integrate the results into our sector rotation model for an even more targeted and advanced trading strategy.