Audit fixes: cache boundary staleness, 6e session bypass, GPU engine parity
Fixes all high+medium findings from the 2026-07-16 full-codebase audit. High: - data_provider: cache now rejects snapshots missing the latest closed bar (_has_latest_closed_bar, weekend-exempt). The wall-clock TTL served mid-candle snapshots at the next boundary, so live M15/H1 scans ran one full bar behind and the bar-close session check evaluated the wrong hour. - signal_aggregator: gate 6e (SELL quality) only acts on actionable grades. It was re-grading session-blocked F reports to D, which re-opened the M5 pullback path (entry check: quality != "F") on session-blocked bars. - gpu_backtest: port the live EMA-ribbon compression/expansion logic (+10 conf on expansion) into the GPU engine. Its absence diverged composite score/conf on 7-9% of bars and flipped signals on ~0.2%. Medium: - gpu_backtest: Bollinger precompute uses the exact pandas rolling calls (cumsum E[x2]-E[x]2 lost precision at gold price levels; bb_position error up to 7.6e-3 crossed signal thresholds, worst during squeezes). - gpu_backtest: --confirm-tfs defaults to the pair factory's live confirmation map instead of a hardcoded 1h,4h. - gpu_backtest: entries re-anchor to the first RAW bar after the signal bar, so >10-sigma spike bars dropped by cleaning are no longer skipped at entry (favorable bias). - gpu_backtest: per-TF warmup pad — D1 confirms get >=210 bars at window start (62-day pad gave ~61 bars: no EMA200, unlike live). - data_provider: thread-safety locks for cache + throttle (shared provider across the bot's 4-thread pool); outlier filter keeps the snap-back bar after a spike instead of punching a two-bar hole. - telegram_bot: alert fingerprint gains a risk-relative entry bucket (materially-moved setups re-alert) and is committed only after a successful send (failed sends no longer consume the alert for 1h). - engine: disabled_indicators=["macd"] now removes the MACD pillar from scoring (histogram still computed for divergence). Verification: test_all.py 187/187 (new Module 11: 8 audit-fix regressions incl. a live-vs-GPU parity sweep with ribbon coverage); real-data parity sweep over 813 slices of 14mo XAU M15: zero divergence (pre-fix: 7-9% of bars diverged); both original bug repros no longer reproduce; cached end-to-end backtest run passes with the live confirm map. Books shift slightly vs pre-fix runs — comparability note added to CLAUDE.md; pinned tuned numbers need re-validation under the fixed backtester. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -739,9 +739,13 @@ class SignalAggregator:
|
||||
report.final_signal in (SignalStrength.SELL, SignalStrength.STRONG_SELL)
|
||||
or (report.final_signal == SignalStrength.NEUTRAL and report.final_score < 0)
|
||||
)
|
||||
# Actionable grades only: without this guard the gate would "upgrade"
|
||||
# a session-blocked F report to D, which re-opens the M5 pullback
|
||||
# path (its entry check is quality != "F").
|
||||
if (self.config.xau_strategy.enabled
|
||||
and report.display_name == "XAU/USD"
|
||||
and xau_is_sell_dir
|
||||
and report.signal_quality in ("A+", "A", "B", "C")
|
||||
and report.signal_quality not in self.config.xau_strategy.sell_min_quality):
|
||||
report.warnings.append(
|
||||
f"SELL FILTER: quality {report.signal_quality} below minimum for SELL"
|
||||
|
||||
Reference in New Issue
Block a user