Tighten signal pipeline: yfinance-only XAU/XAG, leaner Telegram /scan

- XAU/XAG always route to Yahoo Finance and skip Twelve Data entirely
  (excluded from batch prefetch, served per-symbol via yfinance).
- Daily chart cleanly skipped for gold/silver — engine drops it from MTF.
- Telegram /scan limited to EURUSD, USDJPY, GBPUSD, XAUUSD.
- SCAN_TIMEFRAMES reduced to single H1 primary; engine still pulls
  M15+H1+D1 internally via confirmation TFs (halves API credits per scan).
- Default confirmation TFs swapped H4 -> D1 in config and main.py.
- mtf_agreement_threshold kept at 2-of-3.
- CLAUDE.md cleaned up — old XAUUSD/synthetic-data bug reports removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Harwinder
2026-05-05 19:52:41 -04:00
parent 4c1d839a1a
commit 1100b9eaf2
5 changed files with 45 additions and 70 deletions
+27 -3
View File
@@ -157,6 +157,24 @@ class ForexDataProvider:
if cached is not None and not cached.empty:
return cached
# Symbols not on Twelve Data (gold, silver) always use yfinance.
# D1 is intentionally skipped for these — yfinance daily for futures
# is unreliable and the engine drops missing confirmation TFs cleanly.
if symbol in _YF_FALLBACK_MAP:
if timeframe == Timeframe.D1:
raise DataUnavailableError(
f"Daily chart skipped for {symbol} — gold/silver use M15/H1 only."
)
yf_df = self._fetch_yfinance_fallback(symbol, timeframe)
if yf_df is None:
raise DataUnavailableError(
f"Yahoo Finance unavailable for {symbol} ({timeframe.value})."
)
df = self._validate_and_clean(yf_df, symbol, timeframe)
self._cache[cache_key] = df
self._cache_timestamps[cache_key] = now
return df
df = self._fetch_twelve_data(symbol, timeframe, lookback_days)
df = self._validate_and_clean(df, symbol, timeframe)
@@ -181,6 +199,12 @@ class ForexDataProvider:
if lookback_days is None:
lookback_days = self.config.data_lookback_days
# XAU/XAG aren't on Twelve Data — exclude them from the batch call,
# they'll be fetched individually via yfinance on demand.
td_symbols = [s for s in symbols if s not in _YF_FALLBACK_MAP]
if not td_symbols:
return
now = time.time()
for tf in timeframes:
ttl = self._cache_ttl(tf)
@@ -188,13 +212,13 @@ class ForexDataProvider:
f"{s}_{tf.value}" in self._cache_timestamps
and (now - self._cache_timestamps[f"{s}_{tf.value}"]) < ttl
and not self._cache.get(f"{s}_{tf.value}", pd.DataFrame()).empty
for s in symbols
for s in td_symbols
)
if cached:
logger.debug(f"Skipping prefetch for {tf.value} — all {len(symbols)} symbols cached (TTL {ttl}s)")
logger.debug(f"Skipping prefetch for {tf.value} — all {len(td_symbols)} symbols cached (TTL {ttl}s)")
continue
try:
self._batch_fetch_timeframe(symbols, tf, lookback_days)
self._batch_fetch_timeframe(td_symbols, tf, lookback_days)
time.sleep(1.0) # brief pause between TF requests
except Exception as e:
logger.warning(f"Batch prefetch failed for {tf.value}: {e}")