Daily-trend veto on M15 + lot-size / already-open lines (campaign 2026-09-30), and the 2026-10-01 whole-codebase bug review

Two bodies of work that touch the same files, so one commit.

Direction and setup-size campaign (2026-09-30 → 10-01, owner's RISK-FIRST rule,
written before the runs):
- SIGNAL: M15 daily-trend veto (factory override 7, xau_strategy.daily_trend_veto
  "both"). A finished setup against a clear daily trend (closed D1 bars, Sunday
  stubs dropped; close vs its 50-bar EMA AND vs the close 60 kept days earlier)
  is removed as the last step of the core. One definition
  (signal_aggregator.daily_trend_series) for live, the bar replay and the twin's
  host side; D1 is a required frame of the M15 scan; mirrored in
  cuda_signal_kernels.py K2. W3 824 / +205.12R / PF 1.73 / max DD 12.4R vs
  1105 / +195.79R / 1.49 / 20.9R; 2019 → 2026 1473 / +223.33R / 1.42 / 41.5R vs
  2091 / +192.53R / 1.24 / 64.8R; unseen holdout −4.62R vs −6.63R.
- FAILED, not shipped: the veto on M5 (W3 drawdown 10.1R → 15.2R) and on H1
  (−9.7R), buy-only and sell-only on M15, the wide-stop cap
  (xau_strategy.wide_stop_cap_atr stays 0.0, a research knob).
- New M15 pins: W2 dfc647ee…, OOS e87b6de1…, W3 ad3b0dbd…. M5 / H1 / H4 pins
  unchanged. --set xau_strategy.daily_trend_veto=off reproduces the previous M15
  pins byte for byte. Twin and reference script MD5-equal on every window;
  recorder and feature-export parity re-proved; base-rate table rebuilt.
- DISPLAY (books byte-identical): exposure.py — the lot size for
  trade_size.risk_per_trade (new config.json block, off by default, private to
  the owner) and the count of alerted same-direction plans still open
  (signals.alerted_at, read-only open_alerted_setups); the daily trend in words
  on Telegram, the CLI and the dashboard; signals.daily_trend logged.
- providers/oanda: a date window with no bars is an empty page, not an error
  (a D1 pad starting on a Saturday could not be fetched).
- Reports only, nothing shipped: seven context screens (no state nominated) and
  eight outside data sources (none adds a forecast to gold's own daily trend).
- Independent verification (report section 5.13): every figure reproduced on
  both scripts, scoring identical to the previous commit on all four
  timeframes, no look-ahead. Caveats recorded there: this is a risk filter, not
  a more accurate direction call; nine tenths of the 2019 → 2026 gain is 2022;
  the neighbour clause is thin (a simple 100-day average misses the R line by
  1.2R); "never adds a trade" is an observation, not a guarantee.

Bug review of the whole codebase (2026-10-01). Signal path clean. 17 defects
elsewhere, plus 4 found by an independent review of the fixes; all fixed, each
with a test; no trade book changed:
- telegram_bot: one _deliver_alert for the candle scan and the level break. The
  row is stamped alerted_at BEFORE the send, on a one-worker alert-db pool, and
  un-stamped when no chat received it or the task is cancelled mid-stamp, so
  two alerts at one candle close count each other and no SQLite write runs on
  the event loop. The 5-bar cooldown counts bars of the scan's own frame
  (== gpu_backtest._apply_cooldown; clock time released the 22:00 UTC bar after
  the settlement pause) and is restored from signals.db at start-up. The
  lot-size line goes to the owner's own chat only (a group the owner ran
  /autoscan in used to receive it). /status gains a news-model line and escapes
  failure details.
- signal_log: mark_alerted returns the stamp it wrote; unmark_alerted;
  last_alerted_bars (read-only).
- advisory_outcome: candle continuity is judged bar by bar inside the walk; a
  hole after a trade's exit no longer voids it. The stored-candle replay
  resolves 108 of 111 logged setups instead of 99, all equal to the live
  resolver's R.
