feat: portfolio simulation + per-trade stats (gaps, hold time, best/worst)
Per-trade additions to the report: - Gap-through-stop fills: stops now fill at the worse of the stop or the bar's open across every exit model (target, TP, trailing, time), so a loss can exceed -1R; targets never fill better than their level. - best_r / worst_r, avg holding days, and net R per day of capital deployed on the summary buckets and the time-exit sweep. Portfolio simulation (the stats a per-setup replay cannot give): - One capital-constrained book over the qualified setups: 10k start, max 10 concurrent positions (one per ticker, best momentum first), 1% fixed-fractional risk with a 20% no-leverage notional cap, entries at the detection close, 0.1%/side costs, daily mark-to-market. - Two exit policies compared: S/R target race vs hold-to-horizon. - Equity-curve stats: final equity, total return, CAGR, max drawdown, annualized daily Sharpe, win rate, avg P&L, best/worst trade, avg hold, entries skipped on a full book, and SPY price return over the same window (benchmark history refreshed to cover the replay span). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -232,6 +232,10 @@ export interface BacktestBucket {
|
||||
// Net of transaction costs — optional so a stale cached report still renders.
|
||||
net_avg_r?: number | null;
|
||||
net_total_r?: number | null;
|
||||
best_r?: number | null;
|
||||
worst_r?: number | null;
|
||||
avg_hold_days?: number | null;
|
||||
net_r_per_day?: number | null;
|
||||
}
|
||||
|
||||
export interface BacktestCalibrationRow {
|
||||
@@ -276,6 +280,45 @@ export interface BacktestTimeExitRow {
|
||||
total_r: number | null;
|
||||
net_avg_r?: number | null;
|
||||
net_total_r?: number | null;
|
||||
best_r?: number | null;
|
||||
worst_r?: number | null;
|
||||
avg_hold_days?: number | null;
|
||||
net_r_per_day?: number | null;
|
||||
}
|
||||
|
||||
export interface BacktestPortfolioPolicy {
|
||||
policy: string;
|
||||
starting_capital: number;
|
||||
final_equity: number;
|
||||
total_return_pct: number;
|
||||
cagr_pct: number | null;
|
||||
max_drawdown_pct: number;
|
||||
sharpe: number | null;
|
||||
trades: number;
|
||||
win_rate: number | null;
|
||||
avg_trade_pnl: number | null;
|
||||
best_trade_r: number | null;
|
||||
worst_trade_r: number | null;
|
||||
best_trade_pnl: number | null;
|
||||
worst_trade_pnl: number | null;
|
||||
avg_hold_days: number | null;
|
||||
skipped_book_full: number;
|
||||
spy_return_pct: number | null;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
}
|
||||
|
||||
export interface BacktestPortfolioSim {
|
||||
params: {
|
||||
starting_capital: number;
|
||||
max_positions: number;
|
||||
risk_per_trade_pct: number;
|
||||
notional_cap_pct: number;
|
||||
cost_per_side_pct: number;
|
||||
hold_days: number;
|
||||
};
|
||||
policies: BacktestPortfolioPolicy[];
|
||||
note?: string;
|
||||
}
|
||||
|
||||
export interface BacktestGateAblationRow extends BacktestBucket {
|
||||
@@ -319,6 +362,7 @@ export interface BacktestReport {
|
||||
take_profit_sweep?: BacktestTakeProfitRow[];
|
||||
trailing_sweep?: BacktestTrailingRow[];
|
||||
time_exit_sweep?: BacktestTimeExitRow[];
|
||||
portfolio_sim?: BacktestPortfolioSim;
|
||||
calibration: BacktestCalibrationRow[];
|
||||
signal_eval?: BacktestSignalEvalRow[];
|
||||
signal_eval_note?: string;
|
||||
|
||||
Reference in New Issue
Block a user