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. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -168,7 +168,23 @@ def print_signal_report(report: SignalReport, detail: bool = False):
|
||||
print(f" {Colors.MAGENTA}📰{Colors.RESET} {report.news_description}")
|
||||
if report.news_summary:
|
||||
print(f" {Colors.MAGENTA}🧠{Colors.RESET} {report.news_summary}")
|
||||
if report.panel_verdict:
|
||||
if report.panel_verdict and report.panel_verdict_source == "mean":
|
||||
base = (report.panel_context or {}).get("base_rate") or {}
|
||||
usual = base.get("win_rate")
|
||||
usual_txt = (f" (usual for this kind of setup: {usual:.0f}%)"
|
||||
if usual is not None else "")
|
||||
print(f" {Colors.CYAN}🤖{Colors.RESET} AI estimate: about a "
|
||||
f"{Colors.BOLD}{report.panel_probability:.0f}%{Colors.RESET} "
|
||||
f"chance this trade pays off{usual_txt}. "
|
||||
f"{report.panel_rationale} Still being tested.")
|
||||
for t in report.panel_takes:
|
||||
p_win = t.get("p_win")
|
||||
p_txt = f"{p_win:3.0f}%" if p_win is not None else " - "
|
||||
label = t['persona'] if len(report.panel_takes) > 1 else "reasons"
|
||||
print(f" {Colors.GRAY}{label:<11} {p_txt} "
|
||||
f"for: {t.get('reason_for') or '-'} | against: "
|
||||
f"{t.get('reason_against') or '-'}{Colors.RESET}")
|
||||
elif report.panel_verdict:
|
||||
panel_label = ("AI macro view"
|
||||
if report.panel_verdict_source == "macro" else "AI Panel")
|
||||
print(f" {Colors.CYAN}🤖{Colors.RESET} {panel_label}: "
|
||||
@@ -230,6 +246,10 @@ def report_to_dict(report: SignalReport) -> dict:
|
||||
"panel_created_at": report.panel_created_at,
|
||||
"panel_cache_status": report.panel_cache_status,
|
||||
"panel_payload_hash": report.panel_payload_hash,
|
||||
"panel_verdict_source": report.panel_verdict_source,
|
||||
"panel_prompt_version": report.panel_prompt_version,
|
||||
"panel_probability": round(report.panel_probability, 1),
|
||||
"panel_context": report.panel_context,
|
||||
"watch_line": report.watch_line,
|
||||
"bullish_reasons": report.bullish_reasons,
|
||||
"bearish_reasons": report.bearish_reasons,
|
||||
|
||||
Reference in New Issue
Block a user