Title: | Stock Market Analysis |
---|---|
Description: | Functions for analyzing and visualizing stock market data. Main features are loading and aligning historical data, calculating performance metrics for individual funds or portfolios (e.g. annualized growth, maximum drawdown, Sharpe/Sortino ratio), and creating graphs. |
Authors: | Dane R. Van Domelen |
Maintainer: | Dane R. Van Domelen <[email protected]> |
License: | GPL-3 |
Version: | 2.0.0 |
Built: | 2025-02-22 04:10:35 UTC |
Source: | https://github.com/vandomed/stocks |
Calculates beta for a ticker symbol based on the previous 50 daily gains.
beta_trailing50(ticker, benchmark = "SPY", ...)
beta_trailing50(ticker, benchmark = "SPY", ...)
ticker |
Character string with ticker symbol that Yahoo! Finance recognizes. |
benchmark |
Character string specifying which fund to use as benchmark. |
... |
Arguments to pass to |
Numeric value.
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
## Not run: # Calculate TLT's beta based on the previous 50 daily gains beta_trailing50("TLT") ## End(Not run)
## Not run: # Calculate TLT's beta based on the previous 50 daily gains beta_trailing50("TLT") ## End(Not run)
Mainly a helper function for calc_metrics
and
calc_metrics_overtime
, but could also be used independently.
calc_metric(gains, metric = "mean", units.year = 252, benchmark.gains = NULL)
calc_metric(gains, metric = "mean", units.year = 252, benchmark.gains = NULL)
gains |
Numeric vector. |
metric |
Character string specifying metric to calculate. Choices are
|
units.year |
Integer value. |
benchmark.gains |
Numeric vector. |
Numeric value.
## Not run: # Load daily gains for SPY in 2019 and calculate various metrics gains <- load_gains(tickers = "SPY", from = "2019-01-01", to = "2019-12-31") calc_metric(gains$SPY, "growth") calc_metric(gains$SPY, "cagr") calc_metric(gains$SPY, "mdd") calc_metric(gains$SPY, "sharpe") calc_metric(gains$SPY, "growth.10k") # Calculate alpha and beta for TLT in 2019, using SPY as a benchmark gains <- load_gains(tickers = c("SPY", "TLT"), from = "2019-01-01", to = "2019-12-31") calc_metric(gains = gains$TLT, metric = "alpha", benchmark.gains = gains$SPY) calc_metric(gains = gains$TLT, metric = "beta", benchmark.gains = gains$SPY) ## End(Not run)
## Not run: # Load daily gains for SPY in 2019 and calculate various metrics gains <- load_gains(tickers = "SPY", from = "2019-01-01", to = "2019-12-31") calc_metric(gains$SPY, "growth") calc_metric(gains$SPY, "cagr") calc_metric(gains$SPY, "mdd") calc_metric(gains$SPY, "sharpe") calc_metric(gains$SPY, "growth.10k") # Calculate alpha and beta for TLT in 2019, using SPY as a benchmark gains <- load_gains(tickers = c("SPY", "TLT"), from = "2019-01-01", to = "2019-12-31") calc_metric(gains = gains$TLT, metric = "alpha", benchmark.gains = gains$SPY) calc_metric(gains = gains$TLT, metric = "beta", benchmark.gains = gains$SPY) ## End(Not run)
Useful for comparing funds on one or more metrics.
calc_metrics( gains = NULL, metrics = c("cagr", "mdd", "mean", "sd", "sharpe", "alpha.annualized", "beta", "r"), prices = NULL, tickers = NULL, ..., benchmark = "SPY" )
calc_metrics( gains = NULL, metrics = c("cagr", "mdd", "mean", "sd", "sharpe", "alpha.annualized", "beta", "r"), prices = NULL, tickers = NULL, ..., benchmark = "SPY" )
gains |
Data frame with one column of gains for each investment and a date variable named Date. |
metrics |
Character vector specifying metrics to calculate. Choices are
|
prices |
Data frame with one column of prices for each investment and a date variable named Date. |
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
... |
Arguments to pass along with |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
Data frame with performance metrics for each investment.
## Not run: # Calculate performance metrics for FANG stocks since the beginning of 2019 calc_metrics(tickers = fang, from = "2019-01-01") # Repeat, but use step-by-step approach with piping (need SPY to calculate # alpha and beta) c("SPY", fang) %>% load_gains(from = "2019-01-01") %>% calc_metrics() ## End(Not run)
## Not run: # Calculate performance metrics for FANG stocks since the beginning of 2019 calc_metrics(tickers = fang, from = "2019-01-01") # Repeat, but use step-by-step approach with piping (need SPY to calculate # alpha and beta) c("SPY", fang) %>% load_gains(from = "2019-01-01") %>% calc_metrics() ## End(Not run)
Integrates calc_metrics
, calc_metrics_2funds
, and
calc_metrics_3funds
into a single function, so you can compare
strategies of varying complexities.
calc_metrics_123( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., step = 1, prices = NULL, benchmark = "SPY" )
calc_metrics_123( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., step = 1, prices = NULL, benchmark = "SPY" )
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
metrics |
Character vector specifying metrics to calculate. See
|
tickers |
List where each element is a character vector of ticker
symbols for a particular fund combination, e.g.
|
... |
Arguments to pass along with |
step |
Numeric value specifying fund allocation increments. |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
Data frame with performance metrics for each portfolio at each allocation.
## Not run: # Calculate CAGR vs. max drawdown for BRK-B, SPY/TLT, and VWEHX/VBLTX/VFINX df <- calc_metrics_123( tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")), metrics = c("cagr", "mdd") ) head(df) # To plot, just pipe into plot_metrics_123 df %>% plot_metrics_123() # Or bypass calc_metrics_123 altogether plot_metrics_123( formula = cagr ~ mdd, tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")) ) ## End(Not run)
## Not run: # Calculate CAGR vs. max drawdown for BRK-B, SPY/TLT, and VWEHX/VBLTX/VFINX df <- calc_metrics_123( tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")), metrics = c("cagr", "mdd") ) head(df) # To plot, just pipe into plot_metrics_123 df %>% plot_metrics_123() # Or bypass calc_metrics_123 altogether plot_metrics_123( formula = cagr ~ mdd, tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")) ) ## End(Not run)
Useful for assessing the characteristics of 2-fund portfolios.
calc_metrics_2funds( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., prices = NULL, benchmark = "SPY", ref.tickers = NULL )
calc_metrics_2funds( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., prices = NULL, benchmark = "SPY", ref.tickers = NULL )
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
metrics |
Character vector specifying metrics to calculate. See
|
tickers |
Character vector of ticker symbols, where the first two are are a 2-fund pair, the next two are another, and so on. |
... |
Arguments to pass along with |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
ref.tickers |
Character vector of ticker symbols to include. |
Data frame with performance metrics for each portfolio at each allocation.
## Not run: # Calculate CAGR and max drawdown for UPRO/VBLTX df <- calc_metrics_2funds( metrics = c("cagr", "mdd"), tickers = c("UPRO", "VBLTX") ) head(df) # To plot, just pipe into plot_metrics_2funds df %>% plot_metrics_2funds() # Or bypass calc_metrics_2funds altogether plot_metrics_2funds( formula = cagr ~ mdd, tickers = c("UPRO", "VBLTX") ) ## End(Not run)
## Not run: # Calculate CAGR and max drawdown for UPRO/VBLTX df <- calc_metrics_2funds( metrics = c("cagr", "mdd"), tickers = c("UPRO", "VBLTX") ) head(df) # To plot, just pipe into plot_metrics_2funds df %>% plot_metrics_2funds() # Or bypass calc_metrics_2funds altogether plot_metrics_2funds( formula = cagr ~ mdd, tickers = c("UPRO", "VBLTX") ) ## End(Not run)
Useful for assessing the characteristics of 3-fund portfolios.
calc_metrics_3funds( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., step = 1, prices = NULL, benchmark = "SPY", ref.tickers = NULL )
calc_metrics_3funds( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., step = 1, prices = NULL, benchmark = "SPY", ref.tickers = NULL )
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
metrics |
Character vector specifying metrics to calculate. See
|
tickers |
Character vector of ticker symbols, where the first three are are a 3-fund set, the next three are another, and so on. |
... |
Arguments to pass along with |
step |
Numeric value specifying fund allocation increments. |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
ref.tickers |
Character vector of ticker symbols to include. |
Data frame with performance metrics for each portfolio at each allocation.
## Not run: # Calculate CAGR and max drawdown for UPRO/VBLTX/VWEHX df <- calc_metrics_3funds(metrics = c("cagr", "mdd"), tickers = c("UPRO", "VBLTX", "VWEHX")) head(df) # To plot, just pipe into plot_metrics_3funds df %>% plot_metrics_3funds() # Or bypass calc_metrics_3funds altogether plot_metrics_3funds(formula = cagr ~ mdd, tickers = c("UPRO", "VBLTX", "VWEHX")) ## End(Not run)
## Not run: # Calculate CAGR and max drawdown for UPRO/VBLTX/VWEHX df <- calc_metrics_3funds(metrics = c("cagr", "mdd"), tickers = c("UPRO", "VBLTX", "VWEHX")) head(df) # To plot, just pipe into plot_metrics_3funds df %>% plot_metrics_3funds() # Or bypass calc_metrics_3funds altogether plot_metrics_3funds(formula = cagr ~ mdd, tickers = c("UPRO", "VBLTX", "VWEHX")) ## End(Not run)
Useful for assessing how one or two performance metrics vary over time, for one or several funds. Supports fixed-width rolling windows, fixed-width disjoint windows, and disjoint windows on per-month or per-year basis.
calc_metrics_overtime( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., type = "hop.year", minimum.n = 3, prices = NULL, benchmark = "SPY" )
calc_metrics_overtime( gains = NULL, metrics = c("mean", "sd"), tickers = NULL, ..., type = "hop.year", minimum.n = 3, prices = NULL, benchmark = "SPY" )
gains |
Data frame with one column of gains for each investment and a date variable named Date. |
metrics |
Character vector specifying metrics to calculate. See
|
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
... |
Arguments to pass along with |
type |
Character string or vector specifying type of calculation.
Choices are (1) |
minimum.n |
Integer value specifying the minimum number of observations per period, e.g. if you want to exclude short partial months at the beginning or end of the analysis period. |
prices |
Data frame with a date variable named Date and one column of prices for each investment. |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
Data frame with performance metrics for each investment.
## Not run: # Calculate annual CAGR's, MDD's, and Sharpe ratios for FANG stocks calc_metrics_overtime( tickers = c("FB", "AAPL", "NFLX", "GOOG"), metrics = c("cagr", "mdd", "sharpe"), type = "hop.year" ) ## End(Not run)
## Not run: # Calculate annual CAGR's, MDD's, and Sharpe ratios for FANG stocks calc_metrics_overtime( tickers = c("FB", "AAPL", "NFLX", "GOOG"), metrics = c("cagr", "mdd", "sharpe"), type = "hop.year" ) ## End(Not run)
Implements the following strategy: Each day, hold XIV/SPXU (weighted for zero
beta) if contango > xiv.spxu.cutpoint
, hold VXX/UPRO (weighted for
zero beta) if contango < vxx.upro.cutpoint
, and hold cash otherwise.
Perhaps not very useful since XIV closed on Feb. 20, 2018.
contango_hedged( contango, xiv.spxu.gains = NULL, vxx.upro.gains = NULL, xiv.spxu.cutpoint = 6.36, vxx.upro.cutpoint = 5.45, xiv.allocation = 0.46, vxx.allocation = 0.46, xiv.beta = NULL, vxx.beta = NULL, initial = 10000 )
contango_hedged( contango, xiv.spxu.gains = NULL, vxx.upro.gains = NULL, xiv.spxu.cutpoint = 6.36, vxx.upro.cutpoint = 5.45, xiv.allocation = 0.46, vxx.allocation = 0.46, xiv.beta = NULL, vxx.beta = NULL, initial = 10000 )
contango |
Numeric vector of contango values at the end of each trading day. |
xiv.spxu.gains |
2-column numeric matrix with gains for XIV and SPXU.
Should have the same number of rows as |
vxx.upro.gains |
2-column numeric matrix with gains for VXX and UPRO.
Should have the same number of rows as |
xiv.spxu.cutpoint |
Numeric value giving the contango cutpoint for
XIV/SPXU position. For example, if |
vxx.upro.cutpoint |
Numeric value giving the contango cutpoint for
VXX/UPRO position. For example, if |
xiv.allocation |
Numeric value specifying XIV allocation for XIV/SPXU
position. For example, if set to 0.46, 46% is allocated to XIV and 54% to
SPXU when contango > |
vxx.allocation |
Numeric value specifying VXX allocation for VXX/UPRO
position. For example, if set to 0.46, 46% is allocated to VXX and 54% to
UPRO when contango < |
xiv.beta |
Numeric value specifying XIV's beta. If specified, the
function figures out what |
vxx.beta |
Numeric value indicating VXX's beta. If specified, the
function figures out what |
initial |
Numeric value giving the initial value of the portfolio. |
You can find historical contango values from The Intelligent Investor Blog. You can click the first link at http://investing.kuchita.com/2012/06/28/xiv-data-and-pricing-model-since-vix-futures-available-2004/ to download a zip file containing an Excel spreadsheet. Then, you will need to calculate whatever version of "contango" you prefer. I typically define contango as what percent higher the second-month VIX futures are acompared to the first-month futures, i.e. dividing the "2nd mth" column by the "1st mth" column, subtracting 1, and then multiplying by 100.
To load daily gains for XIV, SPXU, VXX, and UPRO, you can use
load_gains
, which uses the quantmod package to load
data from Yahoo! Finance. You will have to specify the from
and
to
inputs to match the date range for your contango values.
List containing:
Character vector named holdings
indicating what fund was held
each day (XIV/SPXU, VXX/UPRO, or cash).
Numeric vector named port.gains
giving the portfolio gain for
each day, which will be 0 for days that cash was held and the weighted
XIV/SPXU or VXX/UPRO gain for days that one of those positions was held.
Numeric vector named port.balances
giving the portfolio balance
each day.
Numeric value named trades
giving the total number of trades
executed.
Simple strategy: Each day, hold XIV if contango > xiv.cutpoint
, hold
VXX if contango < vxx.cutpoint
, and hold cash otherwise. Perhaps not
very useful since XIV closed on Feb. 20, 2018.
contango_simple( contango, xiv.gains = NULL, vxx.gains = NULL, xiv.cutpoint = 0, vxx.cutpoint = -Inf, initial = 10000 )
contango_simple( contango, xiv.gains = NULL, vxx.gains = NULL, xiv.cutpoint = 0, vxx.cutpoint = -Inf, initial = 10000 )
contango |
Numeric vector of contango values at the end of each trading day. |
xiv.gains |
Numeric vector of gains for XIV. Should be same length as
|
vxx.gains |
Numeric vector of gains for VXX. Should be same length as
|
xiv.cutpoint |
Numeric value giving the contango cutpoint for XIV, in percent. |
vxx.cutpoint |
Numeric value giving the contango cutpoint for VXX, in percent. |
initial |
Numeric value giving the initial value of the portfolio. |
You can find historical contango values from The Intelligent Investor Blog. You can click the first link at http://investing.kuchita.com/2012/06/28/xiv-data-and-pricing-model-since-vix-futures-available-2004/ to download a zip file containing an Excel spreadsheet. Then, you will need to calculate whatever version of "contango" you prefer. I typically define contango as what percent higher the second-month VIX futures are acompared to the first-month futures, i.e. dividing the "2nd mth" column by the "1st mth" column, subtracting 1, and then multiplying by 100.
I think the most common approach for contango-based volatility strategies is
holding XIV (inverse volatility) when contango is above some value (e.g. 0%,
5%, or 10%), and holding cash otherwise. You can do that with this function
by leaving vxx.cutpoint
as -Inf
. However, you may also want to
hold VXX (volatility) when contango is below some value
(e.g. 0%, -5%, -10%), also known as "backwardation". You can implement an
XIV-only, VXX-only, or XIV and VXX strategy with this function.
To load daily gains for XIV and/or VXX, you can use load_gains
,
which uses the quantmod package to load data from Yahoo! Finance. You
will have to specify the from
and to
inputs to match the date
range for your contango values.
List containing:
Character vector named holdings
indicating what fund was held
each day (XIV, VXX, or cash).
Numeric vector named port.gains
giving the portfolio gain for
each day, which will be 0 for days that cash was held and the XIV or VXX gain
for days that XIV or VXX was held.
Numeric vector named port.balances
giving the portfolio balance
each day.
Numeric value named trades
giving the total number of trades
executed.
For example, you can use this function to figure out that an 8% gain over 70 trading days corresponds to 31.9% annualized.
convert_gain(gain, units.in = 1, units.out = 1)
convert_gain(gain, units.in = 1, units.out = 1)
gain |
Numeric vector specifying each gain to convert, e.g. 0.005 for 0.5%. |
units.in |
Numeric value specifying the time period you want to convert from. |
units.out |
Numeric value specifying the time period you want to convert to. |
Numeric vector.
# Calculate annualized gain for an 8% gain over a 70-day period convert_gain(gain = 0.08, units.in = 70, units.out = 252) # Calculate the annual growth rate of a fund that gains 0.02% per day convert_gain(gain = 0.0002, units.in = 1, units.out = 252) # Calculate the annual growth rate of a fund that gains 1% per week convert_gain(gain = 0.01, units.in = 1, units.out = 52) # You invest in AAPL and gain 0.5% in 17 business days. Express as a 5-year # growth rate. convert_gain(gain = 0.005, units.in = 17, units.out = 252 * 5) # Your portfolio has tripled in a 13-year period. Calculate your average # annual gain. convert_gain(gain = 2, units.in = 13, units.out = 1)
# Calculate annualized gain for an 8% gain over a 70-day period convert_gain(gain = 0.08, units.in = 70, units.out = 252) # Calculate the annual growth rate of a fund that gains 0.02% per day convert_gain(gain = 0.0002, units.in = 1, units.out = 252) # Calculate the annual growth rate of a fund that gains 1% per week convert_gain(gain = 0.01, units.in = 1, units.out = 52) # You invest in AAPL and gain 0.5% in 17 business days. Express as a 5-year # growth rate. convert_gain(gain = 0.005, units.in = 17, units.out = 252 * 5) # Your portfolio has tripled in a 13-year period. Calculate your average # annual gain. convert_gain(gain = 2, units.in = 13, units.out = 1)
Mainly a helper function for plot_metrics_overtime
. Work in
progress.
cum_metric(gains, metric = "mean", units.year = 252, benchmark.gains = NULL)
cum_metric(gains, metric = "mean", units.year = 252, benchmark.gains = NULL)
gains |
Numeric vector. |
metric |
Character string. |
units.year |
Integer value. |
benchmark.gains |
Numeric vector. |
Numeric vector.
For example, you can use this function to calculate that an investment that gains 0.1% each day would gain approximately 28.5% in a year (252 trading days).
daily_yearly(gain, years = 1)
daily_yearly(gain, years = 1)
gain |
Numeric vector specifying each gain to convert, e.g. 0.001 for 0.1%. |
years |
Numeric value. |
Numeric value or vector.
# Calculate annual gain for an investment that gains 0.1% per day daily_yearly(gain = 0.001) # Calculate 5-year gains corresponding to various daily gains daily_yearly(gain = seq(0, 0.001, 0.0001), years = 5)
# Calculate annual gain for an investment that gains 0.1% per day daily_yearly(gain = 0.001) # Calculate 5-year gains corresponding to various daily gains daily_yearly(gain = seq(0, 0.001, 0.0001), years = 5)
Calculates differences between subsequent (or lagged) elements of a vector.
Very similar to diff
, but written in C++.
diffs(x, lag = 1L)
diffs(x, lag = 1L)
x |
Numeric vector. |
lag |
Numeric value (e.g. 2 for differences between 1st and 3rd element, 2nd and 4th, ...). |
Numeric vector.
# Generate 1 million values from Poisson(3) distribution x <- rpois(100000, 3) # Calculate vector of differences between subsequent values y <- diffs(x) # Could get same result from base R function diff z <- diff(x) all.equal(y, z) # But diffs is faster benchmark(diffs(x), diff(x), replications = 100)
# Generate 1 million values from Poisson(3) distribution x <- rpois(100000, 3) # Calculate vector of differences between subsequent values y <- diffs(x) # Could get same result from base R function diff z <- diff(x) all.equal(y, z) # But diffs is faster benchmark(diffs(x), diff(x), replications = 100)
Ticker Symbols for FANG Stocks (Facebook Apple, Netflix, Google)
Converts sequence of gains and initial balance to sequence of prices for one or more investments.
gains_prices(gains, initial = 10000, date1 = NULL)
gains_prices(gains, initial = 10000, date1 = NULL)
gains |
Numeric vector of gains for one investment, or data frame with one column for each investment and an optional Date variable. |
initial |
Numeric value. |
date1 |
Date to use for initial price. |
Numeric vector or data frame.
# Simulate daily gains over a 5-year period set.seed(123) gains <- rnorm(n = 252 * 5, mean = 0.001, sd = 0.02) # Plot balance over time if initial balance is $10,000 prices <- gains_prices(gains) plot(prices)
# Simulate daily gains over a 5-year period set.seed(123) gains <- rnorm(n = 252 * 5, mean = 0.001, sd = 0.02) # Plot balance over time if initial balance is $10,000 prices <- gains_prices(gains) plot(prices)
The formula is simply: prod(gains + 1) - 1
. If units.out
is
specified, then it converts to x-unit growth rate.
gains_rate(gains, units.out = NULL)
gains_rate(gains, units.out = NULL)
gains |
Data frame with one column of gains for each investment (can be a numeric vector if there is only one). |
units.out |
Numeric value specifying the number of units for growth
rate calculation, if you want something other than total growth. For
annualized growth rate, set to 252 if |
Numeric vector.
# Create vector of daily gains for a hypothetical stock daily.gains <- c(-0.02, -0.01, 0.01, 0.02, 0.01) # Overall growth is 0.95% gains_rate(daily.gains) # Average daily growth is 0.19% gains_rate(daily.gains, 1) # Corresponds to 61.0% annual growth gains_rate(daily.gains, 252)
# Create vector of daily gains for a hypothetical stock daily.gains <- c(-0.02, -0.01, 0.01, 0.02, 0.01) # Overall growth is 0.95% gains_rate(daily.gains) # Average daily growth is 0.19% gains_rate(daily.gains, 1) # Corresponds to 61.0% annual growth gains_rate(daily.gains, 252)
Scrapes ticker symbols from the Wikipedia Revision history https://en.wikipedia.org/wiki/List_of_S%26P_500_companies. Of course, the data may be imperfect.
get_sp500_tickers(date = Sys.Date())
get_sp500_tickers(date = Sys.Date())
date |
Date (or character vector that can be coerced). |
Character vector.
## Not run: # S&P 500 tickers as of today head(get_sp500_tickers()) # S&P 500 tickers at the beginning of 2019 head(get_sp500_tickers("2019-01-01")) ## End(Not run)
## Not run: # S&P 500 tickers as of today head(get_sp500_tickers()) # S&P 500 tickers at the beginning of 2019 head(get_sp500_tickers("2019-01-01")) ## End(Not run)
High-Yield ETFs from ETFdb.com
https://etfdb.com/etfdb-category/high-yield-bonds/
Mainly a helper function.
label_metric(label)
label_metric(label)
label |
Character string. |
Character string.
Largest 100 Market Cap ETFs (as of 3/2/18) and Inception Dates
http://etfdb.com/compare/market-cap/
Downloads historical gains for specified tickers from Yahoo! Finance, with various options. Relies heavily on the quantmod package.
load_gains( tickers, intercepts = NULL, slopes = NULL, from = "1950-01-01", to = Sys.Date(), time.scale = "daily", preto.days = NULL, prefrom.days = NULL, mutual.lifetimes = TRUE, mutual.start = mutual.lifetimes, mutual.end = mutual.lifetimes, drop.anyNA = FALSE )
load_gains( tickers, intercepts = NULL, slopes = NULL, from = "1950-01-01", to = Sys.Date(), time.scale = "daily", preto.days = NULL, prefrom.days = NULL, mutual.lifetimes = TRUE, mutual.start = mutual.lifetimes, mutual.end = mutual.lifetimes, drop.anyNA = FALSE )
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, or "^CASH" for cash. |
intercepts |
Numeric vector of values to add to daily gains for each fund. |
slopes |
Numeric vector of values to multiply daily gains for each fund by. Slopes are multiplied prior to adding intercepts. |
from |
Date or character string, e.g. |
to |
Date or character string, e.g. |
time.scale |
Character string. Choices are |
preto.days |
Numeric value. If specified, function returns gains for
|
prefrom.days |
Numeric value. If specified, function returns gains for
|
mutual.lifetimes |
Logical value for whether to start on the first day
and end on the last day of the funds' mutual lifetimes (within |
mutual.start |
Logical value for whether to start on the first day of the funds' mutual lifetimes. |
mutual.end |
Logical value for whether to end on the last day of the funds' mutual lifetimes. |
drop.anyNA |
Logical value for whether to drop dates on which prices are missing for any of the funds. |
Data frame with gains for each fund.
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
## Not run: # Load gains for Netflix and Amazon over their mutual lifetimes gains <- load_gains(c("NFLX", "AMZN")) ## End(Not run)
## Not run: # Load gains for Netflix and Amazon over their mutual lifetimes gains <- load_gains(c("NFLX", "AMZN")) ## End(Not run)
Downloads historical prices for specified tickers from Yahoo! Finance, with various options. Relies heavily on the quantmod package.
load_prices( tickers, intercepts = NULL, slopes = NULL, from = "1950-01-01", to = Sys.Date(), time.scale = "daily", preto.days = NULL, prefrom.days = NULL, initial = NULL, mutual.lifetimes = TRUE, mutual.start = mutual.lifetimes, mutual.end = mutual.lifetimes, anchor = FALSE, drop.anyNA = FALSE )
load_prices( tickers, intercepts = NULL, slopes = NULL, from = "1950-01-01", to = Sys.Date(), time.scale = "daily", preto.days = NULL, prefrom.days = NULL, initial = NULL, mutual.lifetimes = TRUE, mutual.start = mutual.lifetimes, mutual.end = mutual.lifetimes, anchor = FALSE, drop.anyNA = FALSE )
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, or "^CASH" for cash. |
intercepts |
Numeric vector of values to add to daily gains for each fund. |
slopes |
Numeric vector of values to multiply daily gains for each fund by. Slopes are multiplied prior to adding intercepts. |
from |
Date or character string, e.g. |
to |
Date or character string, e.g. |
time.scale |
Character string. Choices are |
preto.days |
Numeric value. If specified, function returns prices for
|
prefrom.days |
Numeric value. If specified, function returns prices for
|
initial |
Numeric value specifying what value to scale initial prices to. |
mutual.lifetimes |
Logical value for whether to start on the first day
and end on the last day of the funds' mutual lifetimes (within |
mutual.start |
Logical value for whether to start on the first day of the funds' mutual lifetimes. |
mutual.end |
Logical value for whether to end on the last day of the funds' mutual lifetimes. |
anchor |
Logical value for whether to anchor the starting price for each
fund to the price of the longest-running fund on that day. Useful for
visualizing funds' entire histories while also fairly comparing them over
their mutual lifetimes. Only used if |
drop.anyNA |
Logical value for whether to drop dates on which prices are missing for any of the funds. |
Data frame with closing prices for each fund.
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
## Not run: # Load prices for Netflix and Amazon over their mutual lifetimes prices <- load_prices(c("NFLX", "AMZN")) ## End(Not run)
## Not run: # Load prices for Netflix and Amazon over their mutual lifetimes prices <- load_prices(c("NFLX", "AMZN")) ## End(Not run)
Calculates maximum drawdown from vector of closing prices, highs and lows, or gains. Missing values should be removed prior to calling this function.
mdd(prices = NULL, highs = NULL, lows = NULL, gains = NULL, indices = FALSE)
mdd(prices = NULL, highs = NULL, lows = NULL, gains = NULL, indices = FALSE)
prices |
Numeric vector of daily closing prices. |
highs |
Numeric vector of daily high prices. |
lows |
Numeric vector of daily low prices. |
gains |
Data frame with one column of gains for each investment (extra non-numeric columns are ignored), or numeric vector for one investment. |
indices |
Logical value for whether to include indices for when the maximum drawdown occurred. |
Numeric value, vector, or matrix depending on indices
and whether
there is 1 fund or several.
## Not run: # Calculate MDD's for FANG stocks in 2018 prices <- load_prices(c("FB", "AAPL", "NFLX", "GOOG"), from = "2018-01-01", to = "2018-12-31") sapply(prices[-1], mdd) ## End(Not run)
## Not run: # Calculate MDD's for FANG stocks in 2018 prices <- load_prices(c("FB", "AAPL", "NFLX", "GOOG"), from = "2018-01-01", to = "2018-12-31") sapply(prices[-1], mdd) ## End(Not run)
Mainly a helper function.
metric_decimals(metric)
metric_decimals(metric)
metric |
Character string. |
Character string.
Lookup Table for Performance Metrics
Original
Mainly a helper function.
metric_label(metric)
metric_label(metric)
metric |
Character string. |
Character string.
Mainly a helper function.
metric_title(metric)
metric_title(metric)
metric |
Character string. |
Character string.
Mainly a helper function.
metric_units(metric)
metric_units(metric)
metric |
Character string. |
Character string.
Calculates moving averages or maximum moving average. For optimal speed, use
integer = TRUE
if x
is an integer vector and
integer = FALSE
otherwise.
moving_mean(x, window, integer = FALSE, max = FALSE)
moving_mean(x, window, integer = FALSE, max = FALSE)
x |
Integer or numeric vector. |
window |
Integer value specifying window length. |
integer |
Logical value for whether |
max |
Logical value for whether to return maximum moving average (as opposed to vector of moving averages). |
Numeric value or vector depending on max
.
# 5-unit moving average for integer vector of length 10 x <- rpois(10, lambda = 3) moving_mean(x, 5)
# 5-unit moving average for integer vector of length 10 x <- rpois(10, lambda = 3) moving_mean(x, 5)
Calculates proportion changes between subsequent (or lagged) elements of a vector.
pchanges(x, lag = 1L)
pchanges(x, lag = 1L)
x |
Numeric vector. |
lag |
Numeric value (e.g. 2 for differences between 1st and 3rd element, 2nd and 4th, ...). |
Numeric vector.
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of proportion changes between subsequent values (y <- pchanges(x)) # Equivalent base R computation len <- length(x) p1 <- x[2: len] p2 <- x[1: (len - 1)] y2 <- p1 / p2 - 1 all.equal(y, y2)
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of proportion changes between subsequent values (y <- pchanges(x)) # Equivalent base R computation len <- length(x) p1 <- x[2: len] p2 <- x[1: (len - 1)] y2 <- p1 / p2 - 1 all.equal(y, y2)
Calculates proportion differences between subsequent (or lagged) elements of a vector.
pdiffs(x, lag = 1L)
pdiffs(x, lag = 1L)
x |
Numeric vector. |
lag |
Numeric value (e.g. 2 for differences between 1st and 3rd element, 2nd and 4th, ...). |
Numeric vector.
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of proportion differences between subsequent values (y <- pdiffs(x)) # Equivalent base R computation len <- length(x) p1 <- x[2: len] p2 <- x[1: (len - 1)] y2 <- (p1 - p2) / (0.5 * (p1 + p2)) all.equal(y, y2)
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of proportion differences between subsequent values (y <- pdiffs(x)) # Equivalent base R computation len <- length(x) p1 <- x[2: len] p2 <- x[1: (len - 1)] y2 <- (p1 - p2) / (0.5 * (p1 + p2)) all.equal(y, y2)
Useful for visualizing how two investments behave relate to each other, or how several investments behave relative to the same benchmark.
plot_gains( formula = NULL, ..., gains = NULL, prices = NULL, poly_order = 1, plotly = FALSE, title = NULL, base_size = 16, return = "plot" )
plot_gains( formula = NULL, ..., gains = NULL, prices = NULL, poly_order = 1, plotly = FALSE, title = NULL, base_size = 16, return = "plot" )
formula |
Formula, e.g. |
... |
Arguments to pass along with |
gains |
Data frame with one column of gains for each investment
mentioned in |
prices |
Data frame with one column of prices for each investment
mentioned in |
poly_order |
Numeric value specifying the polynomial order for linear
regression, e.g. |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
In addition to the graph, a list containing fitted linear regression models
returned by lm
for each investment vs. the benchmark.
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
## Not run: # Plot daily gains for SSO and UPRO vs. VFINX p <- plot_gains(SSO + UPRO ~ VFINX) ## End(Not run)
## Not run: # Plot daily gains for SSO and UPRO vs. VFINX p <- plot_gains(SSO + UPRO ~ VFINX) ## End(Not run)
Useful for comparing the performance of several investments, over their full histories or mutual lifetimes.
plot_growth( prices = NULL, tickers = NULL, ..., gains = NULL, initial = 10000, plotly = FALSE, title = "Growth Over Time", base_size = 16, tooltip_size = 20, point_size = 1, line_size = 1, ticklabel_size = 8, legend_position = "right", return = "plot" )
plot_growth( prices = NULL, tickers = NULL, ..., gains = NULL, initial = 10000, plotly = FALSE, title = "Growth Over Time", base_size = 16, tooltip_size = 20, point_size = 1, line_size = 1, ticklabel_size = 8, legend_position = "right", return = "plot" )
prices |
Data frame with one column of prices for each investment and a date variable named Date. |
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
... |
Arguments to pass along with |
gains |
Data frame with one column of gains for each investment and a date variable named Date. |
initial |
Numeric value specifying value to scale initial prices to. |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value to pass to
|
tooltip_size |
Numeric value to pass to |
point_size |
Numeric value to pass to |
line_size |
Numeric value to pass to
|
ticklabel_size |
Numeric value to pass to |
legend_position |
Character string to pass to |
return |
Character string specifying what to return. Choices are
|
Depending on return
and plotly
, a
ggplot
/plotly
object, a data
frame with the source data, or a list containing both.
A ggplot
object.
## Not run: # Plot growth of $10k in VFINX and BRK-B plot_growth(tickers = c("VFINX", "BRK-B")) ## End(Not run)
## Not run: # Plot growth of $10k in VFINX and BRK-B plot_growth(tickers = c("VFINX", "BRK-B")) ## End(Not run)
Useful for visualizing the performance of individual funds. For 2- and 3-fund
portfolios, see plot_metrics_2funds
and plot_metrics_3funds
.
To visualize any combination of single funds and 2- and 3-fund portfolios,
see link{plot_metrics_123}
.
plot_metrics( metrics = NULL, formula = cagr ~ mdd, tickers = NULL, ..., gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, ticklabel_size = 8, return = "plot" )
plot_metrics( metrics = NULL, formula = cagr ~ mdd, tickers = NULL, ..., gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, ticklabel_size = 8, return = "plot" )
metrics |
"Long" data frame with Fund column and column for each metric
you want to plot. Typically the result of a prior call to
|
formula |
Formula specifying what to plot, e.g. |
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
... |
Arguments to pass along with |
gains |
Data frame with one column of gains for each investment and a date variable named Date. |
prices |
Data frame with one column of prices for each investment and a date variable named Date. |
benchmark |
Character string specifying which fund to use as a benchmark for metrics that require one. |
y.benchmark |
Character string specifying which fund to use as benchmark for y-axis metric. |
x.benchmark |
Character string specifying which fund to use as benchmark for x-axis metric. |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value. |
label_size |
Numeric value. |
ticklabel_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
Depending on return
, a ggplot
, a data frame
with the source data, or a list containing both.
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
## Not run: # Plot Sharpe ratio for FANG stocks plot_metrics(formula = sharpe ~ ., tickers = fang) # Create previous plot in step-by-step process with pipes fang %>% load_gains() %>% calc_metrics("sharpe") %>% plot_metrics(. ~ sharpe) # Plot CAGR vs. max drawdown for SPY and BRK-B plot_metrics(formula = cagr ~ mdd, tickers = c("SPY", "BRK-B")) # Create previous plot in step-by-step process with pipes c("SPY", "BRK-B") %>% load_gains() %>% calc_metrics("cagr", "mdd") %>% plot_metrics(cagr ~ mdd) ## End(Not run)
## Not run: # Plot Sharpe ratio for FANG stocks plot_metrics(formula = sharpe ~ ., tickers = fang) # Create previous plot in step-by-step process with pipes fang %>% load_gains() %>% calc_metrics("sharpe") %>% plot_metrics(. ~ sharpe) # Plot CAGR vs. max drawdown for SPY and BRK-B plot_metrics(formula = cagr ~ mdd, tickers = c("SPY", "BRK-B")) # Create previous plot in step-by-step process with pipes c("SPY", "BRK-B") %>% load_gains() %>% calc_metrics("cagr", "mdd") %>% plot_metrics(cagr ~ mdd) ## End(Not run)
Integrates plot_metrics
, plot_metrics_2funds
, and
plot_metrics_3funds
into a single function, so you can visualize
strategies of varying complexities on one figure.
plot_metrics_123( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., step = 1, gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
plot_metrics_123( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., step = 1, gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
metrics |
Data frame with Fund column and column for each metric you
want to plot. Typically the result of a prior call to
|
formula |
Formula specifying what to plot, e.g. |
tickers |
Character vector of ticker symbols, where the first three are are a three-fund set, the next three are another, and so on. |
... |
Arguments to pass along with |
step |
Numeric value specifying fund allocation increments. |
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark , y.benchmark , x.benchmark
|
Character string specifying which
fund to use as benchmark for metrics (if you request |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value. |
label_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
If you prefer to have complete control over the plotting, you can set
return = "data"
to just get the source data.
Depending on return
, a ggplot
object, a data
frame, or a list containing both.
## Not run: # Plot CAGR vs. max drawdown for BRK-B, SPY/TLT, and VWEHX/VBLTX/VFINX plot_metrics_123( formula = cagr ~ mdd, tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")) ) ## End(Not run)
## Not run: # Plot CAGR vs. max drawdown for BRK-B, SPY/TLT, and VWEHX/VBLTX/VFINX plot_metrics_123( formula = cagr ~ mdd, tickers = list("BRK-B", c("SPY", "TLT"), c("VWEHX", "VBLTX", "VFINX")) ) ## End(Not run)
Useful for visualizing the behavior of 2-fund portfolios, e.g. by plotting a measure of growth vs. a measure of volatility.
plot_metrics_2funds( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., points = seq(0, 100, 10), gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, ref.tickers = NULL, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
plot_metrics_2funds( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., points = seq(0, 100, 10), gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, ref.tickers = NULL, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
metrics |
Data frame with Fund column and column for each metric you
want to plot. Typically the result of a prior call to
|
formula |
Formula specifying what to plot, e.g. |
tickers |
Character vector of ticker symbols, where the first two are are a two-fund pair, the next two are another, and so on. |
... |
Arguments to pass along with |
points |
Numeric vector specifying allocations to include as points on
the curve. Set to |
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark , y.benchmark , x.benchmark
|
Character string specifying which
fund to use as benchmark for metrics (if you request |
ref.tickers |
Character vector of ticker symbols to include on the plot. |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value. |
label_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
Depending on return
, a ggplot
object, a data
frame, or a list containing both.
## Not run: # Plot mean vs. SD for UPRO/VBLTX, and compare to SPY plot_metrics_2funds( formula = mean ~ sd, tickers = c("UPRO", "VBLTX") ) # Plot CAGR vs. max drawdown for AAPL/GOOG and FB/TWTR plot_metrics_2funds( formula = cagr ~ mdd, tickers = c("AAPL", "GOOG", "FB", "TWTR") ) # Plot Sharpe ratio vs. allocation for SPY/TLT plot_metrics_2funds( formula = sharpe ~ allocation, tickers = c("SPY", "TLT") ) ## End(Not run)
## Not run: # Plot mean vs. SD for UPRO/VBLTX, and compare to SPY plot_metrics_2funds( formula = mean ~ sd, tickers = c("UPRO", "VBLTX") ) # Plot CAGR vs. max drawdown for AAPL/GOOG and FB/TWTR plot_metrics_2funds( formula = cagr ~ mdd, tickers = c("AAPL", "GOOG", "FB", "TWTR") ) # Plot Sharpe ratio vs. allocation for SPY/TLT plot_metrics_2funds( formula = sharpe ~ allocation, tickers = c("SPY", "TLT") ) ## End(Not run)
Useful for visualizing the behavior of one or several 3-fund portfolios, e.g. by plotting a measure of growth vs. a measure of volatility.
plot_metrics_3funds( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., step = 2.5, gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, ref.tickers = NULL, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
plot_metrics_3funds( metrics = NULL, formula = mean ~ sd, tickers = NULL, ..., step = 2.5, gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, ref.tickers = NULL, plotly = FALSE, title = NULL, base_size = 16, label_size = 5, return = "plot" )
metrics |
Data frame with Fund column and column for each metric you
want to plot. Typically the result of a prior call to
|
formula |
Formula specifying what to plot, e.g. |
tickers |
Character vector of ticker symbols, where the first three are are a 3-fund set, the next three are another, and so on. |
... |
Arguments to pass along with |
step |
Numeric value specifying fund allocation increments. |
gains |
Data frame with a date variable named Date and one column of gains for each fund. |
prices |
Data frame with a date variable named Date and one column of prices for each fund. |
benchmark , y.benchmark , x.benchmark
|
Character string specifying which
fund to use as benchmark for metrics (if you request |
ref.tickers |
Character vector of ticker symbols to include on the graph. |
plotly |
Logical value for whether to convert the
|
title |
Character string. |
base_size |
Numeric value. |
label_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
Depending on return
, a ggplot
object, a data
frame, or a list containing both.
## Not run: # Plot mean vs. SD for UPRO/VBLTX/VWEHX plot_metrics_3funds( formula = mean ~ sd, tickers = c("UPRO", "VBLTX", "VWEHX") ) # Plot CAGR vs. max drawdown for FB/AAPL/NFLX and SPY/TLT/JNK plot_metrics_3funds( formula = cagr ~ mdd, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK") ) # Plot Sharpe ratio vs. allocation for the same sets plot_metrics_3funds( formula = sharpe ~ allocation, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK") ) ## End(Not run)
## Not run: # Plot mean vs. SD for UPRO/VBLTX/VWEHX plot_metrics_3funds( formula = mean ~ sd, tickers = c("UPRO", "VBLTX", "VWEHX") ) # Plot CAGR vs. max drawdown for FB/AAPL/NFLX and SPY/TLT/JNK plot_metrics_3funds( formula = cagr ~ mdd, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK") ) # Plot Sharpe ratio vs. allocation for the same sets plot_metrics_3funds( formula = sharpe ~ allocation, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK") ) ## End(Not run)
Useful for assessing how one or two performance metrics vary over time, for one or several funds. Supports fixed-width rolling windows, fixed-width disjoint windows, and disjoint windows on per-month or per-year basis.
plot_metrics_overtime( metrics = NULL, formula = cagr ~ ., type = "hop.year", minimum.n = 3, tickers = NULL, ..., gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, return = "plot" )
plot_metrics_overtime( metrics = NULL, formula = cagr ~ ., type = "hop.year", minimum.n = 3, tickers = NULL, ..., gains = NULL, prices = NULL, benchmark = "SPY", y.benchmark = benchmark, x.benchmark = benchmark, plotly = FALSE, title = NULL, base_size = 16, return = "plot" )
metrics |
"Long" data frame with Fund column, Date column, and column
for each metric you want to plot. Typically the result of a prior call to
|
formula |
Formula specifying what to plot, e.g. |
type |
Character string or vector specifying type of calculation.
Choices are (1) |
minimum.n |
Integer value specifying the minimum number of observations per period, e.g. if you want to exclude short partial months at the beginning or end of the analysis period. |
tickers |
Character vector of ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
... |
Arguments to pass along with |
gains |
Data frame with a date variable named Date and one column of gains for each investment. |
prices |
Data frame with a date variable named Date and one column of prices for each investment. |
benchmark , y.benchmark , x.benchmark
|
Character string specifying which
fund to use as benchmark for metrics (if you request |
plotly |
Logical value for whether to convert the
|
title |
Character string. Only really useful if you're going to set
|
base_size |
Numeric value. |
return |
Character string specifying what to return. Choices are
|
Depending on return
, a ggplot
, a data frame
with the source data, or a list containing both.
## Not run: # Plot net growth each year for BRK-B and SPY plot_metrics_overtime(formula = growth ~ ., type = "hop.year", tickers = c("BRK-B", "SPY")) # Create previous plot in step-by-step process with pipes c("BRK-B", "SPY") %>% load_gains() %>% calc_metrics_overtime("growth", type = "hop.year") %>% plot_metrics_overtime(growth ~ .) # Plot betas from 100-day disjoint intervals for a 2x daily (SSO) and 3x # daily (UPRO) leveraged ETF plot_metrics_overtime(formula = beta ~ ., type = "hop.100", tickers = c("SSO", "UPRO")) # Create previous plot in step-by-step process with pipes c("SPY", "SSO", "UPRO") %>% load_gains() %>% calc_metrics_overtime(metrics = "beta", type = "hop.100") %>% plot_metrics_overtime(formula = beta ~ .) # Plot 50-day rolling alpha vs. beta for SSO and UPRO during 2018 plot_metrics_overtime( formula = alpha ~ beta, type = "roll.50", tickers = c("SSO", "UPRO"), from = "2018-01-01", to = "2018-12-31" ) # Create previous plot in step-by-step process with pipes c("SPY", "SSO", "UPRO") %>% load_gains(from = "2018-01-01", to = "2018-12-31") %>% calc_metrics_overtime(metrics = c("alpha", "beta"), type = "roll.50") %>% plot_metrics_overtime(alpha ~ beta) ## End(Not run)
## Not run: # Plot net growth each year for BRK-B and SPY plot_metrics_overtime(formula = growth ~ ., type = "hop.year", tickers = c("BRK-B", "SPY")) # Create previous plot in step-by-step process with pipes c("BRK-B", "SPY") %>% load_gains() %>% calc_metrics_overtime("growth", type = "hop.year") %>% plot_metrics_overtime(growth ~ .) # Plot betas from 100-day disjoint intervals for a 2x daily (SSO) and 3x # daily (UPRO) leveraged ETF plot_metrics_overtime(formula = beta ~ ., type = "hop.100", tickers = c("SSO", "UPRO")) # Create previous plot in step-by-step process with pipes c("SPY", "SSO", "UPRO") %>% load_gains() %>% calc_metrics_overtime(metrics = "beta", type = "hop.100") %>% plot_metrics_overtime(formula = beta ~ .) # Plot 50-day rolling alpha vs. beta for SSO and UPRO during 2018 plot_metrics_overtime( formula = alpha ~ beta, type = "roll.50", tickers = c("SSO", "UPRO"), from = "2018-01-01", to = "2018-12-31" ) # Create previous plot in step-by-step process with pipes c("SPY", "SSO", "UPRO") %>% load_gains(from = "2018-01-01", to = "2018-12-31") %>% calc_metrics_overtime(metrics = c("alpha", "beta"), type = "roll.50") %>% plot_metrics_overtime(alpha ~ beta) ## End(Not run)
Converts sequence of prices to sequence of gains for one or more investments.
prices_gains(prices)
prices_gains(prices)
prices |
Numeric vector of prices for one investment or data frame with one column for each investment and an optional Date variable. |
Numeric vector or data frame.
## Not run: # Load 2017 prices for Netflix and Amazon, and calculate growth of $10k prices <- load_prices(c("NFLX", "AMZN"), initial = 1000) # Calculate gains gains <- prices_gains(prices) ## End(Not run)
## Not run: # Load 2017 prices for Netflix and Amazon, and calculate growth of $10k prices <- load_prices(c("NFLX", "AMZN"), initial = 1000) # Calculate gains gains <- prices_gains(prices) ## End(Not run)
The formula is simply: prices[length(prices)] / prices[1] - 1
. If
units.rate
is specified, then it converts to x-unit growth rate.
prices_rate(prices, units.rate = NULL)
prices_rate(prices, units.rate = NULL)
prices |
Numeric vector of prices or data frame with one column for each investment. |
units.rate |
Numeric value specifying the number of units for growth
rate calculation, if you want something other than total growth. For
annualized growth rate, set to 252 if |
Numeric value or vector.
## Not run: # Load historical prices for SPY and TLT and then calculate growth rate prices <- load_prices(tickers = c("SPY", "TLT"), mutual.start = TRUE) prices_rate(prices) # Plot mean vs. SD for UPRO/VBLTX/VWEHX plot_metrics_3funds(mean ~ sd, tickers = c("UPRO", "VBLTX", "VWEHX")) # Plot CAGR vs. MDD for FB/AAPL/NFLX and SPY/TLT/JNK plot_metrics_3funds(cagr ~ mdd, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK")) # Plot Sharpe ratio vs. allocation for the same sets plot_metrics_3funds(sharpe ~ allocation, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK")) ## End(Not run) # Create vector of daily closing prices for a hypothetical stock prices <- c(100.4, 98.7, 101.3, 101.0, 100.9) # Overall growth is 0.50% prices_rate(prices) # Average daily growth is 0.12% prices_rate(prices, 1) # Corresponds to 36.7% annualized growth prices_rate(prices, 252)
## Not run: # Load historical prices for SPY and TLT and then calculate growth rate prices <- load_prices(tickers = c("SPY", "TLT"), mutual.start = TRUE) prices_rate(prices) # Plot mean vs. SD for UPRO/VBLTX/VWEHX plot_metrics_3funds(mean ~ sd, tickers = c("UPRO", "VBLTX", "VWEHX")) # Plot CAGR vs. MDD for FB/AAPL/NFLX and SPY/TLT/JNK plot_metrics_3funds(cagr ~ mdd, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK")) # Plot Sharpe ratio vs. allocation for the same sets plot_metrics_3funds(sharpe ~ allocation, tickers = c("FB", "AAPL", "NFLX", "SPY", "TLT", "JNK")) ## End(Not run) # Create vector of daily closing prices for a hypothetical stock prices <- c(100.4, 98.7, 101.3, 101.0, 100.9) # Overall growth is 0.50% prices_rate(prices) # Average daily growth is 0.12% prices_rate(prices, 1) # Corresponds to 36.7% annualized growth prices_rate(prices, 252)
Calculates vector of ratios of a vector, i.e. ratio of x[2]
to
x[1]
, ratio of x[3]
to x[2]
, and so forth.
ratios(x)
ratios(x)
x |
Numeric vector. |
Numeric vector.
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of ratios (y <- ratios(x)) # Slower base R computation len <- length(x) y2 <- x[2: len] / x[1: (len - 1)] all.equal(y, y2)
# Generate 10 values from N(0, 1) x <- rnorm(10) # Calculate vector of ratios (y <- ratios(x)) # Slower base R computation len <- length(x) y2 <- x[2: len] / x[1: (len - 1)] all.equal(y, y2)
Mainly a helper function for plot_metrics_overtime
.
rolling_metric( gains, metric = "mean", width = 50, units.year = 252, benchmark.gains = NULL )
rolling_metric( gains, metric = "mean", width = 50, units.year = 252, benchmark.gains = NULL )
gains |
Numeric vector. |
metric |
Character string. |
width |
Integer value. |
units.year |
Integer value. |
benchmark.gains |
Numeric vector. |
Numeric vector.
Calculates risk-return ratio, defined as growth rate divided by maximum drawdown.
rrr(prices = NULL, gains = NULL)
rrr(prices = NULL, gains = NULL)
prices |
Numeric vector of prices. |
gains |
Numeric vector of gains. |
Numeric value.
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Convert to daily balances assuming an initial balance of $10,000 daily.balances <- gains_prices(stock.gains + 1) # Total return is about 1.23 daily.balances[length(daily.balances)] / daily.balances[1] - 1 # Maximum drawdown is about 0.19 mdd(prices = daily.balances) # Ratio of these two is about 6.48 (daily.balances[length(daily.balances)] / daily.balances[1] - 1) / mdd(daily.balances) # Easier to calculate using rrr rrr(daily.balances)
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Convert to daily balances assuming an initial balance of $10,000 daily.balances <- gains_prices(stock.gains + 1) # Total return is about 1.23 daily.balances[length(daily.balances)] / daily.balances[1] - 1 # Maximum drawdown is about 0.19 mdd(prices = daily.balances) # Ratio of these two is about 6.48 (daily.balances[length(daily.balances)] / daily.balances[1] - 1) / mdd(daily.balances) # Easier to calculate using rrr rrr(daily.balances)
Sector SPDR ETFs
http://www.sectorspdr.com/sectorspdr/sectors/performance
Calculates Sharpe ratio from vector of gains or prices. The formula is:
(mean(gains) - rf) / sd(gains)
, where rf
is some risk-free rate
of return.
sharpe(gains = NULL, prices = NULL, rf = 0)
sharpe(gains = NULL, prices = NULL, rf = 0)
gains |
Numeric vector of gains. |
prices |
Numeric vector of prices. |
rf |
Numeric value. |
Numeric value.
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Calculate Sharpe ratio using risk-free return of 0 sharpe(stock.gains)
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Calculate Sharpe ratio using risk-free return of 0 sharpe(stock.gains)
Calculates Sortino ratio from vector of gains or prices. The formula is:
(mean(gains) - rf) / sd(gains[gains < 0])
, where rf
is some
risk-free rate of return.
sortino(gains = NULL, prices = NULL, rf = 0)
sortino(gains = NULL, prices = NULL, rf = 0)
gains |
Numeric vector of gains. |
prices |
Numeric vector of prices. |
rf |
Numeric value. |
Numeric value.
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Calculate Sortino ratio using risk-free return of 0 sortino(stock.gains)
# Simulate daily gains over a 5-year period set.seed(123) stock.gains <- rnorm(252 * 5, 0.0005, 0.01) # Calculate Sortino ratio using risk-free return of 0 sortino(stock.gains)
Lookup Table for Wikipedia S&P 500 Pages
Wikipedia
Functions for analyzing and visualizing stock market data. Main features are loading and aligning historical data, calculating performance metrics for individual funds or portfolios (e.g. annualized growth, maximum drawdown, Sharpe/Sortino ratio), and creating graphs.
Package: | stocks |
Type: | Package |
Version: | 2.0.0 |
Date: | 2020-07-14 |
License: | GPL-3 |
See CRAN documentation for full list of functions and the GitHub page for an overview of the package with some examples.
Dane R. Van Domelen
[email protected]
Jeffrey A. Ryan and Joshua M. Ulrich (2019). quantmod: Quantitative Financial Modelling Framework. R package version 0.4-15. https://CRAN.R-project.org/package=quantmod
Implements a trading strategy aimed at maintaining a fixed allocation to each of several funds, rebalancing when the effective allocations deviate too far from the targets.
targetall( tickers = NULL, intercepts = NULL, slopes = NULL, ..., tickers.gains = NULL, target.alls = NULL, tol = 0.05, rebalance.cost = 0, initial = 10000 )
targetall( tickers = NULL, intercepts = NULL, slopes = NULL, ..., tickers.gains = NULL, target.alls = NULL, tol = 0.05, rebalance.cost = 0, initial = 10000 )
tickers |
Character vector specifying 2 ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
intercepts |
Numeric vector of values to add to daily gains for each fund. |
slopes |
Numeric vector of values to multiply daily gains for each fund by. Slopes are multiplied prior to adding intercepts. |
... |
Arguments to pass along with |
tickers.gains |
Data frame with one column of gains for each investment and a date variable named Date. |
target.alls |
Numeric vector specifying target allocations to each fund. If unspecified, equal allocations are used (e.g. 1/3, 1/3, 1/3 if there are 3 funds). |
tol |
Numeric value indicating how far the effective allocations can drift away from the targets before rebalancing. |
rebalance.cost |
Numeric value specifying total cost of each rebalancing trade. |
initial |
Numeric value specifying what value to scale initial prices to. |
List containing:
Numeric matrix named fund.balances
giving fund balances over
time.
Numeric value named rebalance.count
giving the number of
rebalancing trades executed.
## Not run: # Backtest equal-allocation UPRO/VBLTX/VWEHX strategy port <- targetall(tickers = c("UPRO", "VBLTX", "VWEHX")) plot(port$fund.balances[, "Portfolio"]) ## End(Not run)
## Not run: # Backtest equal-allocation UPRO/VBLTX/VWEHX strategy port <- targetall(tickers = c("UPRO", "VBLTX", "VWEHX")) plot(port$fund.balances[, "Portfolio"]) ## End(Not run)
Implements a two-fund strategy where allocations to each fund are adjusted to maintain some user-specified portfolio beta. For example, you could back-test a zero-beta (i.e. market neutral) UPRO/VBLTX strategy using this function.
targetbeta_twofunds( tickers = NULL, intercepts = NULL, slopes = NULL, ..., benchmark.ticker = NULL, reference.tickers = NULL, tickers.gains = NULL, benchmark.gains = NULL, reference.gains = NULL, target.beta = 0, tol = 0.15, window.units = 50, failure.method = "closer", maxall.tol = tol - 0.05, initial = 10000 )
targetbeta_twofunds( tickers = NULL, intercepts = NULL, slopes = NULL, ..., benchmark.ticker = NULL, reference.tickers = NULL, tickers.gains = NULL, benchmark.gains = NULL, reference.gains = NULL, target.beta = 0, tol = 0.15, window.units = 50, failure.method = "closer", maxall.tol = tol - 0.05, initial = 10000 )
tickers |
Character vector specifying 2 ticker symbols that Yahoo! Finance recognizes, if you want to download data on the fly. |
intercepts |
Numeric vector of values to add to daily gains for each fund. |
slopes |
Numeric vector of values to multiply daily gains for each fund by. Slopes are multiplied prior to adding intercepts. |
... |
Arguments to pass along with |
benchmark.ticker |
Character string specifying ticker symbol for
benchmark index for calculating beta. If unspecified, the first fund in
|
reference.tickers |
Character vector of ticker symbols to include on graph as data points for comparative purposes. |
tickers.gains |
Data frame with one column of gains for each investment and a date variable named Date. |
benchmark.gains |
Numeric vector of gains for the benchmark index for
calculating beta. If unspecified, the first fund in |
reference.gains |
Numeric vector or matrix of gains for funds to include on graph as data points for comparative purposes. |
target.beta |
Numeric value. |
tol |
Numeric value specifying how far the effective portfolio beta has
to deviate from |
window.units |
Numeric value specifying the width of the trailing moving window used to estimate each fund's beta. |
failure.method |
Character string or vector specifying method(s) to use
when fund betas are such that the target portfolio beta cannot be achieved.
Choices are |
maxall.tol |
Numeric value specifying tolerance to use when implementing
the |
initial |
Numeric value specifying what value to scale initial prices to. |
The general implementation is as follows. Beta for each of the two funds is
estimated based on the first window.units
gains. Initial allocations
are selected to achieve portfolio beta of target.beta
. If that is not
possible - for example, if target.beta = 0
and both funds have
positive beta - then the action taken depends on what method is selected
through the failure.method
input (details below).
Assuming the target beta is attainable, the function moves over 1 day, and
applies each fund's gains for that day. It then re-calculates each fund's
beta based on the window.units
-width interval, and determines the
effective portfolio beta based on fund allocations and betas. If the
effective beta is outside of [target.beta - tol, target.beta + tol]
, a
rebalancing trade is triggered. As before, if the target beta cannot be
achieved, certain actions are taken depending on the selected method.
When outside of a trade because the target beta could not be achieved, the function attempts to rebalance each time it shifts over to a new day, regardless of the effective portfolio beta.
When failure.method = "cash"
, the entire portfolio balance is
allocated to cash when the target beta cannot be achieved.
When failure.method = "fund1"
(or "fund2"
), the entire
portfolio balance is allocated to the first (or second) fund when the target
beta cannot be achieved.
When failure.method = "fund1.maxall"
(or "fund2.maxall"
), when
the target beta cannot be achieved, fund 1 (or fund 2) is combined with cash,
with the fund 1 (fund 2) allocation as high as possible while staying within
maxall.tol
of target.beta
.
When failure.method = "inverse1"
(or "inverse2"
), an inverse
version of the first (or second) fund is used when the target beta cannot be
achieved. In many cases where the target beta cannot be achieved with the two
funds, it can be achieved with an inverse version of one and the other. If
the target beta still cannot be achieved, the entire portfolio balance is
allocated to cash.
When failure.method = "closer"
, the entire portfolio balance is
allocated to whichever fund has a beta closer to target.beta
.
For each method, a 4-element list containing:
Numeric matrix named fund.balances
giving fund balances over
time.
Numeric matrix named fund.betas
giving fund betas over time.
Numeric vector named effective.betas
giving effective portfolio
beta over time.
Numeric value named trades
giving the total number of trades
executed.
## Not run: # Backtest zero-beta UPRO/VBLTX strategy beta0 <- targetbeta_twofunds(tickers = c("UPRO", "VBLTX"), target.beta = 0) plot(beta0$fund.balances$Portfolio) ## End(Not run)
## Not run: # Backtest zero-beta UPRO/VBLTX strategy beta0 <- targetbeta_twofunds(tickers = c("UPRO", "VBLTX"), target.beta = 0) plot(beta0$fund.balances$Portfolio) ## End(Not run)
Useful for figuring out a time period over which to compare several funds.
ticker_dates(tickers, from = "1950-01-01", to = Sys.Date())
ticker_dates(tickers, from = "1950-01-01", to = Sys.Date())
tickers |
Character vector with ticker symbols that Yahoo! Finance recognizes. |
from |
Date or character string (e.g. |
to |
Date or character string (e.g. |
Data frame with start and end dates for each fund.
## Not run: # See what dates are available for AAPL and AMZN ticker_dates(c("AAPL", "AMZN")) ## End(Not run)
## Not run: # See what dates are available for AAPL and AMZN ticker_dates(c("AAPL", "AMZN")) ## End(Not run)
For internal use only.
title_metric(title)
title_metric(title)
title |
Character string. |
Character string.
Vanguard ETF's
https://investor.vanguard.com/mutual-funds/list#/mutual-funds/asset-class/month-end-returns
Vanguard Mutual Funds
https://investor.vanguard.com/mutual-funds/list#/mutual-funds/asset-class/month-end-returns
Vanguard Products
https://investor.vanguard.com/mutual-funds/list#/mutual-funds/asset-class/month-end-returns