<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/principal-component-momentum/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://quantstrattrader.wordpress.com/2018/09/17/principal-component-momentum/"> R – QuantStrat TradeR</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>This post will investigate using Principal Components as part of a momentum strategy.</p>
<p>Recently, I ran across a <a rel="nofollow" href="https://cssanalytics.wordpress.com/2018/08/21/2d-asset-allocation-using-pca-part-2/" target="_blank">post from David Varadi</a> that I thought I’d further investigate and translate into code I can explicitly display (as David Varadi doesn’t). Of course, as David Varadi is a quantitative research director with whom I’ve done good work with in the past, I find that trying to investigate his ideas is worth the time spent.</p>
<p>So, here’s the basic idea: in an allegedly balanced universe, containing both aggressive (e.g. equity asset class ETFs) assets and defensive assets (e.g. fixed income asset class ETFs), that principal component analysis, a cornerstone in machine learning, should have some effectiveness at creating an effective portfolio.</p>
<p>I decided to put that idea to the test with the following algorithm:</p>
<p>Using the same assets that David Varadi does, I first use a rolling window (between 6-18 months) to create principal components. Making sure that the SPY half of the loadings is always positive (that is, if the loading for SPY is negative, multiply the first PC by -1, as that’s the PC we use), and then create two portfolios–one that’s comprised of the normalized positive weights of the first PC, and one that’s comprised of the negative half.</p>
<p>Next, every month, I use some momentum lookback period (1, 3, 6, 10, and 12 months), and invest in the portfolio that performed best over that period for the next month, and repeat.</p>
<p>Here’s the source code to do that: (and for those who have difficulty following, I highly recommend James Picerno’s <a rel="nofollow" href="https://www.amazon.com/Quantitative-Investment-Portfolio-Analytics-Introduction/dp/1987583515" target="_blank">Quantitative Investment Portfolio Analytics in R</a> book.</p>
<pre>
require(PerformanceAnalytics)
require(quantmod)
require(stats)
require(xts)

symbols &lt;- c(&quot;SPY&quot;, &quot;EFA&quot;, &quot;EEM&quot;, &quot;DBC&quot;, &quot;HYG&quot;, &quot;GLD&quot;, &quot;IEF&quot;, &quot;TLT&quot;)  

# get free data from yahoo
rets &lt;- list()
getSymbols(symbols, src = 'yahoo', from = '1990-12-31')
for(i in 1:length(symbols)) {
  returns &lt;- Return.calculate(Ad(get(symbols[i])))
  colnames(returns) &lt;- symbols[i]
  rets[[i]] &lt;- returns
}
rets &lt;- na.omit(do.call(cbind, rets2))

# 12 month PC rolling PC window, 3 month momentum window
pcPlusMinus &lt;- function(rets, pcWindow = 12, momWindow = 3) {
  ep &lt;- endpoints(rets)

  wtsPc1Plus &lt;- NULL
  wtsPc1Minus &lt;- NULL
  
  for(i in 1:(length(ep)-pcWindow)) {
    # get subset of returns
    returnSubset &lt;- rets[(ep[i]+1):(ep[i+pcWindow])]
    
    # perform PCA, get first PC (I.E. pc1)
    pcs &lt;- prcomp(returnSubset) 
    firstPc &lt;- pcs[[2]][,1]
    
    # make sure SPY always has a positive loading
    # otherwise, SPY and related assets may have negative loadings sometimes
    # positive loadings other times, and creates chaotic return series
    
    if(firstPc['SPY'] &lt; 0) {
      firstPc &lt;- firstPc * -1
    }
    
    # create vector for negative values of pc1
    wtsMinus &lt;- firstPc * -1
    wtsMinus[wtsMinus &lt; 0] &lt;- 0
    wtsMinus &lt;- wtsMinus/(sum(wtsMinus)+1e-16) # in case zero weights
    wtsMinus &lt;- xts(t(wtsMinus), order.by=last(index(returnSubset)))
    wtsPc1Minus[[i]] &lt;- wtsMinus
    
    # create weight vector for positive values of pc1
    wtsPlus &lt;- firstPc
    wtsPlus[wtsPlus &lt; 0] &lt;- 0
    wtsPlus &lt;- wtsPlus/(sum(wtsPlus)+1e-16)
    wtsPlus &lt;- xts(t(wtsPlus), order.by=last(index(returnSubset)))
    wtsPc1Plus[[i]] &lt;- wtsPlus
  }
  
  # combine positive and negative PC1 weights
  wtsPc1Minus &lt;- do.call(rbind, wtsPc1Minus)
  wtsPc1Plus &lt;- do.call(rbind, wtsPc1Plus)
  
  # get return of PC portfolios
  pc1MinusRets &lt;- Return.portfolio(R = rets, weights = wtsPc1Minus)
  pc1PlusRets &lt;- Return.portfolio(R = rets, weights = wtsPc1Plus)
  
  # combine them
  combine &lt;-na.omit(cbind(pc1PlusRets, pc1MinusRets))
  colnames(combine) &lt;- c(&quot;PCplus&quot;, &quot;PCminus&quot;)
  
  momEp &lt;- endpoints(combine)
  momWts &lt;- NULL
  for(i in 1:(length(momEp)-momWindow)){
    momSubset &lt;- combine[(momEp[i]+1):(momEp[i+momWindow])]
    momentums &lt;- Return.cumulative(momSubset)
    momWts[[i]] &lt;- xts(momentums==max(momentums), order.by=last(index(momSubset)))
  }
  momWts &lt;- do.call(rbind, momWts)
  
  out &lt;- Return.portfolio(R = combine, weights = momWts)
  colnames(out) &lt;- paste(&quot;PCwin&quot;, pcWindow, &quot;MomWin&quot;, momWindow, sep=&quot;_&quot;)
  return(list(out, wtsPc1Minus, wtsPc1Plus, combine))
}


pcWindows &lt;- c(6, 9, 12, 15, 18)
momWindows &lt;- c(1, 3, 6, 10, 12)

permutes &lt;- expand.grid(pcWindows, momWindows)

stratStats &lt;- function(rets) {
  stats &lt;- rbind(table.AnnualizedReturns(rets), maxDrawdown(rets))
  stats[5,] &lt;- stats[1,]/stats[4,]
  stats[6,] &lt;- stats[1,]/UlcerIndex(rets)
  rownames(stats)[4] &lt;- &quot;Worst Drawdown&quot;
  rownames(stats)[5] &lt;- &quot;Calmar Ratio&quot;
  rownames(stats)[6] &lt;- &quot;Ulcer Performance Index&quot;
  return(stats)
}

results &lt;- NULL
for(i in 1:nrow(permutes)) {
  tmp &lt;- pcPlusMinus(rets = rets, pcWindow = permutes$Var1[i], momWindow = permutes$Var2[i])
  results[[i]] &lt;- tmp[[1]]
}
results &lt;- do.call(cbind, results)
stats &lt;- stratStats(results)
</pre>
<p>After a cursory look at the results, it seems the performance is fairly miserable with my implementation, even by the standards of tactical asset allocation models (the good ones have a Calmar and Sharpe Ratio above 1)</p>
<p>Here are histograms of the Calmar and Sharpe ratios.</p>
<p><img data-orig-file="https://quantstrattrader.files.wordpress.com/2018/09/pccalmarhistogram.png?w=456" data-orig-size="799,539" data-medium-file="https://quantstrattrader.files.wordpress.com/2018/09/pccalmarhistogram.png?w=456?w=300" data-attachment-id="1574" data-image-meta="{" data-image-description="" src="https://quantstrattrader.files.wordpress.com/2018/09/pccalmarhistogram.png?w=456" data-permalink="https://quantstrattrader.wordpress.com/2018/09/17/principal-component-momentum/pccalmarhistogram/#main" data-large-file="https://quantstrattrader.files.wordpress.com/2018/09/pccalmarhistogram.png?w=456?w=640" alt="PCCalmarHistogram" data-image-title="PCCalmarHistogram" sizes="(max-width: 640px) 100vw, 640px" data-comments-opened="1" class="wp-image-1574" data-recalc-dims="1"><br>
<img data-orig-file="https://quantstrattrader.files.wordpress.com/2018/09/pcsharpehistogram.png?w=456" data-orig-size="799,539" data-medium-file="https://quantstrattrader.files.wordpress.com/2018/09/pcsharpehistogram.png?w=456?w=300" data-attachment-id="1573" data-image-meta="{" data-image-description="" src="https://quantstrattrader.files.wordpress.com/2018/09/pcsharpehistogram.png?w=456" data-permalink="https://quantstrattrader.wordpress.com/2018/09/17/principal-component-momentum/pcsharpehistogram/#main" data-large-file="https://quantstrattrader.files.wordpress.com/2018/09/pcsharpehistogram.png?w=456?w=640" alt="PCSharpeHistogram" data-image-title="PCSharpeHistogram" sizes="(max-width: 640px) 100vw, 640px" data-comments-opened="1" class="wp-image-1573" data-recalc-dims="1"></p>
<p>These values are generally too low for my liking. Here’s a screenshot of the table of all 25 results.</p>
<p><img data-orig-file="https://quantstrattrader.files.wordpress.com/2018/09/pcresultstable.png?w=456" data-orig-size="991,538" data-medium-file="https://quantstrattrader.files.wordpress.com/2018/09/pcresultstable.png?w=456?w=300" data-attachment-id="1575" data-image-meta="{" data-image-description="" src="https://quantstrattrader.files.wordpress.com/2018/09/pcresultstable.png?w=456" data-permalink="https://quantstrattrader.wordpress.com/2018/09/17/principal-component-momentum/pcresultstable/#main" data-large-file="https://quantstrattrader.files.wordpress.com/2018/09/pcresultstable.png?w=456?w=640" alt="PCresultsTable.PNG" data-image-title="PCresultsTable" sizes="(max-width: 640px) 100vw, 640px" data-comments-opened="1" class="wp-image-1575" data-recalc-dims="1"></p>
<p>While my strategy of choosing which portfolio to hold is different from David Varadi’s (momentum instead of whether or not the aggressive portfolio is above its 200-day moving average), there are numerous studies that show these two methods are closely related, yet the results feel starkly different (and worse) compared to his site.</p>
<p>I’d certainly be willing to entertain suggestions as to how to improve the process, which will hopefully create some more meaningful results. I also know that <a rel="nofollow" href="https://allocatesmartly.com/?aff=177" target="_blank">AllocateSmartly</a> expressed interest in implementing something along these lines for their estimable library of TAA strategies, so I thought I’d try to do it and see what results I’d find, which in this case, aren’t too promising.</p>
<p>Thanks for reading.</p>
<p>NOTE: I am networking, and actively seeking a position related to my skill set in either Philadelphia, New York City, or remotely. If you know of a position which may benefit from my skill set, feel free to let me know. You can reach me on my LinkedIn profile <a rel="nofollow" href="https://www.linkedin.com/in/ilyakipnis/" target="_blank">here</a>, or email me.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://quantstrattrader.wordpress.com/2018/09/17/principal-component-momentum/"> R – QuantStrat TradeR</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/fiA-5EfNXUA" height="1"></a></div>