Live pipeline: - Drop still-forming candle before analysis (signals no longer repaint) - Direction-aware MTF agreement + opposition gate (no trade against 2-of-3 TF consensus) - SELL volatility gate: block shorts in low/normal vol regimes (config sell_vol_regimes) - Divergence: 40-bar lookback, price/indicator swings must align within ±2 bars (fired on 0.5% of trades before, 29% after), trending weight 2.0→1.0 - RSI regime_aware by default; transitioning regime only signals at extremes - ADX ±DM tie no longer nudges bearish; TP2 clamped beyond TP1 Backtester realism: - Charge $0.30 round-trip spread (--spread), gap-through SL/TP fills at bar open - Resolve trades on RAW price path (cache stores raw bars, cleaning runs on load) - Weekend/session filters use bar-close decision time to match live wall clock Validated per-step on M15 2025-03-30→2026-05-31 under identical pricing: +46.9R → +66.8R, win rate 69.9% → 73.0%, SELL side -2.3R → +9.6R. Tested-and-reverted: ROC weight removal (-13R), BB fade suppression (-11.6R), candlestick de-weight (-2R) — composite thresholds are co-tuned with weight mass.
7.0 KiB
ForexBot2
XAU/USD signal intelligence platform. Analyzes gold across multiple timeframes using 9 technical indicators with regime-adaptive weights, news sentiment, and economic calendar data. Delivers signals via Telegram with full trade setups (entry, SL, TP).
Architecture
Twelve Data REST API + WebSocket
|
data_provider.py (fetch, cache, validate OHLCV; rate-limited 55 calls/min)
|
engine.py (9 indicators per timeframe → composite score)
|
signal_aggregator.py (MTF agreement + news + final signal + trade setup)
|
+-----+--------+
| |
telegram_bot.py main.py
(Telegram alerts, (CLI single-pair
auto-scanner, analysis)
WS monitor)
Core Files
| File | Purpose |
|---|---|
config.py |
All configuration dataclasses, XAU/USD pair definition, strategy config |
data_provider.py |
Twelve Data SDK wrapper with in-memory cache and rate limiting |
engine.py |
TechnicalEngine — computes EMA, RSI, BB, ADX, ATR, MACD, ROC, Keltner, divergences, candlestick patterns, swing S/R |
signal_aggregator.py |
SignalAggregator — MTF analysis, news integration, diminishing penalty cap, trade setup generation |
news_engine.py |
Economic calendar (Forex Factory JSON) + RSS sentiment (keyword-based) |
telegram_bot.py |
Async Telegram bot with auto-scanner (M5/M15/H1/H4), WebSocket price monitor |
main.py |
CLI entry point for XAU/USD analysis |
test_all.py |
Comprehensive QA suite (~137 tests, no live API needed) |
Key Concepts
Signal Pipeline: OHLCV → indicators → regime classification → regime-weighted composite score → MTF agreement check → news/event adjustment → diminishing penalty cap → final signal (STRONG_BUY/BUY/NEUTRAL/SELL/STRONG_SELL) → quality grade (A+/A/B/C/D/F) → trade setup if grade C+.
Regime-Adaptive Weights: Market classified as trending_up, trending_down, ranging, or transitioning via ADX + EMA + ADX slope. Gold-specific weights per regime:
- Trending: MACD (2.0), EMA (2.0), Keltner (1.5), ROC (1.5), Divergence (1.0)
- Ranging: Divergence (2.5), Keltner (2.0), RSI (1.5), BB (1.5), MACD (1.5)
- Transitioning: Keltner (2.5), MACD (2.5), ROC (2.0), Divergence (2.0), EMA (1.5)
ROC is directionally redundant with MACD/Keltner/EMA (0.8–0.94 correlation) but its weight is load-bearing: composite thresholds are calibrated with it — removing it backtested 13R worse. Don't zero it without retuning thresholds.
RSI (regime-aware, default): In trends RSI buys pullback zones instead of fading strength (classic mode backtested worse for gold). In transitioning only extremes (≥70/≤30) signal.
Divergence: 40-bar lookback; price and indicator swings must align within ±2 bars to count as one divergence observation.
Transitioning Regime: ADX < 25 but ADX slope > 3.0 = trend emerging. Catches trend birth 5-10 bars before ADX crosses 25. Boosts quality grade for early entries.
Diminishing Penalty Cap: Penalties sorted by magnitude, applied with exponential decay (1st at 100%, 2nd at 50%, 3rd at 25%). Hard cap at 30% total. Replaces old additive stacking that could gut 30-50% confidence.
Indicators (9 scored): EMA Trend, RSI, Bollinger Bands, MACD, ADX, Keltner Channels (TTM Squeeze), ROC (Rate of Change), Divergence, Candlestick Patterns.
Trade Setup: SL = nearest swing low/high ± 1×ATR buffer (min 1.5×ATR). TP = nearest swing level if RR≥1.2, else calculated from ATR. Minimum RR 0.5:1.
How to Run
# CLI (XAU/USD analysis)
python main.py # H1 default
python main.py --timeframe M15 --detail --json
# Telegram bot (auto-scanner)
TELEGRAM_TOKEN=<token> TELEGRAM_CHAT_ID=<id> python telegram_bot.py
# Tests
python test_all.py
# Backtest
python backtest/gpu_backtest.py --pair XAUUSD --days 365
Environment Variables
| Variable | Purpose | Default |
|---|---|---|
TWELVE_DATA_API_KEY |
Market data API key | Hardcoded fallback in config |
TELEGRAM_TOKEN |
Telegram bot token | Hardcoded fallback |
TELEGRAM_CHAT_ID |
Auto-scan chat ID (enables boot auto-scan) | Hardcoded fallback |
Dependencies
numpy, pandas, requests, twelvedata, python-telegram-bot, websockets — see requirements.txt.
Data Provider
- Source: Twelve Data REST API via
twelvedataSDK - Rate limit: 55 credits/min (Grow plan), enforced by sliding-window throttle
- Cache: In-memory dict, TTL = candle duration of the timeframe
- Validation: Drops NaN rows, forward-fills gaps (limit 3), fixes OHLC inconsistencies, removes outliers (>10σ), strips future timestamps, deduplicates
- WebSocket: XAU/USD only
Telegram Bot
- Auto-scan: M5, M15, H1, H4 at candle boundaries + 10s buffer (all timeframes alert)
- Manual scan: Buttons for M15/H1/H4 individual scans + "Scan All TFs" multi-timeframe summary
- WebSocket: Streams live ticks for XAU/USD; triggers immediate M15 scan on key level breach (swing S/R, BB, KC, EMA200) with 5-min cooldown
- Commands:
/start,/scan,/autoscan,/status,/cache,/clearcache,/help
Backtesting
The backtest/ directory contains gpu_backtest.py — a GPU-accelerated backtester (CuPy with NumPy fallback) that replays historical OHLCV through the real SignalAggregator. Pre-computes all indicator series including ROC, Keltner, ADX slope for 100x+ speedup. Uses parquet caching for data persistence.
Fill realism: charges a round-trip spread per trade (--spread, default $0.30 for XAU), fills gap-through SL/TP at the bar open, and resolves trades against the RAW price path (the parquet cache stores raw bars; validation/cleaning runs on load — signals see cleaned data, trade resolution sees real spikes). Entry is at the next bar's open after the signal bar. Weekend/session filters evaluate bar-close (decision) time to match the live bot's wall clock.
GPU note: CuPy needs the NVIDIA runtime pip wheels (nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-curand-cu12, nvidia-nvjitlink-cu12) or it silently falls back to NumPy — check the "Backend:" line in the run log. The bar-replay loop itself is single-threaded Python either way (~340 bars/s); GPU only accelerates indicator precompute and SL/TP scanning.
Code Conventions
- Python 3.12, type hints on public methods
- Dataclasses for all config and output structures
SignalStrengthenum (-2 to +2) is the universal signal currency- Indicators stored as
Dict[str, IndicatorSignal]inTechnicalAnalysis - Key levels stored as
Dict[str, float]— prefixedswing_high_,swing_low_,ema_,bb_,kc_,atr - Private indicator data attached as
result._rsi_series,result._macd_histogram,result._adx_slope,result._kc_squeeze(underscore prefix, skipped by composite scorer) - Blocking signal computation runs in
ThreadPoolExecutor(max_workers=4)to avoid blocking the async Telegram event loop - Shared
ForexDataProviderinstance across all scans for cache reuse