Type: | Package |
Title: | Test Investment Strategies with English-Like Code |
Version: | 0.1.1 |
Description: | Design, backtest, and analyze portfolio strategies using simple, English-like function chains. Includes technical indicators, flexible stock selection, portfolio construction methods (equal weighting, signal weighting, inverse volatility, hierarchical risk parity), and a compact backtesting engine for portfolio returns, drawdowns, and summary metrics. |
License: | MIT + file LICENSE |
URL: | https://github.com/alb3rtazzo/PortfolioTesteR |
BugReports: | https://github.com/alb3rtazzo/PortfolioTesteR/issues |
Depends: | R (≥ 3.5.0) |
Imports: | data.table, graphics, stats, TTR, utils, zoo |
Suggests: | quantmod, RSQLite, rvest, knitr, rmarkdown, testthat (≥ 3.0.0) |
VignetteBuilder: | knitr |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.2 |
Config/testthat/edition: | 3 |
ByteCompile: | true |
NeedsCompilation: | no |
Packaged: | 2025-09-16 16:34:14 UTC; alber |
Author: | Alberto Pallotta [aut, cre] |
Maintainer: | Alberto Pallotta <pallottaalberto@gmail.com> |
Repository: | CRAN |
Date/Publication: | 2025-09-22 08:20:02 UTC |
PortfolioTesteR: Test Investment Strategies with English-Like Code
Description
Design, backtest, and analyze portfolio strategies using simple, English-like function chains. Includes technical indicators, flexible stock selection, portfolio construction methods (equal weighting, signal weighting, inverse volatility, hierarchical risk parity), and a compact backtesting engine for portfolio returns, drawdowns, and summary metrics.
Author(s)
Maintainer: Alberto Pallotta pallottaalberto@gmail.com
See Also
Useful links:
Report bugs at https://github.com/alb3rtazzo/PortfolioTesteR/issues
Create Window Splits for Walk-Forward
Description
Create Window Splits for Walk-Forward
Usage
.wf_make_splits(n, is_periods, oos_periods, step)
Align Data to Strategy Timeframe
Description
Aligns higher-frequency data to match strategy timeframe.
Usage
align_to_timeframe(
high_freq_data,
low_freq_dates,
method = c("forward_fill", "nearest", "interpolate")
)
Arguments
high_freq_data |
Data frame to align |
low_freq_dates |
Date vector from strategy |
method |
Alignment method: "forward_fill", "nearest", or "interpolate" |
Value
Aligned data frame
Examples
data("sample_prices_weekly")
data("sample_prices_daily")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
# Create a stability signal from daily data
daily_vol <- calc_rolling_volatility(sample_prices_daily, lookback = 20)
stability_signal <- align_to_timeframe(daily_vol, sample_prices_weekly$Date)
weights <- weight_by_signal(selected, stability_signal)
Analyze Drawdown Characteristics
Description
Detailed analysis of drawdown periods including depth, duration, and recovery.
Usage
analyze_drawdowns(drawdowns, returns)
Arguments
drawdowns |
Drawdown series (negative values) |
returns |
Return series for additional metrics |
Value
List with drawdown statistics
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
weights <- weight_equally(selected)
result <- run_backtest(sample_prices_weekly, weights)
dd_analysis <- analyze_drawdowns(result$portfolio_value, result$dates)
Analyze Backtest Performance with Daily Monitoring
Description
Calculates comprehensive performance metrics using daily price data for enhanced accuracy. Provides risk-adjusted returns, drawdown analysis, and benchmark comparison even when strategy trades at lower frequency.
Usage
analyze_performance(
backtest_result,
daily_prices,
benchmark_symbol = "SPY",
rf_rate = 0,
confidence_level = 0.95
)
Arguments
backtest_result |
Result object from run_backtest() |
daily_prices |
Daily price data including all portfolio symbols |
benchmark_symbol |
Symbol for benchmark comparison (default: "SPY") |
rf_rate |
Annual risk-free rate for Sharpe/Sortino (default: 0) |
confidence_level |
Confidence level for VaR/CVaR (default: 0.95) |
Value
performance_analysis object with metrics and daily tracking
Examples
data("sample_prices_weekly")
data("sample_prices_daily")
# Use overlapping symbols; cap to 3
syms_all <- intersect(names(sample_prices_weekly)[-1], names(sample_prices_daily)[-1])
stopifnot(length(syms_all) >= 1)
syms <- syms_all[seq_len(min(3L, length(syms_all)))]
# Subset weekly (strategy) and daily (monitoring) to the same symbols
P <- sample_prices_weekly[, c("Date", syms), with = FALSE]
D <- sample_prices_daily[, c("Date", syms), with = FALSE]
# Simple end-to-end example
mom <- calc_momentum(P, lookback = 12)
sel <- filter_top_n(mom, n = 3)
W <- weight_equally(sel)
res <- run_backtest(P, W)
# Pick a benchmark that is guaranteed to exist in D
perf <- analyze_performance(res, D, benchmark_symbol = syms[1])
print(perf)
summary(perf)
Analyze Performance Against Benchmark
Description
Calculates benchmark-relative metrics including alpha, beta, tracking error, information ratio, and correlation.
Usage
analyze_vs_benchmark(
portfolio_returns,
benchmark_prices,
dates,
benchmark_symbol = "SPY"
)
Arguments
portfolio_returns |
Portfolio return series data("sample_prices_weekly") |
benchmark_prices |
Benchmark price data with dates |
dates |
Portfolio dates |
benchmark_symbol |
Benchmark name for reporting |
Value
List of benchmark comparison metrics
Apply Market Regime Filter
Description
Applies regime-based filtering. When regime is FALSE (e.g., bear market), all selections become 0, moving portfolio to cash.
Usage
apply_regime(selection_df, regime_condition, partial_weight = 0)
Arguments
selection_df |
Binary selection matrix |
regime_condition |
Logical vector (TRUE = trade, FALSE = cash) |
partial_weight |
Fraction to hold when regime is FALSE (default: 0) |
Value
Modified selection matrix respecting regime
Examples
data("sample_prices_weekly")
# Create selection
momentum <- calc_momentum(sample_prices_weekly, 12)
selected <- filter_top_n(momentum, 10)
# Only trade when SPY above 20-week MA
ma20 <- calc_moving_average(sample_prices_weekly, 20)
spy_regime <- sample_prices_weekly$SPY > ma20$SPY
spy_regime[is.na(spy_regime)] <- FALSE
regime_filtered <- apply_regime(selected, spy_regime)
Apply Weighting Method to Values
Description
Internal utility function that applies various weighting methods to a vector. Used by other weighting functions.
Usage
apply_weighting_method(values, method = "rank", preference_ascending = TRUE)
Arguments
values |
Named numeric vector of values to weight |
preference_ascending |
TRUE = prefer lower values, FALSE = prefer higher |
Value
Named numeric vector of weights that sum to 1
Convert Conditions to Selection Format
Description
Converts condition matrices or data frames to standard selection format with Date column and binary values. Handles NA by converting to 0.
Usage
as_selection(condition_matrix, date_column = NULL)
Arguments
condition_matrix |
Matrix or data frame with conditions |
date_column |
Optional Date vector if not in input |
Value
Data.table in selection format (Date + binary columns)
Examples
data("sample_prices_weekly")
ma20 <- calc_moving_average(sample_prices_weekly, 20)
above_ma <- filter_above(calc_distance(sample_prices_weekly, ma20), 0)
selection <- as_selection(above_ma, sample_prices_weekly$Date)
Calculate Comprehensive Backtest Metrics
Description
Computes performance metrics including Sharpe ratio, maximum drawdown, win rate, and other statistics from backtest results.
Usage
backtest_metrics(result)
Arguments
result |
Backtest result object from run_backtest() |
Value
List containing performance metrics
Examples
# Create a backtest result to use
data(sample_prices_weekly)
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
weights <- weight_equally(selected)
result <- run_backtest(sample_prices_weekly, weights)
# Calculate metrics
metrics <- backtest_metrics(result)
print(metrics$sharpe_ratio)
Calculate Commodity Channel Index (CCI)
Description
Calculates CCI using closing prices. CCI measures deviation from average price. Values above 100 indicate overbought, below -100 indicate oversold.
Usage
calc_cci(data, period = 20)
Arguments
data |
Data frame with Date column and price columns |
period |
CCI period (default: 20) |
Value
Data.table with CCI values
Examples
data("sample_prices_weekly")
cci <- calc_cci(sample_prices_weekly, period = 20)
Calculate Distance from Reference
Description
data("sample_prices_weekly") Calculates percentage distance between prices and reference values (typically moving averages).
Usage
calc_distance(price_df, reference_df)
Arguments
price_df |
Data frame with price data |
reference_df |
Data frame with reference values (same structure) |
Value
Data.table with percentage distances
Examples
data("sample_prices_weekly")
ma20 <- calc_moving_average(sample_prices_weekly, 20)
data("sample_prices_weekly")
distance <- calc_distance(sample_prices_weekly, ma20)
Calculate Market Breadth Percentage
Description
Measures the percentage of stocks meeting a condition (market participation). Useful for assessing market health and identifying broad vs narrow moves.
Usage
calc_market_breadth(condition_df, min_stocks = 10)
Arguments
condition_df |
Data frame with Date column and TRUE/FALSE values |
min_stocks |
Minimum stocks required for valid calculation (default: 10) |
Value
A data.table
with Date
and Breadth_[Sector]
columns (0–100 scale)
Examples
# Percent of stocks above 200-day MA
data("sample_prices_weekly")
ma200 <- calc_moving_average(sample_prices_weekly, 200)
above_ma <- filter_above(calc_distance(sample_prices_weekly, ma200), 0)
breadth <- calc_market_breadth(above_ma)
Calculate Price Momentum
Description
Calculates momentum as the percentage change in price over a specified lookback period. Optimized using column-wise operations (25x faster).
Usage
calc_momentum(data, lookback = 12)
Arguments
data |
A data.frame or data.table with Date column and price columns |
lookback |
Number of periods for momentum calculation (default: 12) |
Value
Data.table with momentum values (0.1 = 10% increase)
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
Calculate Moving Average
Description
Calculates simple moving average for each column in the data.
Usage
calc_moving_average(data, window = 20)
Arguments
data |
Data frame with Date column and price columns |
window |
Number of periods for moving average (default: 20) |
Value
Data.table with moving average values
Examples
data("sample_prices_weekly")
ma20 <- calc_moving_average(sample_prices_weekly, window = 20)
Calculate Cross-Sectional Ranking of Indicators
Description
Ranks each stock's indicator value against all other stocks on the same date. Enables relative strength strategies that adapt to market conditions. Optimized using matrix operations for 15x speedup.
Usage
calc_relative_strength_rank(
indicator_df,
method = c("percentile", "rank", "z-score")
)
Arguments
indicator_df |
Data frame with Date column and indicator values |
method |
Ranking method: "percentile" (0-100), "rank" (1-N), or "z-score" |
Value
Data frame with same structure containing ranks/scores
Examples
# Rank RSI across all stocks
data("sample_prices_weekly")
rsi <- calc_rsi(sample_prices_weekly, 14)
rsi_ranks <- calc_relative_strength_rank(rsi, method = "percentile")
# Find relatively overbought (top 10%)
relative_overbought <- filter_above(rsi_ranks, 90)
Calculate Rolling Volatility
Description
Calculates rolling volatility using various methods including standard deviation, range-based, MAD, or absolute returns. Supports different lookback periods.
Usage
calc_rolling_volatility(data, lookback = 20, method = "std")
Arguments
data |
Data frame with Date column and price columns |
lookback |
Number of periods for rolling calculation (default: 20) |
method |
Volatility calculation method: "std", "range", "mad", or "abs_return" |
Value
Data frame with Date column and volatility values for each symbol
Examples
data("sample_prices_weekly")
# Standard deviation volatility
vol <- calc_rolling_volatility(sample_prices_weekly, lookback = 20)
# Range-based volatility
vol_range <- calc_rolling_volatility(sample_prices_weekly, lookback = 20, method = "range")
Calculate Relative Strength Index (RSI)
Description
Calculates RSI for each column. RSI ranges from 0-100. Above 70 indicates overbought, below 30 indicates oversold.
Usage
calc_rsi(data, period = 14)
Arguments
data |
Data frame with Date column and price columns |
period |
RSI period (default: 14) |
Value
Data.table with RSI values (0-100 range)
Examples
data("sample_prices_weekly")
rsi <- calc_rsi(sample_prices_weekly, period = 14)
overbought <- filter_above(rsi, 70)
Calculate Market Breadth by Sector
Description
Measures participation within each sector separately, revealing which sectors have broad strength vs concentrated leadership. Optimized using pre-splitting for speed.
Usage
calc_sector_breadth(
condition_df,
sector_mapping,
min_stocks_per_sector = 3,
na_sector_action = c("exclude", "separate", "market")
)
Arguments
condition_df |
Data frame with Date column and TRUE/FALSE values |
sector_mapping |
Data frame with |
min_stocks_per_sector |
Minimum stocks for valid sector breadth (default: 3) |
na_sector_action |
How to handle unmapped stocks: "exclude", "separate", or "market" |
Value
A data.table
with Date
and Breadth_[Sector]
columns (0–100 scale)
Examples
data("sample_prices_weekly")
data("sample_sp500_sectors")
ma200 <- calc_moving_average(sample_prices_weekly, 200)
above_ma <- filter_above(calc_distance(sample_prices_weekly, ma200), 0)
sector_breadth <- calc_sector_breadth(above_ma, sample_sp500_sectors)
Calculate Indicators Relative to Sector Average
Description
Measures how each stock's indicator compares to its sector benchmark. Enables sector-neutral strategies and identifies sector outperformers.
Usage
calc_sector_relative_indicators(
indicator_df,
sector_mapping,
method = c("difference", "ratio", "z-score"),
benchmark = c("mean", "median"),
ratio_threshold = 0.01,
min_sector_size = 2
)
Arguments
indicator_df |
Data frame with Date column and indicator values |
sector_mapping |
Data frame with |
method |
"difference" (absolute), "ratio" (relative), or "z-score" |
benchmark |
"mean" or "median" sector average |
ratio_threshold |
Minimum denominator for ratio method (default: 0.01) |
min_sector_size |
Minimum stocks per sector (default: 2) |
Value
Data frame with sector-relative values
Examples
# Find stocks outperforming their sector
data("sample_prices_weekly")
data("sample_sp500_sectors")
momentum <- calc_momentum(sample_prices_weekly, 12)
relative_momentum <- calc_sector_relative_indicators(
momentum, sample_sp500_sectors, method = "difference"
)
Calculate Stochastic D Indicator
Description
Calculates the Stochastic D indicator for momentum analysis. The %D line is the smoothed version of %K, commonly used for momentum signals in range 0-100.
Usage
calc_stochastic_d(data, k = 14, d = 3)
Arguments
data |
Price data with Date column and symbol columns |
k |
Lookback period for stochastic K calculation |
d |
Smoothing period for D line |
Value
Data.table with Stochastic D values for each symbol
Examples
data("sample_prices_weekly")
data(sample_prices_weekly)
data("sample_prices_weekly")
stoch_d <- calc_stochastic_d(sample_prices_weekly, k = 14, d = 3)
head(stoch_d)
Calculate Annualized Return
Description
Converts total return to annualized return based on time period.
Usage
calculate_annualized_return(result)
Arguments
result |
Backtest result object |
Value
Annualized return as decimal (0.1 = 10%)
Optimized cluster variance calculation
Description
Optimized cluster variance calculation
Optimized cluster variance calculation
Usage
calculate_cluster_variance_optimized(cov_matrix, asset_names)
calculate_cluster_variance_optimized(cov_matrix, asset_names)
Calculate Drawdown Time Series
Description
Computes drawdown series from portfolio values.
Usage
calculate_drawdown_series(values)
Arguments
values |
Numeric vector of portfolio values |
Value
Numeric vector of drawdowns (as negative percentages)
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
sel <- filter_top_n(momentum, n = 10)
W <- weight_equally(sel)
res <- run_backtest(sample_prices_weekly, W)
dd_series <- calculate_drawdown_series(res$portfolio_values)
dd_stats <- analyze_drawdowns(dd_series, res$returns)
Calculate Portfolio Drawdowns
Description
Calculates drawdown series from portfolio values. Drawdown is the percentage decline from the previous peak.
Usage
calculate_drawdowns(values)
Arguments
values |
Numeric vector of portfolio values |
Value
Numeric vector of drawdown percentages (negative values)
Calculate Enhanced Performance Metrics
Description
Computes comprehensive risk and return metrics from daily data including Sharpe, Sortino, Calmar ratios, VaR, CVaR, and tail risk measures.
Usage
calculate_enhanced_metrics(
daily_values,
daily_returns,
rf_rate = 0,
confidence_level = 0.95
)
Arguments
daily_values |
Daily portfolio values |
daily_returns |
Daily return series |
rf_rate |
Risk-free rate |
confidence_level |
VaR/CVaR confidence level |
Value
List of performance metrics
Calculate Equal Risk Contribution weights (simplified)
Description
Calculate Equal Risk Contribution weights (simplified)
Usage
calculate_erc_weights(cov_matrix, asset_names)
Calculate HRP weights for a given returns matrix
Description
Calculate HRP weights for a given returns matrix
Usage
calculate_hrp_weights(
returns_matrix,
asset_names,
cluster_method,
distance_method
)
Calculate Maximum Diversification Portfolio weights
Description
Calculate Maximum Diversification Portfolio weights
Usage
calculate_max_div_weights(cov_matrix, asset_names)
Combine Multiple Filter Conditions
Description
Combines multiple filter conditions using AND or OR logic.
Usage
combine_filters(..., op = "and", apply_when = NULL, debug = FALSE)
Arguments
... |
Two or more filter data frames to combine |
op |
Operation: "and" or "or" |
apply_when |
Optional condition vector for conditional filtering |
debug |
Print debug information (default: FALSE) |
Value
Combined binary selection matrix
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
rsi <- calc_rsi(sample_prices_weekly, 14)
# Create individual filters
high_momentum <- filter_above(momentum, 0.05)
moderate_rsi <- filter_between(rsi, 40, 60)
# Combine them
combined <- combine_filters(high_momentum, moderate_rsi, op = "and")
Combine Multiple Weighting Schemes
Description
Blends multiple weight matrices with specified weights. Useful for multi-factor strategies that combine different allocation approaches. Optimized using matrix operations for 1000x+ speedup.
Usage
combine_weights(weight_matrices, weights = NULL)
Arguments
weight_matrices |
List of weight data frames to combine |
weights |
Numeric vector of weights for each matrix (default: equal) |
Value
Data.table with blended portfolio weights
Examples
data("sample_prices_weekly")
# Calculate signals
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
volatility <- calc_rolling_volatility(sample_prices_weekly, lookback = 20)
# Combine momentum and low-vol weights
mom_weights <- weight_by_signal(selected, momentum)
vol_weights <- weight_by_signal(selected, invert_signal(volatility))
combined <- combine_weights(list(mom_weights, vol_weights), weights = c(0.7, 0.3))
Convert Data to N-Week Frequency
Description
Resamples daily or weekly data to n-week periods. Handles week-ending calculations and various aggregation methods.
Usage
convert_to_nweeks(data, n = 1, method = "last")
Arguments
data |
Data.table with Date column and price columns |
n |
Number of weeks to aggregate (default: 1 for weekly) |
method |
Aggregation method: "last" or "mean" (default: "last") |
Value
Data.table resampled to n-week frequency
Examples
data("sample_prices_daily")
# Convert daily to weekly
weekly <- convert_to_nweeks(sample_prices_daily, n = 1)
# Convert to bi-weekly
biweekly <- convert_to_nweeks(sample_prices_daily, n = 2)
Convert Continuous Indicator to Discrete Regimes
Description
Transforms continuous indicators into discrete regime categories.
Usage
create_regime_buckets(
indicator,
breakpoints,
labels = NULL,
use_percentiles = FALSE
)
Arguments
indicator |
Numeric vector or data frame with indicator values |
breakpoints |
Numeric vector of breakpoints |
labels |
Optional character vector of regime names |
use_percentiles |
Use percentiles instead of fixed breakpoints (default: FALSE) |
Value
Integer vector of regime classifications
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
# Create VIX-like indicator from volatility
vol <- calc_rolling_volatility(sample_prices_weekly, lookback = 20)
vix_proxy <- vol$SPY * 100 # Scale to VIX-like values
regimes <- create_regime_buckets(vix_proxy, c(15, 25))
Load Price Data from CSV File
Description
Reads stock price data from CSV files with flexible column naming. Automatically standardizes to library format.
Usage
csv_adapter(
file_path,
date_col = "Date",
symbol_col = "Symbol",
price_col = "Price",
frequency = "daily",
symbol_order = NULL
)
Arguments
file_path |
Path to CSV file |
date_col |
Name of date column (default: "date") |
symbol_col |
Name of symbol column (default: "symbol") |
price_col |
Name of price column (default: "close") |
frequency |
Target frequency: "daily" or "weekly" (default: "daily") |
symbol_order |
Optional vector to order symbols |
Value
Data.table with Date column and price columns
Examples
# Create a temporary tidy CSV from included weekly sample data (offline, fast)
data("sample_prices_weekly")
PW <- as.data.frame(sample_prices_weekly)
syms <- setdiff(names(PW), "Date")[1:2]
stk <- stack(PW[1:10, syms])
tidy <- data.frame(
Date = rep(PW$Date[1:10], times = length(syms)),
Symbol = stk$ind,
Price = stk$values
)
tmp <- tempfile(fileext = ".csv")
write.csv(tidy, tmp, row.names = FALSE)
prices <- csv_adapter(tmp)
head(prices)
unlink(tmp)
Download S&P 500 Sector Mappings from Wikipedia
Description
Scrapes current S&P 500 constituent list with sector classifications from Wikipedia and returns as a data.table.
Usage
download_sp500_sectors()
Value
Data.table with columns: Symbol, Security, Sector, SubIndustry, Industry
Examples
sectors <- download_sp500_sectors()
head(sectors)
Ensure Data.Table Without Mutation
Description
Converts input to data.table if needed, always returning a copy to prevent accidental data mutation. Core safety function used throughout the library.
Usage
ensure_dt_copy(data)
Arguments
data |
Data.frame or data.table |
Value
Copy of data as data.table
Examples
data("sample_prices_weekly")
dt <- ensure_dt_copy(sample_prices_weekly) # Safe to modify dt
Filter Stocks Above Threshold
Description
Convenience function to select stocks with signal above a value.
Usage
filter_above(signal_df, value)
Arguments
signal_df |
Data frame with signal values |
value |
Threshold value |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
rsi <- calc_rsi(sample_prices_weekly, 14)
high_rsi <- filter_above(rsi, 70)
Filter Stocks Below Threshold
Description
Convenience function to select stocks with signal below a value.
Usage
filter_below(signal_df, value)
Arguments
signal_df |
Data frame with signal values |
value |
Threshold value |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
rsi <- calc_rsi(sample_prices_weekly, 14)
oversold <- filter_below(rsi, 30)
Filter Stocks Between Two Values
Description
Selects stocks with signal values between lower and upper bounds.
Usage
filter_between(signal_df, lower, upper)
Arguments
signal_df |
Data frame with signal values |
lower |
Lower bound (inclusive) |
upper |
Upper bound (inclusive) |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
rsi <- calc_rsi(sample_prices_weekly, 14)
# Select stocks with RSI between 30 and 70
neutral_rsi <- filter_between(rsi, 30, 70)
Filter by Percentile
Description
Select securities in the top or bottom X percentile. More intuitive than filter_top_n when universe size varies.
Usage
filter_by_percentile(signal_df, percentile, type = c("top", "bottom"))
Arguments
signal_df |
DataFrame with signal values |
percentile |
Percentile threshold (0-100) |
type |
"top" for highest signals, "bottom" for lowest |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
# Select top 20th percentile
top_20pct <- filter_by_percentile(momentum, 20, type = "top")
Select Top or Bottom N Stocks by Signal
Description
Selects the top N (best) or worst N stocks based on signal strength. Optimized using matrix operations for 5-10x speedup.
Usage
filter_rank(signal_df, n, type = c("top", "worst"))
Arguments
signal_df |
Data frame with Date column and signal values |
n |
Number of stocks to select |
type |
"top" for highest values, "worst" for lowest values |
Value
Binary selection matrix (1 = selected, 0 = not selected)
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
# Select 10 highest momentum stocks
top10 <- filter_rank(momentum, 10, type = "top")
Filter by Threshold Value
Description
Selects stocks above or below a threshold value.
Usage
filter_threshold(signal_df, value, type = c("above", "below"))
Arguments
signal_df |
Data frame with signal values |
value |
Threshold value |
type |
"above" or "below" |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
# Select stocks with positive momentum
positive <- filter_threshold(momentum, 0, type = "above")
Select Top N Stocks by Signal Value
Description
Most commonly used filter function. Selects top N (highest) or bottom N (lowest) stocks by signal value. Optimized for 5-10x faster performance.
Usage
filter_top_n(signal_df, n, ascending = FALSE)
Arguments
signal_df |
Data frame with Date column and signal values |
n |
Number of stocks to select |
ascending |
FALSE (default) selects highest, TRUE selects lowest |
Value
Binary selection matrix (1 = selected, 0 = not selected)
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
# Select 10 highest momentum stocks
top_momentum <- filter_top_n(momentum, n = 10)
Select Top N from Qualified Stocks
Description
Selects top N stocks by signal, but only from those meeting a condition. Combines qualification and ranking in one step.
Usage
filter_top_n_where(
signal_df,
n,
condition_df,
min_qualified = 1,
ascending = FALSE
)
Arguments
signal_df |
Signal values for ranking |
n |
Number to select |
condition_df |
Binary matrix of qualified stocks |
min_qualified |
Minimum qualified stocks required (default: 1) |
ascending |
FALSE for highest, TRUE for lowest |
Value
Binary selection matrix
Examples
data("sample_prices_weekly")
# Calculate indicators
momentum <- calc_momentum(sample_prices_weekly, 12)
ma20 <- calc_moving_average(sample_prices_weekly, 20)
distance_from_ma <- calc_distance(sample_prices_weekly, ma20)
# Top 10 momentum stocks from those above MA
above_ma <- filter_above(distance_from_ma, 0)
top_qualified <- filter_top_n_where(momentum, 10, above_ma)
Detect Data Frequency from Dates
Description
Automatically detects whether data is daily, weekly, monthly, or quarterly based on date spacing.
Usage
get_data_frequency(dates)
Arguments
dates |
Vector of Date objects |
Value
Character string: "daily", "weekly", "monthly", or "quarterly"
Examples
data("sample_prices_weekly")
freq <- get_data_frequency(sample_prices_weekly$Date)
Invert Signal Values for Preference Reversal
Description
Transforms signal values using (1 - value) to reverse preference direction. Useful when high values indicate something to avoid. For example, inverting volatility makes low-vol stocks appear as high signals.
Usage
invert_signal(signal_df)
Arguments
signal_df |
Data frame with Date column and signal columns |
Value
Data frame with inverted signal values
Examples
data("sample_prices_weekly")
# Prefer low volatility stocks
volatility <- calc_rolling_volatility(sample_prices_weekly, 20)
stability_signal <- invert_signal(volatility)
# Select top 10 momentum stocks first
momentum <- calc_momentum(sample_prices_weekly, 12)
selected <- filter_top_n(momentum, 10)
# Weight by inverted volatility (low vol = high weight)
weights <- weight_by_signal(selected, stability_signal)
Limit the number of positions in a selection matrix
Description
This function enforces position limits, keeping only the top N securities when more are selected.
Usage
limit_positions(
selection_df,
max_positions,
ranking_signal = NULL,
verbose = FALSE
)
Arguments
selection_df |
Binary selection matrix |
max_positions |
Maximum number of positions allowed |
ranking_signal |
DataFrame with values for ranking (if NULL, selections are random) |
verbose |
Print information about position limiting (default: FALSE) |
Value
Selection matrix with at most max_positions securities selected per period
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, 12)
# Create a selection of top 30 stocks
my_selections <- filter_top_n(momentum, 30)
# Limit to 20 positions, ranked by momentum
concentrated <- limit_positions(my_selections, 20, momentum)
# Limit to 10 positions, keeping existing selections randomly
limited <- limit_positions(my_selections, 10)
List available example scripts
Description
Shows all example scripts included with the PortfolioTesteR package. These examples demonstrate various strategy patterns and library functions.
Usage
list_examples()
Value
Character vector of example filenames
Examples
# See available examples
list_examples()
# Run a specific example
# run_example("example_momentum_basic.R")
Load Mixed Symbols Including VIX
Description
Handles loading regular stocks and VIX together, with VIX loaded separately without auto-update to avoid issues.
Usage
load_mixed_symbols(
db_path,
symbols,
start_date,
end_date,
frequency = "weekly",
use_adjusted = TRUE
)
Arguments
db_path |
Path to SQLite database |
symbols |
Character vector including regular stocks and optionally "VIX" |
start_date |
Start date for data |
end_date |
End date for data |
frequency |
Data frequency (default: "weekly") |
use_adjusted |
Use adjusted prices (default: TRUE) |
Value
data.table with all symbols properly loaded
Examples
mixed <- load_mixed_symbols(
db_path = "sp500.db",
symbols = c("AAPL", "MSFT", "VIX"),
start_date = "2020-01-01",
end_date = "2020-12-31",
frequency = "weekly"
)
head(mixed)
Adapter for User-Provided Data
Description
Simple adapter for when users provide their own data frame. Ensures proper Date formatting and sorting.
Usage
manual_adapter(data, date_col = "Date")
Arguments
data |
User-provided data frame |
date_col |
Name of date column (default: "Date") |
Value
Standardized data.table
Examples
# Use your own data frame
data("sample_prices_weekly")
my_prices <- manual_adapter(sample_prices_weekly)
Calculate Sharpe Ratio with Frequency Detection
Description
Calculate Sharpe Ratio with Frequency Detection
Usage
metric_sharpe(bt)
Arguments
bt |
Backtest result object with $returns and (optionally) $dates |
Value
Annualized Sharpe ratio
Plot Backtest Results
Description
S3 plot method for visualizing backtest performance.
Usage
## S3 method for class 'backtest_result'
plot(x, type = "performance", ...)
Arguments
x |
backtest_result object |
type |
Plot type: "performance", "drawdown", "weights", or "all" |
... |
Additional plotting parameters |
Value
NULL (creates plot)
Examples
data("sample_prices_weekly")
mom <- calc_momentum(sample_prices_weekly, lookback = 12)
sel <- filter_top_n(mom, n = 10)
W <- weight_equally(sel)
res <- run_backtest(sample_prices_weekly, W)
if (interactive()) plot(res, type = "performance")
Plot Performance Analysis Results
Description
S3 method for visualizing performance metrics. Supports multiple plot types including summary dashboard, return distributions, risk evolution, and rolling statistics.
Usage
## S3 method for class 'performance_analysis'
plot(x, type = "summary", ...)
Arguments
x |
performance_analysis object |
type |
Plot type: "summary", "returns", "risk", "drawdown" |
... |
Additional plotting parameters |
Value
NULL (creates plot)
Examples
data("sample_prices_weekly")
data("sample_prices_daily")
syms_all <- intersect(names(sample_prices_weekly)[-1], names(sample_prices_daily)[-1])
syms <- syms_all[seq_len(min(3L, length(syms_all)))]
P <- sample_prices_weekly[, c("Date", syms), with = FALSE]
D <- sample_prices_daily[, c("Date", syms), with = FALSE]
mom <- calc_momentum(P, lookback = 12)
sel <- filter_top_n(mom, n = 3)
W <- weight_equally(sel)
res <- run_backtest(P, W)
perf <- analyze_performance(res, D, benchmark_symbol = syms[1])
if (interactive()) {
plot(perf, type = "summary")
}
Print Backtest Results
Description
S3 print method for backtest results. Shows key performance metrics.
Usage
## S3 method for class 'backtest_result'
print(x, ...)
Arguments
x |
backtest_result object |
... |
Additional arguments (unused) |
Value
Invisible copy of x
Examples
data("sample_prices_weekly")
mom <- calc_momentum(sample_prices_weekly, lookback = 12)
sel <- filter_top_n(mom, n = 10)
W <- weight_equally(sel)
res <- run_backtest(sample_prices_weekly, W)
print(res)
Print a param_grid_result
Description
Print a param_grid_result
Usage
## S3 method for class 'param_grid_result'
print(x, ...)
Arguments
x |
A |
... |
Additional arguments passed to methods (ignored). |
Value
Invisibly returns x
.
Print Performance Analysis Results
Description
S3 method for printing performance analysis with key metrics including risk-adjusted returns, drawdown statistics, and benchmark comparison.
Usage
## S3 method for class 'performance_analysis'
print(x, ...)
Arguments
x |
performance_analysis object |
... |
Additional arguments (unused) |
Value
Invisible copy of x
Examples
data("sample_prices_weekly")
data("sample_prices_daily")
syms_all <- intersect(names(sample_prices_weekly)[-1], names(sample_prices_daily)[-1])
syms <- syms_all[seq_len(min(3L, length(syms_all)))]
P <- sample_prices_weekly[, c("Date", syms), with = FALSE]
D <- sample_prices_daily[, c("Date", syms), with = FALSE]
mom <- calc_momentum(P, lookback = 12)
sel <- filter_top_n(mom, n = 3)
W <- weight_equally(sel)
res <- run_backtest(P, W)
perf <- analyze_performance(res, D, benchmark_symbol = syms[1])
print(perf) # or just: perf
Print a wf_optimization_result
Description
Print a wf_optimization_result
Usage
## S3 method for class 'wf_optimization_result'
print(x, ...)
Arguments
x |
A |
... |
Additional arguments passed to methods (ignored). |
Value
Invisibly returns x
.
Rank Indicators Within Each Sector
Description
Ranks stocks within their sector for sector-neutral strategies. Enables selecting best stocks from each sector regardless of sector performance. Optimized using matrix operations within groups.
Usage
rank_within_sector(
indicator_df,
sector_mapping,
method = c("percentile", "rank", "z-score"),
min_sector_size = 3
)
Arguments
indicator_df |
Data frame with Date column and indicator values |
sector_mapping |
Data frame with |
method |
"percentile" (0-100), "rank" (1-N), or "z-score" |
min_sector_size |
Minimum stocks per sector (default: 3) |
Value
Data frame with within-sector ranks/scores
Examples
data("sample_prices_weekly")
data("sample_sp500_sectors")
momentum <- calc_momentum(sample_prices_weekly, 12)
sector_ranks <- rank_within_sector(momentum, sample_sp500_sectors)
Optimized recursive bisection for HRP
Description
Optimized recursive bisection for HRP
Optimized recursive bisection for HRP
Usage
recursive_bisection_optimized(cov_matrix, asset_order)
recursive_bisection_optimized(cov_matrix, asset_order)
Run Portfolio Backtest
Description
Main backtesting engine that simulates portfolio performance over time. Handles position tracking, transaction costs, and performance calculation.
Usage
run_backtest(
prices,
weights,
initial_capital = 1e+05,
name = "Strategy",
verbose = FALSE,
stop_loss = NULL,
stop_monitoring_prices = NULL
)
Arguments
prices |
Price data (data.frame with Date column) |
weights |
Weight matrix from weighting functions |
initial_capital |
Starting capital (default: 100000) |
name |
Strategy name for reporting |
verbose |
Print progress messages (default: FALSE) |
stop_loss |
Optional stop loss percentage as decimal |
stop_monitoring_prices |
Optional daily prices for stop monitoring |
Value
backtest_result object with performance metrics
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
weights <- weight_equally(selected)
result <- run_backtest(sample_prices_weekly, weights)
Run an Example Script
Description
Executes an example script bundled in the package inst/examples/
folder.
Usage
run_example(example_name, echo = TRUE)
Arguments
example_name |
Character scalar with the example filename (e.g. |
echo |
Logical; print code as it runs (default |
Value
Invisibly returns NULL
. Runs the example for its side effects.
Examples
# Example (requires a real file under inst/examples):
# run_example("basic.R")
Run Parameter Grid Optimization (safe + ergonomic)
Description
Run Parameter Grid Optimization (safe + ergonomic)
Usage
run_param_grid(
prices,
grid,
builder,
metric = NULL,
name_prefix = "Strategy",
verbose = FALSE,
light_mode = TRUE,
precompute_returns = TRUE,
builder_args = list(),
n_cores = 1
)
Arguments
prices |
Data frame with Date + symbol columns |
grid |
Data frame (each row = a combo) OR a named list of vectors |
builder |
Function(prices, params, ...) -> weights (Date + symbols) |
metric |
Scoring function(backtest) -> numeric. Defaults to metric_sharpe. |
name_prefix |
String prefix for backtest names |
verbose |
Logical |
light_mode |
Logical: speed-ups in backtest |
precompute_returns |
Logical: precompute log-returns once (light_mode only) |
builder_args |
List of extra args forwarded to builder (e.g., caches) |
n_cores |
Integer (kept for API compatibility; ignored here) |
Value
param_grid_result
Walk-Forward Optimization Analysis
Description
Runs rolling IS/OOS optimization, reselects params each window, and backtests OOS performance (optionally with warmup tails).
Usage
run_walk_forward(
prices,
grid,
builder,
metric = NULL,
is_periods = 52,
oos_periods = 13,
step = NULL,
warmup_periods = 0,
verbose = FALSE,
light_mode = TRUE,
precompute_all = TRUE,
builder_args = list(),
n_cores = 1
)
Arguments
prices |
Data frame with Date column and symbol columns |
grid |
Data frame OR named list; each row/combination is a parameter set |
builder |
Function(prices, params, ...) -> weights data.frame (Date + assets) |
metric |
Function(backtest_result) -> scalar score (higher is better).
Defaults to |
is_periods |
Integer, number of in-sample periods |
oos_periods |
Integer, number of out-of-sample periods |
step |
Integer, step size for rolling windows (default = oos_periods) |
warmup_periods |
Integer, warmup periods appended before each OOS |
verbose |
Logical, print progress |
light_mode |
Logical, passed to run_param_grid (kept for compatibility) |
precompute_all |
Logical, precompute indicators once and slice per window |
builder_args |
List, extra args passed to builder (e.g., indicator_cache) |
n_cores |
Integer (kept for API compatibility; ignored here) |
Value
An object of class wf_optimization_result
.
Safe ANY Operation with NA Handling
Description
Performs any() operation that returns FALSE when all values are NA instead of NA.
Usage
safe_any(x, ...)
Arguments
x |
Logical vector |
... |
Additional arguments passed to any() |
Value
Logical value (never NA)
Safe Division with NA and Zero Handling
Description
Performs division with automatic handling of NA values, zeros, and infinity. Returns 0 for division by zero and NA cases.
Usage
safe_divide(numerator, denominator)
Arguments
numerator |
Numeric vector |
denominator |
Numeric vector |
Value
Numeric vector with safe division results
Examples
safe_divide(c(10, 0, NA, 5), c(2, 0, 5, NA)) # Returns c(5, 0, 0, 0)
Sample Daily Stock Prices
Description
Daily closing prices for 20 stocks from 2017-2019. Contains the same symbols as sample_prices_weekly but at daily frequency for more granular analysis and performance calculations.
Usage
data(sample_prices_daily)
Format
A data.table with 754 rows and 21 columns:
- Date
Date object, trading date
- AAPL
Apple Inc. adjusted closing price
- AMZN
Amazon.com Inc. adjusted closing price
- BA
Boeing Co. adjusted closing price
- BAC
Bank of America Corp. adjusted closing price
- ...
Additional stock symbols with adjusted closing prices
Source
Yahoo Finance historical data, adjusted for splits and dividends
Examples
data(sample_prices_daily)
head(sample_prices_daily)
# Get date range
range(sample_prices_daily$Date)
Sample Weekly Stock Prices
Description
Weekly closing prices for 20 stocks from 2017-2019. Data includes major stocks from various sectors and is suitable for demonstrating backtesting and technical analysis functions.
Usage
data(sample_prices_weekly)
Format
A data.table with 158 rows and 21 columns:
- Date
Date object, weekly closing date (typically Friday)
- AAPL
Apple Inc. adjusted closing price
- AMZN
Amazon.com Inc. adjusted closing price
- BA
Boeing Co. adjusted closing price
- BAC
Bank of America Corp. adjusted closing price
- ...
Additional stock symbols with adjusted closing prices
Source
Yahoo Finance historical data, adjusted for splits and dividends
Examples
data(sample_prices_weekly)
head(sample_prices_weekly)
# Calculate momentum
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
S&P 500 Sector Mappings
Description
Sector classifications for the stock symbols in the sample datasets. Note: ETFs (SPY, QQQ, etc.) are not included as they represent indices or sectors themselves rather than individual companies.
Usage
data(sample_sp500_sectors)
Format
A data.table with 18 rows and 2 columns:
- Symbol
Character, stock ticker symbol
- Sector
Character, GICS sector classification
Source
S&P 500 constituent data
Examples
data(sample_sp500_sectors)
head(sample_sp500_sectors)
# Count stocks per sector
table(sample_sp500_sectors$Sector)
Load Price Data from SQL Database
Description
Loads stock price data from SQLite database with automatic frequency conversion.
Usage
sql_adapter(
db_path,
symbols,
start_date = NULL,
end_date = NULL,
auto_update = TRUE,
frequency = "daily"
)
Arguments
db_path |
Path to SQLite database file |
symbols |
Character vector of stock symbols to load |
start_date |
Start date (YYYY-MM-DD) or NULL |
end_date |
End date (YYYY-MM-DD) or NULL |
auto_update |
Auto-update database before loading (default: TRUE) |
frequency |
"daily", "weekly", or "monthly" (default: "daily") |
Value
data.table with Date column and one column per symbol
Examples
prices <- sql_adapter(
db_path = "sp500.db",
symbols = c("AAPL", "MSFT"),
start_date = "2020-01-01",
end_date = "2020-12-31",
frequency = "weekly"
)
head(prices)
Load Adjusted Price Data from SQL Database
Description
Loads adjusted stock prices (for splits/dividends) from SQLite.
Usage
sql_adapter_adjusted(
db_path,
symbols,
start_date = NULL,
end_date = NULL,
auto_update = FALSE,
frequency = "daily",
use_adjusted = TRUE
)
Arguments
db_path |
Path to SQLite database file |
symbols |
Character vector of stock symbols to load |
start_date |
Start date (YYYY-MM-DD) or NULL |
end_date |
End date (YYYY-MM-DD) or NULL |
auto_update |
Auto-update database (default: FALSE) |
frequency |
"daily", "weekly", or "monthly" (default: "daily") |
use_adjusted |
Use adjusted prices if available (default: TRUE) |
Value
data.table with Date column and adjusted prices per symbol
Examples
prices <- sql_adapter_adjusted(
db_path = "sp500.db",
symbols = c("AAPL", "MSFT"),
start_date = "2020-01-01",
end_date = "2020-12-31",
frequency = "monthly"
)
head(prices)
Standardize Data to Library Format
Description
Internal function that converts various data formats to standard wide format with Date column and symbol columns.
Usage
standardize_data_format(
data,
date_col = "date",
symbol_col = "symbol",
price_col = "price",
symbol_order = NULL
)
Arguments
data |
Input data in long or wide format |
date_col |
Name of date column |
symbol_col |
Name of symbol column (for long format) |
price_col |
Name of price column (for long format) |
symbol_order |
Optional ordering for symbols |
Value
Standardized data.table
Summary method for backtest results
Description
Summary method for backtest results
Usage
## S3 method for class 'backtest_result'
summary(object, ...)
Arguments
object |
A backtest_result object |
... |
Additional arguments (unused) |
Value
Invisible copy of the object
Switch Between Weighting Schemes
Description
Dynamically switches between two weighting schemes based on a signal. Enables tactical allocation changes.
Usage
switch_weights(weights_a, weights_b, use_b_condition, partial_blend = 1)
Arguments
weights_a |
Primary weight matrix |
weights_b |
Alternative weight matrix |
use_b_condition |
Logical vector (TRUE = use weights_b) |
partial_blend |
Blend factor 0-1 (default: 1 = full switch) |
Value
Combined weight matrix
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
weights_equal <- weight_equally(selected)
weights_signal <- weight_by_signal(selected, momentum)
# Create switching signal (example: use SPY momentum as regime indicator)
spy_momentum <- momentum$SPY
switch_signal <- as.numeric(spy_momentum > median(spy_momentum, na.rm = TRUE))
switch_signal[is.na(switch_signal)] <- 0
# Switch between strategies
final_weights <- switch_weights(weights_equal, weights_signal, switch_signal)
Update VIX data in database
Description
Update VIX data in database
Usage
update_vix_in_db(db_path, from_date = NULL)
Arguments
db_path |
Path to SQLite database |
from_date |
Start date for update (NULL = auto-detect) |
Value
Number of rows updated (invisible)
Validate Data Format for Library Functions
Description
Checks that data meets library requirements: proper Date column, at least one symbol, correct data types. Prints diagnostic info.
Usage
validate_data_format(data)
Arguments
data |
Data frame to validate |
Value
TRUE if valid, stops with error if not
Examples
data("sample_prices_weekly")
# Check if data is properly formatted
validate_data_format(sample_prices_weekly)
Validate Performance Analysis Inputs
Description
data("sample_prices_weekly") Checks that backtest result and daily prices are properly formatted with matching symbols and appropriate date coverage.
Usage
validate_performance_inputs(backtest_result, daily_prices, benchmark_symbol)
Arguments
backtest_result |
Backtest result object data("sample_prices_weekly") |
daily_prices |
Daily price data |
benchmark_symbol |
Benchmark symbol |
Value
TRUE if valid, stops with error if not
Hierarchical Risk Parity Weighting
Description
Calculates portfolio weights using Hierarchical Risk Parity (HRP) methodology. HRP combines hierarchical clustering with risk-based allocation to create diversified portfolios that don't rely on unstable correlation matrix inversions.
Usage
weight_by_hrp(
selected_df,
prices_df,
lookback_periods = 252,
cluster_method = "ward.D2",
distance_method = "euclidean",
min_periods = 60,
use_correlation = FALSE
)
Arguments
selected_df |
Binary selection matrix (data.frame with Date column) |
prices_df |
Price data for covariance calculation (typically daily) Returns are calculated internally from prices |
lookback_periods |
Number of periods for covariance estimation (default: 252) |
cluster_method |
Clustering linkage method (default: "ward.D2") |
distance_method |
Distance measure for clustering (default: "euclidean") |
min_periods |
Minimum periods required for calculation (default: 60) |
use_correlation |
If TRUE, cluster on correlation instead of covariance |
Details
The HRP algorithm:
Calculate returns from input prices
Compute covariance matrix from returns
Cluster assets based on distance matrix
Apply recursive bisection with inverse variance weighting
Results in naturally diversified portfolio without matrix inversion
The function accepts price data and calculates returns internally, matching the pattern of other library functions like calc_momentum().
Value
Weight matrix with same dates as selected_df
Examples
data("sample_prices_daily")
data("sample_prices_weekly")
# Create a selection first
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
# Using daily prices for risk calculation
weights <- weight_by_hrp(selected, sample_prices_daily, lookback_periods = 252)
# Using correlation-based clustering
weights <- weight_by_hrp(selected, sample_prices_daily, use_correlation = TRUE)
Rank-Based Portfolio Weighting
Description
Weights securities based on their rank rather than raw signal values. Useful when signal magnitudes are unreliable but ordering is meaningful.
Usage
weight_by_rank(
selected_df,
signal_df,
method = c("linear", "exponential"),
ascending = FALSE
)
Arguments
selected_df |
Binary selection matrix |
signal_df |
Signal values for ranking |
method |
Weighting method: "linear" or "exponential" |
ascending |
Sort order for ranking (default: FALSE) |
Value
Data.table with rank-based weights
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
# Linear rank weighting (best gets most)
weights <- weight_by_rank(selected, momentum, method = "linear")
# Exponential (heavy on top stocks)
weights_exp <- weight_by_rank(selected, momentum, method = "exponential")
Regime-Based Adaptive Weighting
Description
Applies different weighting methods based on market regime classification. Enables adaptive strategies that change allocation approach in different market conditions.
Usage
weight_by_regime(
selected_df,
regime,
weighting_configs,
signal_df = NULL,
vol_timeframe_data = NULL,
strategy_timeframe_data = NULL
)
Arguments
selected_df |
Binary selection matrix (1 = selected, 0 = not) |
regime |
Regime classification (integer values per period) |
weighting_configs |
List with method-specific parameters |
signal_df |
Signal values (required for signal/rank methods) |
vol_timeframe_data |
Volatility data (required for volatility method) |
strategy_timeframe_data |
Strategy timeframe alignment data |
Value
Data.table with regime-adaptive weights
Examples
data("sample_prices_weekly")
# Create selection and signals
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
# Create a simple regime (example: based on market trend)
ma20 <- calc_moving_average(sample_prices_weekly, 20)
spy_price <- sample_prices_weekly$SPY
spy_ma <- ma20$SPY
regime <- ifelse(spy_price > spy_ma, 1, 2)
# Different weights for bull/bear markets
weighting_configs <- list(
"1" = list(method = "equal"),
"2" = list(method = "signal")
)
weights <- weight_by_regime(selected, regime, weighting_configs,
signal_df = momentum)
Risk Parity Weighting Suite
Description
Collection of risk-based weighting methods for portfolio construction. Each method allocates capital based on risk characteristics rather than market capitalization or arbitrary equal weights.
Usage
weight_by_risk_parity(
selected_df,
prices_df,
method = c("inverse_vol", "equal_risk", "max_div"),
lookback_periods = 252,
min_periods = 60
)
Arguments
selected_df |
Binary selection matrix (data.frame with Date column) |
prices_df |
Price data for risk calculations (typically daily) Returns are calculated internally from prices |
method |
Optimization method for risk parity |
lookback_periods |
Number of periods for risk estimation (default: 252) |
min_periods |
Minimum periods required (default: 60) |
Details
Methods:
inverse_vol: Weight inversely to volatility (1/'). Lower volatility stocks receive higher weights. Simple but effective.
equal_risk: Equal Risk Contribution (ERC). Each position contributes equally to total portfolio risk. Uses iterative optimization.
max_div: Maximum Diversification Portfolio. Maximizes the ratio of weighted average volatility to portfolio volatility.
The function accepts price data and calculates returns internally, ensuring consistency with other library functions. Daily prices are recommended for accurate volatility estimation.
Value
Weight matrix with same dates as selected_df, rows sum to 1
Examples
data("sample_prices_daily")
data("sample_prices_weekly")
# Create a selection first
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 10)
# Simple inverse volatility weighting
weights <- weight_by_risk_parity(selected, sample_prices_daily, method = "inverse_vol")
# Equal Risk Contribution for balanced exposure
weights <- weight_by_risk_parity(selected, sample_prices_daily, method = "equal_risk")
# Maximum Diversification Portfolio
weights <- weight_by_risk_parity(selected, sample_prices_daily, method = "max_div")
Signal-Based Portfolio Weighting
Description
Weights selected securities proportionally to their signal strength. Stronger signals receive higher allocations.
Usage
weight_by_signal(selected_df, signal_df)
Arguments
selected_df |
Binary selection matrix |
signal_df |
Signal values for weighting |
Value
Data.table with signal-proportional weights
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
# Weight by momentum strength
weights <- weight_by_signal(selected, momentum)
Volatility-Based Portfolio Weighting
Description
Weights securities based on their volatility characteristics. Can prefer low-volatility (defensive) or high-volatility (aggressive) stocks.
Usage
weight_by_volatility(
selected_df,
vol_timeframe_data,
strategy_timeframe_data = NULL,
lookback_periods = 26,
low_vol_preference = TRUE,
vol_method = "std",
weighting_method = c("rank", "equal", "inverse_variance")
)
Arguments
selected_df |
Binary selection matrix (1 = selected, 0 = not) |
vol_timeframe_data |
Price data for volatility calculation (usually daily) |
strategy_timeframe_data |
Price data matching strategy frequency |
lookback_periods |
Number of periods for volatility (default: 26) |
low_vol_preference |
TRUE = lower vol gets higher weight (default: TRUE) |
vol_method |
"std", "range", "mad", or "abs_return" |
weighting_method |
"rank", "equal", or "inverse_variance" |
Value
Data.table with volatility-based weights
Examples
data("sample_prices_weekly")
data("sample_prices_daily")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
daily_vol <- calc_rolling_volatility(sample_prices_daily, lookback = 252)
aligned_vol <- align_to_timeframe(daily_vol, sample_prices_weekly$Date)
weights <- weight_by_volatility(selected, aligned_vol, low_vol_preference = TRUE)
Equal Weight Portfolio Construction
Description
Creates equal-weighted portfolio from selection matrix. The simplest and often most robust weighting scheme.
Usage
weight_equally(selected_df)
Arguments
selected_df |
Binary selection matrix (1 = selected, 0 = not) |
Value
Data.table with equal weights for selected securities
Examples
data("sample_prices_weekly")
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, 10)
weights <- weight_equally(selected)
Generate Walk-Forward Report
Description
Prints a concise summary of a wf_optimization_result
: configuration,
stitched OOS performance, and parameter stability.
Usage
wf_report(wf, digits = 4)
Arguments
wf |
A |
digits |
Integer; number of digits when printing numeric values (default 4). |
Value
Invisibly returns the optimization summary data frame.
Stitch Out-of-Sample Results (overlap-safe)
Description
Concatenates OOS backtests and safely compounds returns on overlapping dates.
Usage
wf_stitch(oos_results, initial_value = 1e+05)
Arguments
oos_results |
List of backtest_result objects, each with $portfolio_values and $dates. |
initial_value |
Numeric starting value for the stitched equity curve (default 100000). |
Value
Data frame with columns: Date
, Value
.
Download Price Data from Yahoo Finance
Description
Downloads stock price data directly from Yahoo Finance using quantmod. No database required - perfect for quick analysis and experimentation. Get started with real data in under 5 minutes.
Usage
yahoo_adapter(symbols, start_date, end_date, frequency = "daily")
Arguments
symbols |
Character vector of stock symbols |
start_date |
Start date in "YYYY-MM-DD" format |
end_date |
End date in "YYYY-MM-DD" format |
frequency |
"daily" or "weekly" (default: "daily") |
Value
Data.table with Date column and one column per symbol
Examples
# Use included sample data
data(sample_prices_weekly)
# Build a quick momentum strategy with offline data
momentum <- calc_momentum(sample_prices_weekly, lookback = 12)
selected <- filter_top_n(momentum, n = 2)
weights <- weight_equally(selected)
result <- run_backtest(sample_prices_weekly, weights, initial_capital = 100000)
# Download tech stocks (requires internet, skipped on CRAN)
if (requireNamespace("quantmod", quietly = TRUE)) {
prices <- yahoo_adapter(
symbols = c("AAPL", "MSFT", "GOOGL"),
start_date = "2023-01-01",
end_date = "2023-12-31",
frequency = "weekly"
)
momentum <- calc_momentum(prices, lookback = 12)
}