Live path: config-driven multi-pair scanning (Telegram bot + CLI)

- telegram_bot: SCAN_PAIRS/_WS_TO_PAIR/SCAN_BUTTONS all derive from
  PlatformConfig.scan_pairs (the single pair on/off switch); buttons and
  keyboards are generated per pair; _run_signal_sync builds per-pair
  configs via pair_signals factories (was: XAU defaults for any symbol);
  scan-all works per pair; PB badge matches any *_PB tag; daily-rotating
  file logs in logs/telegram.log (30-day retention)
- main.py: --pair argument (XAUUSD | EURUSD + aliases) routed through
  pair_signals factories; price display is precision-aware (2dp gold,
  5dp FX)

scan_pairs default stays [XAUUSD] until the EUR M5 re-tune validates.
This commit is contained in:
Harwinder Sekhon
2026-07-10 21:13:42 -04:00
parent 6546b89d6b
commit 74829541d6
3 changed files with 150 additions and 58 deletions
+21 -2
View File
@@ -1415,6 +1415,7 @@ def _():
@test("build_config sets correct timeframe and confirmations")
def _():
class FakeArgs:
pair = "XAUUSD"
timeframe = "H4"
config = build_config(FakeArgs())
assert config.primary_timeframe == Timeframe.H4
@@ -1426,11 +1427,23 @@ def _():
def _():
for tf_str in ["M5", "M15", "M30", "H1", "H4", "D1"]:
class FakeArgs:
pair = "XAUUSD"
timeframe = tf_str
config = build_config(FakeArgs())
assert config.primary_timeframe is not None
@test("build_config resolves EURUSD pair to EUR factory config")
def _():
class FakeArgs:
pair = "EURUSD"
timeframe = "M15"
config = build_config(FakeArgs())
assert config.symbol == "EUR/USD"
assert config.pip_value == 0.0001
assert config.primary_timeframe == Timeframe.M15
# ══════════════════════════════════════════════════════════════════════
# MODULE 7: telegram_bot.py
# ══════════════════════════════════════════════════════════════════════
@@ -1609,10 +1622,13 @@ def _():
@test("SCAN_BUTTONS and SCAN_LOOKUP consistency")
def _():
assert len(SCAN_BUTTONS) == 5 # 4 TFs + "Scan All"
from telegram_bot import SCAN_PAIRS
# 4 TF buttons + one "Scan All" per scanned pair
assert len(SCAN_BUTTONS) == 5 * len(SCAN_PAIRS)
for btn in SCAN_BUTTONS:
assert btn["cb"] in SCAN_LOOKUP
assert "symbol" in btn
assert btn["symbol"] in SCAN_PAIRS
assert "tf" in btn
assert "label" in btn
@@ -1642,8 +1658,11 @@ def _():
_level_cache_ts.clear()
@test("_WS_TO_PAIR mapping is correct")
@test("_WS_TO_PAIR mapping covers every scanned pair")
def _():
from telegram_bot import SCAN_PAIRS
for p in SCAN_PAIRS:
assert _WS_TO_PAIR[PAIR_INFO[p]["display"]] == p
assert _WS_TO_PAIR["XAU/USD"] == XAUUSD