news: beginner-language summary, 4 h headline window, drop neutral headlines; --news log report

Verdict from the 3-week signal log (backtest/research/news_sentiment_value_2026-09-04.md):
news_sentiment is a trailing-24h echo of price (r +0.67 with the past day, +0.03 with
the next; most bullish 2 h after the 08-25 top, bearish 44 h later; most bearish at the
09-02 low, bullish 16 h later). Per-headline LLM labels are correct; the 12 h pool and
the averaging are what destroy the information. Both gating flags stay False.

- news_engine: _LLM_SUMMARY_SYSTEM rewritten for someone who has never traded (no
  acronyms, two worked examples); summary payload newest-first with the platform's own
  gold direction; reply cap 300 -> 400 chars.
- config: headline_max_age_seconds 43200 -> 14400; RSS items without a parsable
  pubDate are dropped (they used to be stamped "now" and never aged out).
- news_engine.get_fundamental_context drops headlines whose every relevant score is
  inside +-0.1 (_is_neutral_headline) before the per-currency mean; news_sentiment
  from this date is a mean over directional <=4 h headlines (log comparisons split here).
- static: dashboard copy for the 4 h pool; news_summary.php prompt gets the same style rule.
- analyze_signal_log: --news (under --stored-candles) prints sentiment lead/lag with
  split halves, sentiment at the window high/low with flip lags, and outcome buckets by
  direction x news x macro stance; LogRow gains news_sentiment/event_risk; _row_index shared.
- tests: 406 -> 414 (age window, undated drop, neutral filter, summary prompt/payload/cap,
  --news helpers, load_rows round-trip); RSS fixtures now carry a pubDate.
- docs: user/beginner guides, CLAUDE.md, deploy README.

Claude-Session: https://claude.ai/code/session_0169BgFtWjp1SEAa5392Q9jH
This commit is contained in:
Harwinder Sekhon
2026-09-04 15:14:58 -04:00
parent 593ddfe81f
commit a3d7594f0c
11 changed files with 795 additions and 38 deletions
+5
View File
@@ -100,6 +100,11 @@ the public page, accepted with these guards baked into the PHP — the id must
match a headline in the published news.json (arbitrary text can never reach
the LLM), each headline's summary is cached forever in `ai/` (≤1 API call per
headline, ever), and a file-based daily cap fails **closed** on I/O errors.
Since 2026-09-04 the engine publishes only headlines up to 4 h old whose
score leans one way (neutral items are dropped), so a headline leaves the
whitelist sooner: a dialog left open past that point returns `unknown_id`
("This headline has left the live feed"); summaries already cached in `ai/`
stay reachable.
Requirements: `php` + the curl extension (`php -m | grep curl`).