strategyr is an execution-oriented R package for modular
strategy workflows. It is designed to transform already-available market
features, portfolio state, and dynamic quantitative analysis into
actionable signals, target positions, portfolio adjustments, and order
intents.
The package emphasizes path-dependent backtesting so strategy logic is evaluated under evolving account state, execution assumptions, and market conditions rather than through purely static signal research.
Compared with investlabr, which is oriented toward
exploratory research and communication, strategyr is
intended for disciplined strategy logic and timely investment decision
support.
devtools::install_github("OliverLDS/strategyr")library(data.table)
library(strategyr)
DT <- data.table(
datetime = as.POSIXct("2020-01-01", tz = "UTC") + 86400 * 0:249
)
DT[, close := 100 + cumsum(sin(seq_len(.N) / 8) + 0.15)]
DT[, open := shift(close, fill = close[1])]
DT[, high := pmax(open, close) + 1]
DT[, low := pmin(open, close) - 1]
tgt_pos <- strat_donchian_turtle_tgt_pos(
DT,
entry_n = 30L,
exit_n = 10L,
target_size = 0.95
)
eq <- backtest_rcpp(
timestamp = as.numeric(DT$datetime),
open = DT$open,
high = DT$high,
low = DT$low,
close = DT$close,
tgt_pos = tgt_pos,
pos_strat = rep(307L, nrow(DT)),
tol_pos = rep(0.05, nrow(DT)),
strat = 307L,
asset = 8001L,
ctr_step = 0.01,
lev = 1,
fee_rt = 0.0005,
rec = TRUE
)
calc_strategy_performance_summary(
eq,
tgt_pos = tgt_pos,
recorder = attr(eq, "recorder"),
fee_rt = 0.0005
)state <- list(
ctr_size = 1.0,
ctr_step = 1.0,
lev = 10.0,
last_px = 100.0,
ctr_unit = 0.0,
avg_price = NaN,
cash = 10000.0,
pos_dir = 0L
)
plan <- strat_donchian_turtle_action_plan(
DT,
state,
entry_n = 30L,
exit_n = 10L,
target_size = 0.95,
strat_id = 307L
)walk_res <- mine_strategy_walk_forward(
DT,
strategy_fun = strat_ema_triple_trend_tgt_pos,
param_grid = data.table::CJ(
fast = c(10L, 20L),
mid = c(30L, 50L),
slow = c(80L, 120L),
target_size = 0.95
)[fast < mid & mid < slow],
train_years = 1,
test_years = 0.5,
step_years = 0.5,
n_best = 2L,
min_train_rows = 100L,
min_test_rows = 50L,
warmup_days = 120L,
strat_id = 106L,
ctr_step = 0.01,
lev = 1,
fee_rt = 0.0005
)
summarize_walk_forward_results(walk_res, group_cols = c("fast", "mid", "slow"))
filter_walk_forward_results(
walk_res,
group_cols = c("fast", "mid", "slow"),
min_windows = 1L,
min_positive_return_rate = 0.5,
max_avg_score_decay = 10
)panel <- CJ(
date = as.Date("2020-01-01") + 0:9,
asset = c("AAA", "BBB", "CCC")
)
panel[, score := fifelse(asset == "AAA", 0.8, fifelse(asset == "BBB", 0.4, 0.2)) + as.numeric(date - min(date)) / 100]
panel[, open := 100 + match(asset, c("AAA", "BBB", "CCC")) * 5 + as.numeric(date - min(date))]
panel[, close := open * (1 + score / 100)]
panel[, target_weight := strat_cross_sectional_rank_allocator_tgt_pos(
panel,
date_col = "date",
asset_col = "asset",
signal_col = "score",
long_n = 2L,
short_n = 0L,
gross_exposure = 1.0
)]
portfolio_bt <- backtest_portfolio_weights(
panel,
initial_equity = 100000,
fee_rt = 0.0005
)
portfolio_bt$equity[, .(date, equity, gross_exposure, turnover, fee_paid)]bond_dt <- data.table(
par = rep(100, 5),
c_rate = rep(0.05, 5),
maturity = seq(2, 6),
freq = rep(2, 5),
ytm = c(0.045, 0.044, 0.043, 0.042, 0.041)
)
carry_tgt <- strat_bond_carry_roll_tgt_pos(
bond_dt,
long_threshold = 0,
short_threshold = -0.02,
target_size = 0.5
)
bond_state <- calc_bond_risk_state(
par = 100,
c_rate = 0.06,
maturity = 3,
freq = 2,
ytm = 0.05,
accrual_frac = 0.25
)
dv01_plan <- plan_duration_neutral_adjustment(
current_dv01 = bond_state$dv01 * 1000,
target_dv01 = 0,
hedge_dv01 = -125
)option_chain <- CJ(
date = as.Date("2020-01-01") + 0:79,
time_to_expiry = c(30, 60) / 365,
type = c("put", "call")
)
option_chain[, option_log_forward_moneyness := fifelse(type == "put", -0.1, 0.1)]
option_chain[, close := 100 + as.numeric(date - min(date)) * 0.1]
option_chain[, iv := 0.2 + fifelse(type == "put", 0.03, -0.01) + sin(seq_len(.N) / 20) / 100]
iv_tgt <- strat_iv_directional_overlay_tgt_pos(
option_chain,
trend_n = 20L,
skew_long_threshold = 0.02,
skew_short_threshold = -0.02,
overlay_mode = "confirm"
)
option_state <- calc_option_risk_state(
S = 100,
K = 100,
time_to_expiry = 30 / 365,
r = 0.04,
sigma = 0.25,
type = "call"
)
delta_plan <- plan_delta_neutral_adjustment(
current_delta = option_state$delta * 100,
target_delta = 0,
hedge_delta = -50
)strategy_public_definition("donchian_turtle")
strategy_monitor_definition("donchian_turtle")strategy_public_definition() is the canonical
public-safe source for Vox strategy descriptions and effective default
parameters. Parameter values are finite numbers or NULL;
NULL explicitly marks an unbounded setting that is disabled
by default so definitions remain JSON-safe.
strategy_monitor_definition() is the canonical public-safe
source for Strategy Monitor family and regime metadata. Current Vox
monitor ids are buy_hold, ema_cross_adx,
ema_cross_slope_confirm, rsi_revert,
vol_target, donchian_turtle,
bollinger_revert, and regime_switch.
Oliver Zhou oliver.yxzhou@gmail.com
MIT License