- providers/oanda: an empty date window is accepted only when it is 5 days or
  shorter and no malformed candle was skipped; a longer one is retried, then
  refused, instead of being cached as history with a hole.
- news_engine: blank RSS titles skipped; one unreadable headline no longer
  costs the local model its whole batch (checked on the real bundle); model
  health recorded; no DeepSeek audit call in a process that does not archive;
  event-direction cache keyed per release; peek_week_events never fetches.
- llm_client: chat_json never raises and never logs the API key (requests
  quotes the Authorization value in InvalidHeader; error bodies are redacted).
- signal_aggregator: the scan's news block is guarded; the replay path
  (use_news=False) assigns exactly the values it did before.
- agent_panel: PANEL_PROMPT_VERSION v2.2 — same prompt text, corrected input
  (event timing over the cached calendar week, headlines newest first).
  scripts/panel_replay.py replays the logged payload per persona;
  scripts/label_scan_outcomes.py counts with an ISO cutoff.
- test_all.py: no ALTER TABLE … DROP COLUMN (the live box has SQLite 3.34);
  tests that write Parquet print a notice and return without pyarrow.

Verification after the last code change: suite 632 passed, 0 failed (also with
both Parquet engines blocked and FB2_BACKEND=cpu, the live box's view); the
five reference MD5s reproduce on both backtesters, 0 cache fallbacks; Module 37
green; static Python 3.9 / SQLite 3.34 check clean on every touched file.

Evidence: backtest/research/daily_trend_campaign_2026-09-30.md,
context_screens_2026-10.md, new_inputs_2026-10.md; CLAUDE.md sections 2, 4, 6,
8, 9, 10 and 11; pair_signals/xauusd.py docstring (M15 override 7).
This commit is contained in:
Harwinder Sekhon
2026-10-01 10:28:28 -04:00
parent 42025da0b0
commit 2cc5915b00
31 changed files with 6021 additions and 286 deletions
+40 -33
View File
@@ -35,42 +35,48 @@
<body>
<h1>ForexBot2 — User Guide</h1>
<div class="subtitle">How to read, act on, and survive the signals &nbsp;·&nbsp; July 2026</div>
<div class="subtitle">How to read, act on, and survive the signals &nbsp;·&nbsp; updated October 2026</div>
<h2>1 · What the bot does</h2>
<p>ForexBot2 analyzes <b>gold (XAU/USD)</b> around the clock on several chart timeframes at once. On every candle close it scores nine technical indicators (trend, momentum, volatility, divergences, candlestick patterns), adapts the weighting to the current market regime (trending / ranging / transitioning), checks that higher timeframes agree, adjusts for news and economic-calendar events, and — only when everything lines up — sends a <b>signal with a complete trade plan</b> to Telegram: direction, entry, stop loss, target, and a trailing-stop management plan.</p>
<p>Most of the time it sends nothing. Silence means no edge was found; that is the bot working correctly, not a malfunction.</p>
<h2>2 · Anatomy of a signal</h2>
<div class="signal-box">🔍 XAU/USD Signal Analysis (M15)
🕐 2026-07-10 14:00 UTC
💰 Close: 4,132.50
📊 Regime: Trending Up | Vol: normal
━━━━━━━━━━━━━━━━━━━━
🟢 BUY 🅰 A | Score: +38.2 | 64% conf
✅ MTF aligned
📈 MTF: M5 ✅ H1 ✅
📋 Indicators … (9 rows)
⚠️ EXTREME volatility — wider stops needed
━━━━━━━━━━━━━━━━━━━━
<div class="signal-box">🟢 Grade A · STRONG BUY · XAU/USD · 15min 🥇
🕐 2026-09-04 08:00 UTC · 💰 4483.41
📐 Direction: strong buy · Reliability: high · timeframes agree
📊 Regime: Transitioning · Vol: high
🧭 Daily trend: rising — this buy goes with it
STRONG BUY — High-quality setup, consider entry
🚀 TRADE SETUP
📈 Direction: BUY
▶ Entry: 4,132.50
🛑 SL: 4,103.10 ($29.40 / 294 pips = 1R)
▶ Entry 4483.41
🛑 SL 4468.92 ($14.49 / 145p = 1R)
📏 Size: 0.06 lots risks $86.94 at the stop
(your limit $100.00 per trade) ← owner's chats only
🧱 Already open: 2 buy plans alerted earlier (2 on M15)
— taking this one adds to the same position
🔄 Exit rule (tested): once price reaches
4,150.14 (+0.6R), trail the SL $22.05
4493.55 (+0.7R), trail the SL $10.87
behind the best price, moving it at
candle close only. Otherwise the SL is the exit.
🎯 TP1 guide 4,161.90 ($29.40 / 294 pips = 1.0R)
🎯 TP2 guide 4,176.60 (1.5R)
🎯 TP1 guide 4497.90 ($14.49 / 145p = 1.0R)
🎯 TP2 guide 4505.15 (1.5R)
⚖️ Planned TP1 RR 1:1.0 (guide only — the trail is the exit)
📚 Book (this setup class): 312 trades, 58% winners, avg +0.19R per trade</div>
📚 Book (this setup class): 58 trades, 62% winners, avg +0.21R per trade
📈 Other timeframes: 15min: STRONG BUY +46.5 | 5min: BUY +22.8 | 1h: NEUTRAL +14.2
📋 EMA⇈ RSI→ BB↓ ADX→ MACD⇈ ROC→ KC⇈</div>
<table>
<tr><th style="width:28%">Field</th><th>What it means</th></tr>
<tr><td><b>Signal + grade</b></td><td>Direction (BUY / SELL / STRONG_*) plus a quality grade <b>A+ → F</b>. A trade setup is only attached at grade C or better. Higher grades = more indicator agreement and cleaner regime.</td></tr>
<tr><td><b>Direction / reliability line</b></td><td>Since 2026-09-27 the alert prints the two raw numbers in words. <i>Direction</i> is the regime-weighted composite of all nine indicators: <b>very strong</b> (|score| ≥ 40), <b>strong</b> (≥ 33), <b>clear</b> (≥ 25), <b>weak</b> (≥ 15) or <b>no clear direction</b>, with buy or sell from its sign. <i>Reliability</i> is the confidence after the penalties: <b>high</b> (≥ 65), <b>good</b> (≥ 55), <b>fair</b> (≥ 45) or <b>low</b>. The cut-offs are the grade table's own, so the words never disagree with the grade. The numbers themselves remain in <code>--json</code>, <code>--detail</code> and the dashboard meters.</td></tr>
<tr><td><b>MTF aligned</b></td><td>The two confirmation timeframes agree with the trade direction. Signals without alignment are filtered out on M5.</td></tr>
<tr><td><b>Timeframes agree</b></td><td>The two confirmation timeframes agree with the trade direction. Signals without alignment are filtered out on M5.</td></tr>
<tr><td><b>Daily trend 🧭</b></td><td>The direction of the daily chart, from closed daily candles only: <b>rising</b> when the last daily close is above its 50-day average <i>and</i> above the close 60 trading days earlier, <b>falling</b> when it is below both, otherwise <b>no clear direction</b>. The line also says whether the plan goes with it or against it. <b>On M15 a plan against a clear daily trend is not sent at all</b> (since 2026-09-30): in the three-year test those plans earned nothing after costs, and dropping them cut the worst losing run from 20.9R to 12.4R while the total rose from +195.8R to +205.1R; over 2019–2026 the worst run fell from 64.8R to 41.5R. On M5, H1 and H4 the same rule was tested and did not pass, so there the line is context only — a plan "against" the daily trend is still a valid signal on those timeframes.</td></tr>
<tr><td><b>Size 📏</b></td><td>How many lots keep the loss at the printed stop inside the risk limit set in <code>config.json</code> (<code>trade_size.risk_per_trade</code>, in US dollars; 1 lot = 100 ounces unless <code>contract_size</code> says otherwise, and the lot step is 0.01 unless <code>lot_step</code> says otherwise). The size is rounded <b>down</b> to the broker's lot step, so the money at risk is at or under the limit, never over. When even the smallest lot would break the limit the line says so and gives the amount; skip that trade or accept the larger risk knowingly. The line appears only when the limit is set, and only in the owner's own chat with the bot and on the command line: the channel, any group the bot posts in and the public dashboard do not show it unless <code>trade_size.telegram_channel</code> / <code>trade_size.dashboard</code> are switched on.</td></tr>
<tr><td><b>Already open 🧱</b></td><td>How many plans in the <i>same direction</i> the bot alerted earlier are still open in its own outcome tracking (stop not hit, trail not closed), and on which timeframes. Taking every alert stacks positions on one move of gold: in the three-year M5 + M15 test two entries in three already had a same-direction plan open and one in four had three or more. Those stacked entries were not worse trades, so the line is not a reason to skip; it is a reminder that the total at risk is the sum of every open plan, not the risk of this one alert. The count comes from the bot's model of the plans it sent, not from your broker account. Alerts sent at the same candle close are counted too: when the 5-minute and the 15-minute alert go out together, the second one already shows the first.</td></tr>
<tr><td><b>Warnings ⚠️</b></td><td>Context, not veto. Backtesting shows warned trades perform about the same — strong momentum often triggers warnings.</td></tr>
<tr><td><b>Violent-move watch 🌪</b></td><td>An occasional extra line saying the next hour looks unusually likely to produce a very large candle — because a high-impact US release is due (or just landed), because the clock is in a historically wild slot, or because price is stretched outside its bands. It is a heads-up about <i>volatility</i>, not a direction call, and it <b>never</b> changes the signal, the grade or the trade setup — the same alert would be sent without it. Do not close or tighten an open trade because of it: every such protective action was tested over three years and lost money. Your stop is the protection.</td></tr>
<tr><td><b>AI check 🤖</b></td><td>An advisory block written for a new trader, such as <i>"AI check: the odds look worse than usual. New data just came out against this buy. Chance it pays off: about 45 in 100 (usual for this kind of setup: 60 in 100). For: Before the news, the price was climbing. Against: Fresh data just came out against gold. This check is an experiment. Do not trade on it alone."</i> The first sentence compares the estimate with the usual odds for this kind of setup (8 points either way counts as a difference); there is no verdict word and no confidence percentage. One AI reviewer (the news reader) receives the recent headlines together with facts computed by code — how far the move has already run, whether a very large candle just printed, how the stop and target compare with the usual, how trades of this exact kind fared in the two-year test, and whether major scheduled news lands before the trade would normally finish — and gives a probability that the trade ends in profit plus one reason for and one against. (Three further reviewers, chart, risk and sceptic, were switched off on 2026-09-17: in two evaluations they added nothing beyond the base rate and mostly voted the same way on every setup.) It is <b>not</b> a recommendation and it <b>never</b> changes the signal, the grade or the setup. Until about 300 of these estimates have been graded against real outcomes, treat it as context, not as a filter: the earlier AGREE/OPPOSE version of this line opposed target-reaching trades as often as it agreed.</td></tr>
@@ -78,33 +84,34 @@
<tr><td><b>SL / TP1 guide / planned RR</b></td><td>Stop loss sits behind the nearest swing level with an ATR buffer (grade A+/A setups use a 2 × ATR stop). <b>1R</b> = the entry-to-SL distance = the amount you risk. TP1 is a <i>guide</i> (the nearest opposing level or a multiple of ATR, never printed closer than 1R since 2026-09-26); the "planned TP1 RR" is TP1 ÷ 1R and is always at least 1:1. It is <b>not</b> the expected payoff: the tested exit is the trail, and the validated books earn their profit from trailed runners (M5 average win about +1.0R against an average loss of −0.76R; M15 +0.87R against −0.93R).</td></tr>
<tr><td><b>Exit rule 🔄</b></td><td>The real, backtested exit. Once price moves the stated R in your favor (0.6R on M5, 0.7R on M15), move the stop to trail the stated $ distance behind the best price and update it at each candle close only. Until then the original SL is the exit. <b>TP1 is advisory — let winners run.</b></td></tr>
<tr><td><b>Book line 📚</b></td><td>What this class of setup (timeframe, setup type, grade, direction) actually did in the validated two-year backtests: number of trades, share of winners and average R per trade. When the exact class has fewer than 30 trades the line falls back to all setups of that direction on the timeframe, then to the whole timeframe.</td></tr>
<tr><td><b>One alert per move</b></td><td>After an alert, the bot sends no new alert on that timeframe for the next 5 candles (25 min on M5, 75 min on M15), the same entry cooldown the backtester applies. Consecutive-bar re-entries into the same move were the largest live-only loss in September 2026.</td></tr>
<tr><td><b>One alert per move</b></td><td>After an alert, the bot sends no new alert on that timeframe for the next 5 candles (25 min on M5, 75 min on M15), the same entry cooldown the backtester applies. Consecutive-bar re-entries into the same move were the largest live-only loss in September 2026. The five candles are candles that actually traded: the daily one-hour pause and the weekend do not use them up, so the first candle after the pause is still held if fewer than five have printed since the alert. The bot also remembers its last alert across a restart.</td></tr>
</table>
<h2>3 · Acting on a signal — step by step</h2>
<ol>
<li><b>Size the position first.</b> Decide your risk per trade — <b>0.5–1% of account, never more</b>. Position size = (account × risk%) ÷ stop distance in $. The stop distance varies per signal, so the size changes every trade; the dollar risk must not.</li>
<li><b>Size the position first.</b> Decide your risk per trade — <b>0.5–1% of account, never more</b>. Position size = (account × risk%) ÷ stop distance in $. The stop distance varies per signal, so the size changes every trade; the dollar risk must not. With <code>trade_size.risk_per_trade</code> set in <code>config.json</code> the alert does this sum for you (the 📏 line). If the 🧱 line shows plans already open in the same direction, the new trade adds to them: keep the <i>total</i> at risk across all open plans inside what you can afford on one move.</li>
<li><b>Enter promptly at market.</b> All backtested results assume entry at the open of the candle after the signal. On M5, minutes matter (see §4). If you are very late — price already moved a large part of the way to the arm level — skip the trade. There is always another signal.</li>
<li><b>Place the stop loss immediately</b> at the given SL. No mental stops — gold gaps and spikes.</li>
<li><b>Manage with the trail, not TP1.</b> When price reaches the arm level printed in the message, start trailing the stop the stated $ distance behind the best price, tightening only at candle close. This is what produced the backtested results; taking fixed TP1 profits gives most of the edge away.</li>
<li><b>One signal, one trade.</b> The M5, M15 and H1 books confirm off each other and are usually long or short gold at the same time. Taking the same move on multiple timeframes multiplies risk, not diversification. Pick your timeframe (§4) and ignore the others.</li>
<li><b>One signal, one trade.</b> The M5, M15 and H1 books confirm off each other and are usually long or short gold at the same time. Taking the same move on multiple timeframes multiplies risk, not diversification. Pick your timeframe (§4) and ignore the others. The 🧱 "already open" line tells you when an alert would add to plans that are still running.</li>
</ol>
<h2>4 · Choosing your timeframe</h2>
<p>Twelve-month Oanda-candle backtest (Aug 2025 – Aug 2026, $0.65 round-trip cost, entry at next candle open):</p>
<p>Twelve-month Oanda-candle backtest with the rules as they run today (Aug 2025 – Aug 2026, $0.65 round-trip cost, entry at next candle open; regenerated 2026-10-01):</p>
<table>
<tr><th></th><th>M5</th><th>M15</th><th>H1</th></tr>
<tr><td>Trades / week</td><td>~11.3</td><td>~7.6</td><td>~2.7</td></tr>
<tr><td>Total result (12 mo)</td><td>+106.8R</td><td>+73.9R</td><td>+24.0R</td></tr>
<tr><td>Win rate / profit factor</td><td>52.9% / 1.51</td><td>62.2% / 1.53</td><td>60.9% / 1.55</td></tr>
<tr><td>Typical (median) hold</td><td>2.4 h</td><td>7 h</td><td>15.5 h</td></tr>
<tr><td>90% of trades close within</td><td>10.5 h</td><td>29.8 h</td><td>3.2 days</td></tr>
<tr><td>Typical stop distance</td><td>~$21</td><td>~$32</td><td>~$52</td></tr>
<tr><td>Worst drawdown</td><td>10.7R</td><td>10.8R</td><td>8.0R</td></tr>
<tr><td>Trades / week</td><td>~10.7</td><td>~5.1</td><td>~1.7</td></tr>
<tr><td>Total result (12 mo)</td><td>+108.8R</td><td>+92.3R</td><td>+22.2R</td></tr>
<tr><td>Win rate / profit factor</td><td>53.6% / 1.54</td><td>68.0% / 2.12</td><td>62.6% / 1.79</td></tr>
<tr><td>Typical (median) hold</td><td>2.5 h</td><td>7.8 h</td><td>21 h</td></tr>
<tr><td>90% of trades close within</td><td>11.2 h</td><td>29.4 h</td><td>3.2 days</td></tr>
<tr><td>Typical stop distance</td><td>~$21</td><td>~$32</td><td>~$48</td></tr>
<tr><td>Worst drawdown</td><td>10.1R</td><td>8.3R</td><td>4.1R</td></tr>
</table>
<p class="small">This was a strongly rising year for gold until March 2026 and a falling, choppy one after. Four fifths of the M5 total (+89.6R of +108.8R) came in January–March 2026; M15 earned in every quarter but only +2.3R since July. Over 2019–2026 the M15 rules made +223R with one losing year (2021, −27R) and two years close to flat (2022 and 2023); the M5 rules took few trades and made nothing before 2025. Judge the next twelve months by the long record, not by this table.</p>
<ul>
<li><b>M5 — intraday, execution-critical.</b> Highest total edge, but stops are tight: a couple of dollars of slippage or a late entry eats a meaningful share of every trade. Suitable only if you can act within a minute or two of the alert (or automate). Trades open and close within a session; you sleep flat. SELL signals are held back while the market regime reads "transitioning" — a validated filter, not a bug if you notice fewer shorts there.</li>
<li><b>M15 — the middle path.</b> Same frequency as M5, wider stops, up to 15 minutes to act. About half your trades will still be open overnight. Since 2026-09-09 the M15 scoring gives its RSI reading half the weight it used to (RSI mostly voted against the trend on this timeframe), so expect roughly 9 signals a week instead of 7–8; in the two-year test (Sep 2024 – Sep 2026) that change lifted M15 from +117.6R to +146.1R with the same win rate and a slightly better profit factor, and it also improved the separate out-of-sample period. The M15 column above predates it.</li>
<li><b>M15 — the middle path.</b> Same frequency as M5, wider stops, up to 15 minutes to act. About half your trades will still be open overnight. Since 2026-09-09 the M15 scoring gives its RSI reading half the weight it used to (RSI mostly voted against the trend on this timeframe), so expect roughly 9 signals a week instead of 7–8; in the two-year test (Sep 2024 – Sep 2026) that change lifted M15 from +117.6R to +146.1R with the same win rate and a slightly better profit factor, and it also improved the separate out-of-sample period. Since 2026-09-26 grade-A shorts are blocked on M15, and since 2026-09-30 any M15 plan against a clear daily trend is dropped (the 🧭 line, §2). Together these leave about 5 signals a week. The daily-trend rule is a trade of profit for safety: it removes about a quarter of the trades, the ones that earned nothing after costs, and shortens the losing runs; in a stretch where gold only rises it gives up a little (Sep 2024 – Sep 2025: +61.8R instead of +70.1R).</li>
<li><b>H1 — swing trading around a normal life.</b> Best quality per trade and very forgiving of slow manual execution (you have up to an hour). The costs: positions held for days, through news and overnight sessions, and a <b>lumpy</b> equity curve — one quarter of the test year was negative and most of the profit came in a single quarter. Judge it on quarters, not weeks. H1 no longer issues SELL signals at all (blocked since 2026-09-03) — it is BUY-only on this timeframe.</li>
</ul>
<div class="callout"><b>If you trade manually from the Telegram alerts, H1 (or M15) is the honest choice.</b> M5's backtested edge assumes near-instant fills that a human copying signals rarely achieves.</div>
@@ -113,7 +120,7 @@
<ul>
<li><b>You will lose roughly 38–47% of trades.</b> A 53–62% win rate means losing streaks of 5+ are routine over a year. The system's edge is the average across hundreds of trades, not any single one.</li>
<li><b>Stops hit fast, winners take time.</b> Losing trades die in roughly half the time winners take. An early stop-out is the system doing its job.</li>
<li><b>Drawdowns of ~10R are normal.</b> At 1% risk per trade, expect to be ~10% down from a peak at some point in a normal year. This is why risking more than 1% per trade is how accounts die.</li>
<li><b>Drawdowns of ~10R are normal, and worse has happened.</b> At 1% risk per trade, expect to be ~10% down from a peak at some point in a normal year. Over 2019–2026 the M15 rules as they run today had one losing run of 41.5R that took from late 2020 to early 2022 to bottom out, while gold drifted sideways and down. This is why risking more than 1% per trade is how accounts die.</li>
<li><b>Backtest ≠ live.</b> Results above charge real spreads and realistic fills, but cannot model your personal latency, broker slippage, or requotes. Assume live results will be somewhat worse — especially on M5.</li>
<li><b>Quiet periods are normal.</b> Filters block bad hours, bad regimes and misaligned timeframes. Days can pass without a signal.</li>
</ul>
@@ -136,7 +143,7 @@
<tr><td><code>/start</code></td><td>Show the button menu (manual scans per timeframe, Scan All TFs).</td></tr>
<tr><td><code>/scan</code></td><td>Run an immediate analysis of the primary timeframe.</td></tr>
<tr><td><code>/autoscan</code></td><td>Toggle automatic scanning (M5 / M15 / H1 / H4 at each candle close).</td></tr>
<tr><td><code>/status</code></td><td>Uptime, auto-scan state, WebSocket price-monitor state.</td></tr>
<tr><td><code>/status</code></td><td>Uptime, auto-scan state, WebSocket price-monitor state, and the health of the news sources: the calendar, the headline feeds, the local headline model (a ⚠️ line "News model: not scoring" means this cycle's headlines carry the simple keyword scores) and DeepSeek.</td></tr>
<tr><td><code>/news</code></td><td>Net XAU/USD news score from the last 4 hours of headlines (neutral headlines are removed before averaging; informational only — never gates signals).</td></tr>
<tr><td><code>/cache</code> · <code>/clearcache</code></td><td>Inspect / reset the market-data cache.</td></tr>
<tr><td><code>/help</code></td><td>Command reference.</td></tr>