- engine: composite-score denominator now confidence-weighted, so the
output actually spans -100..+100 (the prior formula put confidence
in the numerator only, capping the realistic score around ±25-30
and making STRONG_BUY ≥40 essentially unreachable).
- engine: ATR percentile uses iloc[-50:-1] to exclude the current bar
from its own comparison (off-by-one in volatility regime).
- signal_aggregator: always blend primary score with MTF average. The
prior code only blended on agreement, leaving the primary unblended
on disagreement — backwards. Disagreement is exactly when the score
should be pulled toward consensus.
- telegram_bot: JobQueue auto-scan every 10 min that pushes A/A+ to
ALERT_CHAT_ID with a prominent News & Events block (sentiment +
headline summary + event-risk + alignment hint). Per-bar dedup so
persistent setups alert once per new candle, not every 10 min.
Suppresses alerts when event_risk = "danger".
- telegram_bot: /myid returns chat ID for ALERT_CHAT_ID setup. Auto-scan
silently disabled when ALERT_CHAT_ID is unset.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- data_provider: strip yfinance imports, _YF_FALLBACK_MAP, _YF_INTERVALS,
_YF_SESSION, _fetch_yfinance_fallback, _resample_h1_to_h4. Twelve Data
is the sole data source. Raises DataUnavailableError if a pair isn't
on the configured plan.
- config: remove XAU/USD and XAG/USD from SYMBOL_DISPLAY and PIP_VALUES.
PIP_VALUES is now empty (defaults: 0.01 JPY pairs, 0.0001 forex).
- signal_aggregator: clear _PER_SYMBOL_TFS overrides (was XAU/XAG-only).
- telegram_bot: replace XAUUSD with AUDUSD in SCAN_PAIRS. Auto-load .env
via python-dotenv so TELEGRAM_BOT_TOKEN/GEMINI_API_KEY are picked up.
- requirements: drop yfinance and curl_cffi dependencies.
End-to-end pipeline test passes: data freshness, news engine (Gemini live),
signal aggregator, and the /signal+/scan code paths in telegram_bot.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New _PER_SYMBOL_TFS map in signal_aggregator routes gold/silver to
M15+H1+H4 confirmation; forex pairs untouched.
- H4 for XAU/XAG is resampled from yfinance H1 bars (yfinance has no
native 4h candle). New _resample_h1_to_h4 helper.
- Batch prefetch unions per-symbol TFs so future per-pair overrides
work without extra plumbing. XAU/XAG still excluded from Twelve Data
batch — H4 resample triggers a single yfinance H1 fetch.
- Telegram SCAN_TIMEFRAMES restored to [M15, H1] so /scan emits both
M15-primary and H1-primary cards. Shared cache means no extra credits.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- telegram_bot: one ForexDataProvider shared across all SCAN_TIMEFRAMES;
combined prefetch of all unique TFs up front so the 4 concurrent scans
hit the warm cache instead of firing simultaneous API calls
- data_provider: skip prefetch_batch for timeframes already in cache
- data_provider: deduplicate "no data" warning per symbol (fires once, not once per TF)
- data_provider: [live] info log on successful fetch; outlier-removal downgraded to debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add telegram_bot.py: full bot interface with /scan, /signals, /pair,
/all, /tf, /watch, /unwatch, /status, /help commands; per-chat state;
background thread pool for analysis; auto message splitting
- Fix data_provider: warn once per symbol with no API data and cache
synthetic fallback to prevent redundant individual API calls
- Fix signal_aggregator: derive spread estimate from already-fetched
primary DataFrame instead of making a separate M5 API call per pair
- Add python-telegram-bot[job-queue]>=20.0 to requirements.txt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>