<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/rsampling-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/13/rsampling-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 will continue our work on Fama French factor models, but more as a vehicle to explore some of the awesome stuff happening in the world of <a rel="nofollow" href="https://www.tidyverse.org/articles/2018/11/tidymodels-update-nov-18/" target="_blank">tidy models</a>. For new readers who want get familiar with Fama French before diving into this post, see <a rel="nofollow" href="https://rviews.rstudio.com/2018/04/11/introduction-to-fama-french/" target="_blank">here</a> where we covered importing and wrangling the data, <a rel="nofollow" href="https://rviews.rstudio.com/2018/05/10/rolling-fama-french/" target="_blank">here</a> where we covered rolling models and visualization, my most recent previous post <a rel="nofollow" href="https://rviews.rstudio.com/2018/11/19/many-factor-models/" target="_blank">here</a> where we covered managing many models, and if you’re into Shiny, <a rel="nofollow" href="http://www.reproduciblefinance.com/shiny/fama-french-three-factor/" target="_blank">this flexdashboard</a>.</p>
<p>Our goal today is to explore k-fold cross-validation via the <code>rsample</code> package, and a bit of model evaluation via the <code>yardstick</code> package. We started the model evaluation theme last time when we used <code>tidy()</code>, <code>glance()</code> and <code>augment()</code> from the <code>broom</code> package. In this post, we will use the <code>rmse()</code> function from <code>yardstick</code>, but our main focus will be on the <code>vfold_cv()</code> function from <code>rsample</code>. We are going to explore these tools in the context of linear regression and Fama French, which might seem weird since these tools would typically be employed in the realms of machine learning, classification, and the like. We’ll stay in the world of explanatory models via linear regression world for a few reasons.</p>
<p>First, and this is a personal preference, when getting to know a new package or methodology, I prefer to do so in a context that’s already familiar. I don’t want to learn about <code>rsample</code> whilst also getting to know a new data set and learning the complexities of some crazy machine learning model. Since Fama French is familiar from our previous work, we can focus on the new tools in <code>rsample</code> and <code>yardstick</code>. Second, factor models are important in finance, despite relying on good old linear regression. We won’t regret time spent on factor models, and we might even find creative new ways to deploy or visualize them.</p>
<p>The plan for today is take the same models that we ran in the last post, only this use k-fold cross validation and bootstrapping to try to assess the quality of those models.</p>
<p>For that reason, we’ll be working with the same data as we did previously. I won’t go through the logic again, but in short, we’ll import data for daily prices of five 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 five Fama French factor data and join it to our five ETF returns data. Here’s the code to make that happen:</p>
<pre><code>library(tidyverse)
library(broom)
library(tidyquant)
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>