Add session filter + auto-toggle, extend trade journal diagnostics

Session filter restricts trades to a UTC hour window (default 07-16,
London + NY) — opt-in via --session-filter, with --session-start /
--session-end overrides. Wired into both the backtester (cheap hour
check next to the regime gate) and live mode (downgrades signal to
NEUTRAL/F when current UTC hour is outside the window).

Auto-toggle (--auto-session-filter) tracks rolling mean pnl_pct over
the last N closed trades; when it falls below threshold, the session
filter activates, releasing once expectancy recovers. Default lookback
10 trades, threshold -0.3%.

Trade dataclass extended with diagnostic fields captured at entry:
entry_hour, entry_dow, ADX, ATR%, market_regime, volatility_regime,
mtf_agreement. These let --journal-csv exports surface loss-pattern
clusters when a window underperforms.

Validated on 2024 trend / 2023 chop / 2026 recent windows. Auto-toggle
preserves ~50% of trend edge while still cutting ~25% of recent-regime
losses — pure regime filter is still best on cumulative, so both
session flags ship default-off.
This commit is contained in:
Harwinder
2026-05-07 18:38:49 -04:00
parent fb1eb5b73f
commit 2e5d66db1b
5 changed files with 139 additions and 1 deletions
+16
View File
@@ -170,6 +170,22 @@ class BacktestConfig:
regime_filter_timeframe: Timeframe = Timeframe.H4
regime_filter_min_adx: float = 25.0
# Session gate — only trade during a specified UTC hour window.
# 2026 diagnostic backtest showed 07-15 UTC (London + NY) had
# 47% WR / +127 pips while off-hours were 0% WR / -571 pips.
session_filter: bool = False
session_start_hour: int = 7 # UTC, inclusive
session_end_hour: int = 16 # UTC, exclusive — so trades fire on 07..15
# Auto-toggle: enable session filter ONLY when recent realised trades
# show adverse expectancy (mean pnl_pct over the last N closed trades
# below threshold). Releases automatically once expectancy recovers.
# Designed so trending regimes keep all hours, while adverse/chop
# regimes auto-restrict to liquid sessions.
auto_session_filter: bool = False
auto_session_lookback_trades: int = 10
auto_session_threshold_pct: float = -0.3
# Parallelism (used by Optimizer; single-run backtest is sequential)
parallel_workers: int = field(default_factory=lambda: os.cpu_count() or 4)