news corpus for a local scorer + agent panel v2 + dashboard read-only (2026-09-17); books byte-identical

Agent panel v2: personas return p_win anchored to the book base rates with a
code-computed decision context; verdict = equal-weight mean (verdict_source
"mean"); only the macro persona runs live (agent_panel.personas ["macro"]);
prompt version and exact payloads logged; offline replay harness
scripts/panel_replay.py; base-rate table agent_panel_base_rates.json
(scripts/build_panel_base_rates.py). Backtester `strategy` column now carries
the generator's own stamp (label-only; five reference books re-pinned, all
62 other columns identical).

News corpus (after evaluating the owner's ML-NEWS scikit model against
DeepSeek: golden set 39/78 vs 78/78, out-of-sample agreement 64% against a
90% self-agreement ceiling; verdict: fallback only, not a replacement):
- NewsSentiment.xau_score + archive column xau_score keep DeepSeek's gold
  score for every headline (930 of the first 1,546 DeepSeek rows had none);
  an existing newsdata.db gains the column in place on first open
- headlines naming no tracked currency are scored and archived
  (currencies_json []) but never returned to the platform
- _apply_llm_sentiment sends every new headline in its cycle, 25 per call;
  a failed call ends the cycle's sending

Dashboard publisher never writes a database: main() calls
app_config.set_db_writes_for_process(False), honoured by signal_log_enabled()
and news_archive_enabled() (owner decision: the bot is the single writer).

Test suite: the hermetic app config now points both writers at a
suite-private temp dir — the RSS fixture tests were writing fixture
headlines into the real logs/newsdata.db — with a Module 32 test pinning it.
529 tests.
This commit is contained in:
Harwinder Sekhon
2026-09-17 19:49:29 -04:00
parent 183df7832b
commit ad14ea4fed
21 changed files with 3803 additions and 259 deletions
+16 -1
View File
@@ -115,7 +115,16 @@ class SignalReport:
panel_created_at: str = ""
panel_cache_status: str = ""
panel_payload_hash: str = ""
panel_verdict_source: str = "" # "macro" / "chair" / ""
panel_verdict_source: str = "" # "mean" / "macro" / "chair" / ""
# v2 panel (2026-09-17): the mean persona probability (0-100) that
# the trade closes profitably, the prompt version that produced it,
# the exact per-persona payloads and the shared code-computed
# context — all advisory/DISPLAY-ONLY, logged for the offline replay
# harness (scripts/panel_replay.py) and the calibration scorecard.
panel_probability: float = 0.0
panel_prompt_version: str = ""
panel_payloads: Dict = field(default_factory=dict)
panel_context: Dict = field(default_factory=dict)
# Violent-move watch line (advisory/DISPLAY-ONLY). Stamped post-hoc
# by surfaces via violent_watch.attach_watch — never populated
@@ -277,6 +286,12 @@ class SignalAggregator:
dfs=dfs,
use_news=True,
)
# Live-only hand-off for the post-hoc advisory add-ons (the agent
# panel's price context reads the frames this scan analysed, so
# it sees exactly the bars the engine saw). A private attribute
# like _signal_log_rowid: not a dataclass field, never read by
# the core, absent on backtest replays by construction.
report._frames = dfs
if stale_tfs:
report.warnings.append(f"STALE DATA on {', '.join(stale_tfs)} — signal may be unreliable")