main
${ noResults }
4 Commits (main)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
126445ae0e |
Promote v9.5.36 PEAD champion + prune experiments to 3-tier set; ORB soft-day parity; TGTC infra
- v9.5.36 promoted: megacap reaction_min 0.02→0.03 on v9.5.20 cap=0.70 base; Full 13,244%/MDD 11.67%/Sharpe 3.579/OOT 304%; clean Pareto win - Pruned 130 experiment configs → keep 3 (v9.4.5 max-return, v9.5.36 balanced/champion, v9.5.18 cap=0.55 conservative); rebuilt index - PEAD engine probes: low_vol anomaly + breakout_52w (retained as falsification probes; not promoted) - Risk analysis: 11.67% MDD confirmed structurally HYMC (6-day giveback, not controllable); per-name cap sweep on next_open_long/reaction_close falsified (0 MDD impact) - ORB: port soft-day primary-trigger filter to live engine (6-gate parity with simulator) - TGTC trader infrastructure + advisor service (new) - ORB v46/v49 sweep configs, intraday scripts, docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
3 months ago |
|
|
02f7b9f8d4 |
Fix capital_bucket propagation in synthetic engine candidates + ER silo sweep
Bug: synthetic Candidate builders in earnings_runup.py / peer_sympathy.py /
vol_breakout_52w.py did not propagate engine_capital_bucket_id /
engine_capital_bucket_allocation_pct from StrategyEngineConfig onto the
emitted Candidate. The selector path (libs/backtest/selector.py:371-383)
correctly sets these for selector-built candidates, but the synthetic-
candidate paths used by the new engine classes silently dropped them.
Cascade: apps/backtester/run.py:_active_capital_bucket_ids_for_candidates
scans candidate.engine_capital_bucket_id; when empty, the silo allocator
(run.py:790-791) short-circuits and the engine sizes against the full
equity pool — making capital_bucket fields a no-op for the new engines.
Fix: 3-line addition to each builder mirroring selector.py convention.
108 unit tests pass across the 3 engines.
ER silo sweep result (4y midlarge-liquid-long-v1, --split all):
config trades er_tr return% mdd% sharpe er_pnl$
v7.356_baseline 390 0 +2356.28 23.55 2.69 0
phase6_shared_0.20 464 77 +2746.21 25.21 2.63 -7589
silo_05 519 89 +2343.02 22.56 2.69 215
silo_10 508 86 +2450.62 23.51 2.73 321
silo_15 516 88 +2489.91 23.48 2.74 389
silo_20 508 84 +2538.27 23.48 2.76 511
silo_25 503 77 +2566.34 23.46 2.77 466
silo_30 513 88 +2589.80 23.45 2.77 560
Phase 6 shared budget's headline +390pp gain was portfolio-luck distributed
(ER's 30 cancelled trades freed cash for other sleeves to make ~+30k pnl).
With proper silo, ER fires those trades within its dedicated bucket, sizing
correctly relative to the 5-30% pool — flipping ER engine PnL from
-$7,589 (Phase 6) to +$215..+$560 (silos).
silo_30 is the recommended variant:
- Return +2589.80% vs baseline +2356.28% (+233pp, structural not luck)
- MDD 23.45% vs baseline 23.55% (slightly better)
- Sharpe 2.77 vs baseline 2.69 (+0.08, real improvement)
- ER PnL +$560 (engine actually contributing)
- Higher silos (40%+) likely starve PEAD; 30% appears near optimal.
Per-split validation of silo_30 NOT yet run — flagged for follow-up
before any live deployment.
Files:
- libs/backtest/earnings_runup.py:494-499 (3-line fix)
- libs/backtest/peer_sympathy.py:771-776 (3-line fix)
- libs/backtest/vol_breakout_52w.py:654-659 (3-line fix)
- configs/experiments/return_max_long_v7.356_plus_er_silo_{05,10,15,20,25,30}.json
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
3 months ago |
|
|
465e248cb4 |
Wire pct-trailing end-to-end for EarningsRunup; tune v2 risk profile
Fix EarningsRunup trailing config that was previously captured in
Candidate.features only. Add activation-gated pct trailing to
update_trailing_stop with entry-relative giveback semantics
("lock in peak − giveback% of entry"). Plumb through
Candidate → ExecutionConfig → simulator. Default None preserves
legacy pct_X behavior — no impact on engines that don't opt in.
Add earnings_runup_poc_v2_tuned config: per_trade_risk_pct 0.65→0.30,
max_positions 30→8, max_positions_per_sector 30→4, macro_vix_max=30,
trailing_warmup_days 7→0 (activation gate replaces warmup).
v2 backtest (4y, 121 trades) vs v1 baseline (119 trades):
Total return: +37.27% → +254.69%
Max drawdown: 53.23% → 23.97%
SQS: 45.2 → 69.7
Robustness: 50.1 → 100.0
Risk score: 23.5 → 35.0
STOP r-mult: −0.41 → +0.65 (trailing-locked winners)
Promotion thresholds met: MDD < 25%, return preserved, SQS > 55.
Recommend integration as PEAD sleeve adjunct (orthogonal entry timing:
pre-print attention runup vs post-print drift) rather than standalone.
7 new pct-trailing tests: activation gate, ratchet, no-ratchet-down,
reversal-stop, legacy compat, end-to-end engine wiring. 28 passed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
3 months ago |
|
|
956cc78f1b |
Add 3 candidate engine classes beyond PEAD: EarningsRunup, PeerSympathy, VolBreakout52w
Adds three new synthetic-Candidate emitter engines parallel to the existing leader_follower scheduler hook, plus look-ahead defenses (LookaheadViolationError + per-engine assertions). Each engine is covered by a standalone PoC config (no PEAD/parking/idle alpha) for isolation backtests against the midlarge or broad snapshot. Engines: EarningsRunup (libs/backtest/earnings_runup.py) - Trigger: days_to_earnings ∈ [3,7] AND attention_zscore_20d ≥ 1.5 AND dollar_volume_20d_zscore ≥ 1.0 (all evaluated at T-1 close) - Entry: T+1 next_open. Exit: -4% / +8% / max_holding_days = days_to_earnings - buffer (forced flat by close before announcement) - PIT calendar: PointInTimeEarningsCalendar adapter for backtest; oracle_surprise_prefetch fallback when parquet calendar absent - PoC verdict (configs/experiments/earnings_runup_poc_v1.json): 119 trades over 1051 days, +37.27% total return, 44.46% MDD, SQS 45.2 (profitability=55.5, risk=23.5, robustness=50.1). VIABLE BUT NEEDS WORK — signal exists; standalone risk profile too aggressive for v7.356 baseline (8.8% MDD on v7.364). Path forward: per_trade_risk reduction, VIX gate, position cap, or integrate as PEAD sleeve adjunct (not as standalone replacement). PeerSympathy (libs/backtest/peer_sympathy.py) - Trigger: leader passes PEAD filter (earnings_release / guidance_update / material_contract) AND leader reaction_close ≥ +5% AND peer 60d correlation ≥ 0.55 over [T-65, T-5]. Top-2 peers by correlation from leader_follower_extra_peer_symbols_by_sector + sector ETF holdings. - Entry: T+1 next_open on peer. Exit: -3.5% / +6% / max_holding=3 / peer-earnings blackout - PoC verdict (configs/experiments/peer_sympathy_poc_v1.json): 256 trades over 1051 days, -52.92% total return, 54.47% MDD, SQS 19.6 (profitability=0.0, risk=5.4, robustness=100.0). DEAD. The leader's catalyst is already absorbed by T+1 next_open — peers gap up overnight before entry. robustness=100 confirms the negative result is not noise. Salvage paths (not implemented): reaction_close entry, raised-guidance-only restriction. - Note: initial run_id was 0 trades due to a select_candidates filter mismatch (engine.event_types=['peer_sympathy'] dropping real event_type='earnings_release' rows). The runner adapter was patched to bypass strategy_engine filtering for leader selection; the manual peer_sympathy_leader_event_types filter does the gating. VolBreakout52w (libs/backtest/vol_breakout_52w.py) - Trigger: close_T-1 > max(high[T-252:T-2]) AND volume_T-1 ≥ 2 × median_volume_20d_T-2 AND ATR_14_T-1/close ∈ [0.015, 0.06]. Entry T next_open, exit -3% / +5% / max_holding=2 / MOC. - Honest, look-ahead-safe descendant of the retired topgainer v1-v54 family. Five layers of strict-before assertions guard the bar provider, candidate construction, trigger evaluation, and feature timestamps. A leaky-provider proof-by-contradiction test demonstrates the categorical catch. - PoC verdict (configs/experiments/vol_breakout_52w_poc_v1.json, broad-liquid universe): 1,332 trades, -87.28% total return, 88.74% MDD, SQS 24.4 (profitability=0.0, robustness=100.0). DEAD AND HONEST. This is the most important finding of the three PoCs: the topgainer v1-v54 lineage's headline returns (+267% Sharpe 13.73 in best variants) were 100% lookahead bug. With the bug removed, the 52w-high + volume + ATR signal has no real alpha — the lookahead-corrected -4.3% from prior memory is confirmed and amplified to -87% on a fuller universe and longer horizon. Future "revive topgainer" proposals can cite this run (bt_return_max_long_v1_broad-liquid_20260509042903892342_3bb473d9) as definitive falsification. - Pre-open gap guard inactive (no premarket data in broad snapshot). skip_if_no_gap_data=true; the +4% gap-fade guard would not move the result given the magnitude. Shared infrastructure additions: - libs/backtest/domain.py: LookaheadViolationError class + StrategyEngineConfig fields (11 EarningsRunup + 11 PeerSympathy + 13 VolBreakout52w = 35 new fields) - apps/backtester/run.py: _BacktestAttentionZscoreAdapter, _RunnerPeerResolver, _schedule_earnings_runup_candidates, _schedule_peer_sympathy_candidates, _schedule_vol_breakout_52w_candidates wired into the daily scheduler block. PeerSympathy adapter bypasses strategy_engine filtering on leader selection (manual filter handles gating). Tests: 21 (EarningsRunup) + 27 (PeerSympathy) + 38 (VolBreakout52w) = 86 new unit tests, all passing. Broader unit suite: 1392 passed, 2 pre-existing failures unrelated. Net engine state: EarningsRunup is the only viable new engine class. PeerSympathy and VolBreakout52w are kept in-tree as falsification evidence, not as production engines. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
3 months ago |