Create a rolling (sliding) version of any function
slidify
returns a rolling (sliding) version of the input function, with a
rolling (sliding) .period
specified by the user.
slidify( .f, .period = 1, .align = c("center", "left", "right"), .partial = FALSE, .unlist = TRUE )
.f |
A function, formula, or vector (not necessarily atomic). If a function, it is used as is. If a formula, e.g.
This syntax allows you to create very compact anonymous functions. If character vector, numeric vector, or list, it is
converted to an extractor function. Character vectors index by
name and numeric vectors index by position; use a list to index
by position and name at different levels. If a component is not
present, the value of |
.period |
The period size to roll over |
.align |
One of "center", "left" or "right". |
.partial |
Should the moving window be allowed to return partial (incomplete) windows
instead of |
.unlist |
If the function returns a single value each time it is called,
use |
The slidify()
function is almost identical to tibbletime::rollify()
with 3 improvements:
Alignment ("center", "left", "right")
Partial windows are allowed
Uses slider
under the hood, which improves speed and reliability by implementing
code at C++ level
Make any function a Sliding (Rolling) Function
slidify()
turns a function into a sliding version
of itself for use inside of a call to dplyr::mutate()
, however it works
equally as well when called from purrr::map()
.
Because of it's intended use with dplyr::mutate()
, slidify
creates a function that always returns output with the same length of the
input
Alignment
Rolling / Sliding functions generate .period - 1
fewer values than the incoming vector.
Thus, the vector needs to be aligned. Alignment of the vector follows 3 types:
center (default): NA
or .partial
values are divided and added to the beginning and
end of the series to "Center" the moving average. This is common in Time Series applications (e.g. denoising).
left: NA
or .partial
values are added to the end to shift the series to the Left.
right: NA
or .partial
values are added to the beginning to shift the series to the Right. This is common in
Financial Applications (e.g moving average cross-overs).
Allowing Partial Windows
A key improvement over tibbletime::slidify()
is that timetk::slidify()
implements
.partial
rolling windows. Just set .partial = TRUE
.
The Tibbletime R Package
by Davis Vaughan, which includes the original rollify()
Function
Transformation Functions:
slidify_vec()
- A simple vectorized function for applying summary functions
to rolling windows.
Augmentation Functions (Add Rolling Multiple Columns):
tk_augment_slidify()
- For easily adding multiple rolling windows to you data
Slider R Package:
slider::pslide()
- The workhorse function that powers timetk::slidify()
library(tidyverse) library(tidyquant) library(tidyr) library(timetk) FB <- FANG %>% filter(symbol == "FB") # --- ROLLING MEAN (SINGLE ARG EXAMPLE) --- # Turn the normal mean function into a rolling mean with a 5 row .period mean_roll_5 <- slidify(mean, .period = 5, .align = "right") FB %>% mutate(rolling_mean_5 = mean_roll_5(adjusted)) # Use `partial = TRUE` to allow partial windows (those with less than the full .period) mean_roll_5_partial <- slidify(mean, .period = 5, .align = "right", .partial = TRUE) FB %>% mutate(rolling_mean_5 = mean_roll_5_partial(adjusted)) # There's nothing stopping you from combining multiple rolling functions with # different .period sizes in the same mutate call mean_roll_10 <- slidify(mean, .period = 10, .align = "right") FB %>% select(symbol, date, adjusted) %>% mutate( rolling_mean_5 = mean_roll_5(adjusted), rolling_mean_10 = mean_roll_10(adjusted) ) # For summary operations like rolling means, we can accomplish large-scale # multi-rolls with tk_augment_slidify() FB %>% select(symbol, date, adjusted) %>% tk_augment_slidify( adjusted, .period = 5:10, .f = mean, .align = "right", .names = str_c("MA_", 5:10) ) # --- GROUPS AND ROLLING ---- # One of the most powerful things about this is that it works with # groups since `mutate` is being used data(FANG) mean_roll_3 <- slidify(mean, .period = 3, .align = "right") FANG %>% group_by(symbol) %>% mutate(mean_roll = mean_roll_3(adjusted)) %>% slice(1:5) # --- ROLLING CORRELATION (MULTIPLE ARG EXAMPLE) --- # With 2 args, use the purrr syntax of ~ and .x, .y # Rolling correlation example cor_roll <- slidify(~cor(.x, .y), .period = 5, .align = "right") FB %>% mutate(running_cor = cor_roll(adjusted, open)) # With >2 args, create an anonymous function with >2 args or use # the purrr convention of ..1, ..2, ..3 to refer to the arguments avg_of_avgs <- slidify( function(x, y, z) (mean(x) + mean(y) + mean(z)) / 3, .period = 10, .align = "right" ) # Or avg_of_avgs <- slidify( ~(mean(..1) + mean(..2) + mean(..3)) / 3, .period = 10, .align = "right" ) FB %>% mutate(avg_of_avgs = avg_of_avgs(open, high, low)) # Optional arguments MUST be passed at the creation of the rolling function # Only data arguments that are "rolled over" are allowed when calling the # rolling version of the function FB$adjusted[1] <- NA roll_mean_na_rm <- slidify(~mean(.x, na.rm = TRUE), .period = 5, .align = "right") FB %>% mutate(roll_mean = roll_mean_na_rm(adjusted)) # --- ROLLING REGRESSIONS ---- # Rolling regressions are easy to implement using `.unlist = FALSE` lm_roll <- slidify(~lm(.x ~ .y), .period = 90, .unlist = FALSE, .align = "right") FB %>% drop_na() %>% mutate(numeric_date = as.numeric(date)) %>% mutate(rolling_lm = lm_roll(adjusted, numeric_date)) %>% filter(!is.na(rolling_lm))
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.