---
title: "How-to xts"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{How-to xts}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
This vignette demonstrates the step-by-step `FFdownload()` workflow — browse
available datasets, download, and process separately — using `xts` as the output
format. This separation is valuable for reproducible research: you can save a
dated snapshot of the raw zip files and re-process them at any time without
re-downloading.
For a simpler one-step approach (especially for interactive use), see
`vignette("FFD-tibble-how-to")` and the `FFget()` function.
```{r setup, eval=TRUE, echo=FALSE, warning=FALSE, message=FALSE}
library(FFdownload)
outd <- paste0(tempdir(),"/",format(Sys.time(), "%F_%H-%M"))
outfile <- paste0(outd,"FFData_xts.RData")
listfile <- paste0(outd,"FFList.txt")
```
```{r setup2, eval=FALSE, echo=TRUE}
library(FFdownload)
outd <- paste0("data/", format(Sys.time(), "%F_%H-%M"))
outfile <- paste0(outd, "FFData_xts.RData")
listfile <- paste0(outd, "FFList.txt")
```
## Step 1: Browse available datasets
### Option A — `FFlist()` (recommended, new in v1.2.0)
`FFlist()` returns a tidy data frame that you can filter directly:
```{r xts_fflist, eval=FALSE}
fl <- FFlist(exclude_daily = TRUE)
nrow(fl) # 100+ non-daily datasets
head(fl)
# Filter with dplyr
library(dplyr)
fl |> filter(grepl("Momentum|Reversal|5_Factors", name))
```
### Option B — `listsave` (classic approach, still supported)
```{r xts_list_save}
FFdownload(exclude_daily=TRUE, download=FALSE, download_only=TRUE, listsave=listfile)
read.delim(listfile, sep=",")[c(1:4, 73:74), ]
```
### Verifying your search strings with `FFmatch()`
Before downloading, use `FFmatch()` to confirm that your (partial) names map
to the datasets you intend:
```{r xts_ffmatch, eval=FALSE}
FFmatch(c("F-F_Research_Data_Factors_CSV", "F-F_Momentum_Factor_CSV"))
```
## Step 2: Download selected datasets
```{r xts_download}
inputlist <- c("F-F_Research_Data_Factors_CSV","F-F_Momentum_Factor_CSV")
FFdownload(exclude_daily=TRUE, tempd=outd, download=TRUE, download_only=TRUE, inputlist=inputlist)
list.files(outd)
```
The `action` parameter (new in v1.2.0) is equivalent and more readable:
```{r xts_download_action, eval=FALSE}
FFdownload(exclude_daily=TRUE, tempd=outd, action="download_only", inputlist=inputlist)
```
The `cache_days` parameter prevents re-downloading files that are already fresh:
```{r xts_download_cache, eval=FALSE}
# Reuse any cached file younger than 7 days; only download if stale
FFdownload(exclude_daily=TRUE, tempd=outd, action="download_only",
inputlist=inputlist, cache_days=7)
```
## Step 3: Process downloaded files
```{r xts_processing}
FFdownload(exclude_daily=TRUE, tempd=outd, download=FALSE, download_only=FALSE,
inputlist=inputlist, output_file=outfile)
```
To also get the data back directly (skipping a separate `load()` call), add
`return_data=TRUE`:
```{r xts_return_data, eval=FALSE}
FFdata <- FFdownload(exclude_daily=TRUE, tempd=outd, download=FALSE,
download_only=FALSE, inputlist=inputlist,
output_file=outfile, return_data=TRUE)
```
To replace French's missing-value sentinels (`-99`, `-999`, `-99.99`) with `NA`
during processing:
```{r xts_na_values, eval=FALSE}
FFdownload(exclude_daily=TRUE, tempd=outd, download=FALSE, download_only=FALSE,
inputlist=inputlist, output_file=outfile,
na_values=c(-99, -999, -99.99))
```
## Step 4: Inspect the result
```{r xts_load}
load(outfile)
ls.str(FFdata)
```
The output is a named list. Each element corresponds to one dataset and
contains three sub-lists: `$monthly`, `$annual`, and `$daily`. Within each
sub-list, sub-tables are named after the section headings in French's CSV. When
a section has no heading the name defaults to `Temp1`, `Temp2`, etc. — in
factor files the main returns table is always `Temp2`.
```{r xts_names, eval=FALSE}
# Discover sub-table names for the factors dataset
names(FFdata[["x_F-F_Research_Data_Factors"]]$monthly)
#> [1] "Temp2"
names(FFdata[["x_F-F_Research_Data_Factors"]]$annual)
#> [1] "annual_factors:_january-december"
```
## Step 5: Use the data
Code below merges all monthly `xts` objects, trims to post-1963, and plots
cumulative wealth indices (credit: Joshua Ulrich):
```{r xts_process, eval=FALSE, echo=TRUE}
monthly <- do.call(merge, lapply(FFdata, function(i) i$monthly$Temp2))
monthly_1963 <- na.omit(monthly)["1963/"]
monthly_returns <- cumprod(1 + monthly_1963 / 100) - 1
plot(monthly_returns)
```
```{r xts_process2, eval=TRUE, echo=FALSE, out.width="100%", fig.width=8, fig.height=4}
monthly <- do.call(merge, lapply(FFdata, function(i) i$monthly$Temp2))
monthly_1963 <- na.omit(monthly)["1963/"]
monthly_returns <- cumprod(1 + monthly_1963 / 100) - 1
plot(monthly_returns, col=viridis::viridis(5, direction=-1),
legend.loc="topleft", lwd=2,
main="Fama-French & Carhart Factor Wealth Index")
```