Learn R Programming

PortfolioTesteR (version 0.1.4)

vol_target: Volatility targeting (row-wise) with optional down-only cap

Description

Scales each row of a wide weight table (Date + symbols) so the estimated annualised portfolio volatility matches a target. Volatility is estimated from a rolling covariance of simple asset returns computed from prices.

Usage

vol_target(
  weights,
  prices,
  lookback = 26L,
  target_annual = 0.12,
  periods_per_year = 52L,
  cap = TRUE
)

Value

A data.table with the same Date and symbol columns as weights

(plus CASH when cap = TRUE).

Arguments

weights

data.frame/data.table with columns: Date, then one column per symbol.

prices

data.frame/data.table of adjusted prices at the same cadence as weights: first column Date, remaining columns one per symbol (matching weight symbols).

lookback

Integer window length (in periods) for the rolling covariance. Default 26.

target_annual

Annualised volatility target (e.g., 0.12 for 12%). Must be > 0.

periods_per_year

Number of periods per year used for annualisation (e.g., 52 for weekly).

cap

If TRUE (default), scale down only: exposure is reduced when the estimated vol exceeds the target, and untouched otherwise. In this down-only mode, the function adds/overwrites a CASH column equal to 1 - rowSums(pmax(scaled_weights, 0)) so that symbols + CASH is approximately 1. If FALSE, the scaler may be > 1 (leverage allowed) and no CASH is added.

Details

Weights decided at t-1 apply to returns over t.

The covariance at row i is computed from the last lookback rows of simple returns up to i (inclusive), estimated on the intersection of symbols present in both weights and prices. The row scaler is s_i = min(1, target_vol / est_vol_i) when cap = TRUE, and s_i = target_vol / est_vol_i when cap = FALSE, with safeguards for zero or non-finite variances.

Examples

Run this code
# \donttest{
  data(sample_prices_weekly)
  mom12 <- PortfolioTesteR::calc_momentum(sample_prices_weekly, 12)
  sel10 <- PortfolioTesteR::filter_top_n(mom12, 10)
  w_eq  <- PortfolioTesteR::weight_equally(sel10)

  w_vt  <- vol_target(w_eq, sample_prices_weekly, lookback = 26,
                      target_annual = 0.12, periods_per_year = 52, cap = TRUE)
  head(w_vt)
# }

Run the code above in your browser using DataLab