Files
ForexBot2/config.py
T
Harwinder 1100b9eaf2 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>
2026-05-05 19:52:41 -04:00

222 lines
6.5 KiB
Python

"""
Forex Signal Intelligence Platform - Configuration
===================================================
Central configuration for all signal analysis parameters.
Tuned by market regime and validated against historical performance.
"""
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List
class Timeframe(Enum):
M1 = "1min"
M5 = "5min"
M15 = "15min"
M30 = "30min"
H1 = "1h"
H4 = "4h"
D1 = "1d"
W1 = "1wk"
class SignalStrength(Enum):
STRONG_BUY = 2
BUY = 1
NEUTRAL = 0
SELL = -1
STRONG_SELL = -2
class MarketSession(Enum):
SYDNEY = "sydney"
TOKYO = "tokyo"
LONDON = "london"
NEW_YORK = "new_york"
OVERLAP_LONDON_NY = "london_ny_overlap"
# ── Major Forex Pairs ──────────────────────────────────────────────
MAJOR_PAIRS = [
"EURUSD=X", "GBPUSD=X", "USDJPY=X", "USDCHF=X",
"AUDUSD=X", "USDCAD=X", "NZDUSD=X",
]
CROSS_PAIRS = [
"EURGBP=X", "EURJPY=X", "GBPJPY=X", "AUDJPY=X",
"EURCHF=X", "CADJPY=X",
]
# Symbol display names
SYMBOL_DISPLAY = {
"EURUSD=X": "EUR/USD", "GBPUSD=X": "GBP/USD",
"USDJPY=X": "USD/JPY", "USDCHF=X": "USD/CHF",
"AUDUSD=X": "AUD/USD", "USDCAD=X": "USD/CAD",
"NZDUSD=X": "NZD/USD", "EURGBP=X": "EUR/GBP",
"EURJPY=X": "EUR/JPY", "GBPJPY=X": "GBP/JPY",
"AUDJPY=X": "AUD/JPY", "EURCHF=X": "EUR/CHF",
"CADJPY=X": "CAD/JPY",
# Commodities
"XAUUSD=X": "XAU/USD", "XAGUSD=X": "XAG/USD",
}
# Pip values per symbol (used for trade setup risk/reward in pips)
# Commodities and JPY pairs differ from the standard 0.0001 forex pip
PIP_VALUES = {
"XAUUSD=X": 0.01, # Gold: 1 pip = $0.01
"XAGUSD=X": 0.001, # Silver: 1 pip = $0.001
}
@dataclass
class TechnicalConfig:
"""Technical indicator parameters - carefully tuned for Forex."""
# EMA periods (fast/medium/slow for trend detection)
ema_fast: int = 9
ema_medium: int = 21
ema_slow: int = 50
ema_trend: int = 200
# RSI
rsi_period: int = 14
rsi_overbought: float = 70.0
rsi_oversold: float = 30.0
rsi_neutral_upper: float = 60.0
rsi_neutral_lower: float = 40.0
# MACD (12, 26, 9 is standard)
macd_fast: int = 12
macd_slow: int = 26
macd_signal: int = 9
# Bollinger Bands
bb_period: int = 20
bb_std: float = 2.0
# ATR for volatility measurement
atr_period: int = 14
# Stochastic
stoch_k: int = 14
stoch_d: int = 3
stoch_overbought: float = 80.0
stoch_oversold: float = 20.0
# ADX for trend strength
adx_period: int = 14
adx_strong_trend: float = 25.0
adx_very_strong: float = 50.0
# Ichimoku
ichimoku_tenkan: int = 9
ichimoku_kijun: int = 26
ichimoku_senkou_b: int = 52
# Volume profile
volume_ma_period: int = 20
# Pivot points lookback
pivot_lookback: int = 1
# Divergence detection — how many bars back to scan for swing points
divergence_lookback: int = 14
@dataclass
class SignalConfig:
"""Signal scoring and filtering parameters."""
# Minimum confidence to emit a signal (0-100)
min_confidence: float = 55.0
# Weight allocation for composite score
weights: Dict[str, float] = field(default_factory=lambda: {
"trend": 0.25, # EMA alignment, ADX
"momentum": 0.20, # RSI, Stochastic, MACD
"volatility": 0.15, # BB position, ATR regime
"price_action": 0.15, # Candlestick patterns, S/R
"multi_timeframe": 0.15,# Higher TF confirmation
"sentiment": 0.10, # News/calendar events
})
# Multi-timeframe confirmation requirements
mtf_agreement_threshold: int = 2 # out of 3 timeframes must agree
# Signal cooldown (prevent over-signalling same direction)
cooldown_bars: int = 5
# Risk management defaults
default_risk_pct: float = 1.0 # risk 1% per trade
default_rr_ratio: float = 2.0 # 1:2 risk-reward minimum
@dataclass
class NewsConfig:
"""Economic calendar and sentiment configuration."""
# High-impact event currencies
tracked_currencies: List[str] = field(default_factory=lambda: [
"USD", "EUR", "GBP", "JPY", "CHF", "AUD", "CAD", "NZD"
])
# Event impact levels to monitor
min_impact: str = "medium" # "low", "medium", "high"
# Pre-event buffer (minutes before high-impact event = no new signals)
pre_event_buffer_minutes: int = 30
# Post-event volatility window (minutes after event = cautious signals)
post_event_buffer_minutes: int = 15
# News sentiment sources
rss_feeds: List[str] = field(default_factory=lambda: [
"https://www.forexlive.com/feed/",
"https://www.fxstreet.com/rss",
])
@dataclass
class PlatformConfig:
"""Overall platform configuration."""
technical: TechnicalConfig = field(default_factory=TechnicalConfig)
signals: SignalConfig = field(default_factory=SignalConfig)
news: NewsConfig = field(default_factory=NewsConfig)
# Default pairs to monitor
watch_pairs: List[str] = field(default_factory=lambda: MAJOR_PAIRS)
# Analysis timeframes (primary + confirmation)
primary_timeframe: Timeframe = Timeframe.H1
confirmation_timeframes: List[Timeframe] = field(
default_factory=lambda: [Timeframe.M15, Timeframe.D1]
)
# Data source
data_lookback_days: int = 60 # enough for 200 EMA on H1
# Twelve Data API key (overridden by TWELVE_DATA_API_KEY env var)
twelve_data_api_key: str = "f563b22ffdfd4924955decbe1a8c8701"
# Dashboard refresh interval (seconds) — used as a fallback when a
# timeframe isn't covered by cache_ttl_per_tf below.
refresh_interval: int = 300 # 5 minutes
# Per-timeframe cache TTL (seconds). A 1-week candle changes less
# often than a 15-minute candle, so caching them all for the same
# 5 minutes wastes API credits. Tuned to roughly match each TF's
# bar interval so we re-fetch about once per new bar.
cache_ttl_per_tf: Dict[Timeframe, int] = field(default_factory=lambda: {
Timeframe.M1: 60, # 1 minute
Timeframe.M5: 150, # 2.5 minutes
Timeframe.M15: 300, # 5 minutes
Timeframe.M30: 600, # 10 minutes
Timeframe.H1: 1800, # 30 minutes
Timeframe.H4: 7200, # 2 hours
Timeframe.D1: 14400, # 4 hours
Timeframe.W1: 86400, # 24 hours
})
# Logging
log_level: str = "INFO"
log_signals_to_file: bool = True
signal_log_path: str = "signals.log"