<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/rolling-origins-and-fama-french/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://rviews.rstudio.com/2018/12/26/rolling-origins-and-fama-french/"> R Views</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Today, we continue our work on sampling so that we can run models on subsets of our data and then test the accuracy of the models on data not included in those subsets. In the machine learning prediction world, these two data sets are often called <code>training</code> data and <code>testing</code> data, but we’re not going to do any machine learning prediction today. We’ll stay with our good’ol Fama French regression models for the reasons explained last time: the goal is to explore a new method of sampling our data and I prefer to do that in the context of a familiar model and data set. In 2019, we’ll start expanding our horizons to different models and data, but for today it’s more of a tools exploration.</p>
<p>Loyal readers of this blog (if that’s you, thank you!) will remember that we undertook a similar project in the <a rel="nofollow" href="https://rviews.rstudio.com/2018/12/13/rsampling-fama-french/" target="_blank">previous post</a>, when we used k-fold cross-validation. Today, we will use rolling origin sampling of the data, which differs from k-fold cross-validation in the sense that with rolling origin we explicitly sample based on the dates of our observation. With rolling origin, our first sample starts on the first day, our second sample starts on the second day, our third sample starts on third day. Or, we could have the second sample start on the twentieth day, or we could have it start again on the first day and just include an extra day. Either way, we are aware of the order of our data when sampling. With k-fold cross-validation, we were randomly shuffling and then selecting observations. This distinction can be particularly important for economic time series where we believe that the order of our observations is important.</p>
<p>Let’s get to it.</p>
<p>First, we need our data and, as usual, we’ll import data for daily prices of 5 ETFs, convert them to returns (have a look <a rel="nofollow" href="http://www.reproduciblefinance.com/2017/09/25/asset-prices-to-log-returns/" target="_blank">here</a> for a refresher on that code flow), then import the 5 Fama French factor data and join it to our 5 ETF returns data. Here’s the code to make that happen (this code was covered in detail in <a rel="nofollow" href="http://www.reproduciblefinance.com/2018/06/07/fama-french-write-up-part-one/" target="_blank">this post</a>:</p>
<pre><code>library(tidyverse)
library(tidyquant)
library(rsample)
library(broom)
library(timetk)

symbols &lt;- c(&quot;SPY&quot;, &quot;EFA&quot;, &quot;IJS&quot;, &quot;EEM&quot;, &quot;AGG&quot;)


# The prices object will hold our daily price data.
prices &lt;- 
  getSymbols(symbols, src = 'yahoo', 
             from = &quot;2012-12-31&quot;,
             to = &quot;2017-12-31&quot;,
             auto.assign = TRUE, 
             warnings = FALSE) %>% 
  map(~Ad(get(.))) %>% 
  reduce(merge) %>%
  `colnames&lt;-`(symbols)


asset_returns_long &lt;-  
  prices %>% 
  tk_tbl(preserve_index = TRUE, rename_index = &quot;date&quot;) %>%
  gather(asset, returns, -date) %>% 
  group_by(asset) %>%  
  mutate(returns = (log(returns) - log(lag(returns)))) %>% 
  na.omit()

factors_data_address &lt;- 
&quot;http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Global_5_Factors_Daily_CSV.zip&quot;

factors_csv_name &lt;- &quot;Global_5_Factors_Daily.csv&quot;

temp &lt;- tempfile()

download.file(
  # location of file to be downloaded
  factors_data_address,
  # where we want R to store that file
  temp, 
  quiet = TRUE)


Global_5_Factors &lt;- 
  read_csv(unz(temp, factors_csv_name), skip = 6 ) %>%
  rename(date = X1, MKT = `Mkt-RF`) %>%
  mutate(date = ymd(parse_date_time(date, &quot;%Y%m%d&quot;)))%>%
  mutate_if(is.numeric, funs(. / 100)) %>% 
  select(-RF)

data_joined_tidy &lt;- 
  asset_returns_long %>%
  left_join(Global_5_Factors, by = &quot;date&quot;) %>% 
  na.omit()</code></pre>
<p>After running that code, we have an object called <code>data_joined_tidy</code>. It holds daily returns for 5 ETFs and the Fama French factors. Here’s a look at the first row for each ETF rows.</p>
<pre><code>data_joined_tidy %>% 
  slice(1)</code></pre>
<pre><code># A tibble: 5 x 8
# Groups:   asset [5]
  date       asset  returns    MKT     SMB    HML     RMW     CMA
  </code></pre>