Skip to content

synthetic_backtesting

Sampling, Validation and ML Diagnostics

AFML Chapter 13 shows that selecting PT/SL rules on a single historical path is prone to overfitting; synthetic path ensembles let us evaluate rule robustness under calibrated process dynamics.

Pt=α+ϕPt1+σϵt,ϵtN(0,1)P_t=\alpha+\phi P_{t-1}+\sigma\epsilon_t,\quad \epsilon_t\sim\mathcal N(0,1)

Pˉ=α1ϕ\bar P=\frac{\alpha}{1-\phi}

R=argmaxRΩE[πR]σ[πR]R^*=\arg\max_{R\in\Omega}\frac{\mathbb E[\pi\mid R]}{\sigma[\pi\mid R]}

use openquant::synthetic_backtesting::{run_synthetic_otr_workflow, StabilityCriteria, SyntheticBacktestConfig};
let cfg = SyntheticBacktestConfig {
initial_price: historical_prices[historical_prices.len() - 1],
n_paths: 10_000,
horizon: 128,
seed: 42,
profit_taking_grid: vec![0.5, 1.0, 1.5, 2.0, 3.0],
stop_loss_grid: vec![0.5, 1.0, 1.5, 2.0, 3.0],
max_holding_steps: 64,
annualization_factor: 1.0,
stability_criteria: StabilityCriteria::default(),
};
let out = run_synthetic_otr_workflow(&historical_prices, &cfg)?;
if out.diagnostics.no_stable_optimum {
println!("Skip OTR optimization: {}", out.diagnostics.reason);
} else {
println!("Best PT/SL: {:?}", out.best_rule);
}
  • calibrate_ou_params
  • generate_ou_paths
  • evaluate_rule_on_paths
  • search_optimal_trading_rule
  • detect_no_stable_optimum
  • run_synthetic_otr_workflow
  • Near-random-walk estimates (|phi| close to 1) often produce flat Sharpe heatmaps where any selected rule is unstable out-of-sample.
  • Calibrating to process parameters and evaluating many synthetic paths reduces single-path lucky-fit risk compared to brute-force historical optimization.