Tiingo bid/ask spread monitor + logging hardening

- tiingo_provider.py: /tiingo/fx/top quotes (10s TTL cache, graceful
  None on any failure); spread log writer. Signals never consume
  bid/ask; warn-only by design (no historical bid/ask to validate a
  gate against — live == backtest rule).
- app_config: repo-root .env loader (setdefault; shell env still wins),
  tiingo_api_key resolver (TIINGO_API_KEY/TIINGO → config.json),
  telegram.channel_spread_detail flag (default false).
- telegram_bot: 5-min spread sampler → logs/spread_log.csv (weekend-
  aware), alert-time quote refresh, bid/ask + wide-spread warning in
  signal messages, /status spread line. Raw numbers to owner DM always;
  channel only while channel_spread_detail=true (Tiingo free tier is
  internal-use-only; flip before public launch). Free-tier limit math:
  worst case ~41 req/h vs 50/h cap, one pair.
- Logging: 3h rotation x 240 backups (30-day retention), full-date
  stamps, force=True root handlers; candle loops + sampler survive
  failed cycles; breach-task exceptions logged via done-callback;
  PTB error handler; sys/threading excepthooks in main().
- test_all.py: Module 14 (tiingo, dotenv, spread routing, loop
  resilience, rotation) — 215 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVRmy6KspMs96o5PTPYFAB
This commit is contained in:
Harwinder Sekhon
2026-07-22 17:18:14 -04:00
parent 0823c05868
commit 91b4a6bb5e
6 changed files with 733 additions and 27 deletions
+5 -1
View File
@@ -3,12 +3,16 @@
"token": "123456789:REPLACE_WITH_YOUR_BOT_TOKEN",
"chat_id": "REPLACE_WITH_OWNER_CHAT_ID",
"channel_id": "-100REPLACE_WITH_CHANNEL_ID_OR_EMPTY_STRING",
"alert_min_quality": "C"
"alert_min_quality": "C",
"channel_spread_detail": false
},
"data_providers": {
"active": "twelve_data",
"twelve_data": {
"api_key": "REPLACE_WITH_YOUR_TWELVE_DATA_API_KEY"
},
"tiingo": {
"api_key": ""
}
},
"scanning": {