Files
ForexBot2/config.py
T
harwinder cd69980f1f Harden Telegram bot, add EUR/GBP strategies, parallelize scans
Telegram reliability: rate-limited sends (1 msg/s), dashboard lock,
WebSocket JSON/price error handling, markdown escaping, level cache
TTL, cooldown cleanup, breach task tracking, graceful shutdown.

Telegram speed: parallelize 3-pair scans with asyncio.gather(),
increase thread pool 2→4, parallelize boot-up initial scan.

Strategy: add EUR/USD and GBP/USD pullback-buy strategies with
per-pair configs, optimize XAU TP to 0.9×ATR, block hours 8/9
for XAU and hour 17 for GBP.

Backtest: add --max-hours flag to evaluate.py for time-exit support.
2026-05-13 21:07:49 -04:00

234 lines
6.8 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
ForexBot2 — Configuration
==========================================
"""
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"
# ── Supported pairs ──────────────────────────────────────────────
USDJPY = "USDJPY=X"
EURUSD = "EURUSD=X"
GBPUSD = "GBPUSD=X"
XAUUSD = "XAU/USD"
PAIR_INFO = {
USDJPY: {"display": "USD/JPY", "pip_value": 0.01, "is_jpy_pair": True},
EURUSD: {"display": "EUR/USD", "pip_value": 0.0001, "is_jpy_pair": False},
GBPUSD: {"display": "GBP/USD", "pip_value": 0.0001, "is_jpy_pair": False},
XAUUSD: {"display": "XAU/USD", "pip_value": 0.10, "is_jpy_pair": False},
}
# Defaults (kept for backward compat)
DISPLAY = "USD/JPY"
PIP_VALUE = 0.01
@dataclass
class TechnicalConfig:
"""Technical indicator parameters."""
ema_fast: int = 9
ema_medium: int = 21
ema_slow: int = 50
ema_trend: int = 200
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_fast: int = 12
macd_slow: int = 26
macd_signal: int = 9
bb_period: int = 20
bb_std: float = 2.0
atr_period: int = 14
adx_period: int = 14
adx_strong_trend: float = 25.0
adx_very_strong: float = 50.0
divergence_lookback: int = 14
swing_sr_lookback: int = 50
disabled_indicators: List[str] = field(default_factory=lambda: ["divergence"])
ema_mode: str = "4ema" # "4ema" (9/21/50/200) or "2ema" (50/200)
rsi_mode: str = "classic" # "classic" or "regime_aware"
macd_as_pillar: bool = False # promote MACD histogram to scored signal
regime_weights_override: Dict[str, Dict[str, float]] = field(default_factory=dict)
@dataclass
class SignalConfig:
"""Signal scoring & filtering."""
min_confidence: float = 55.0
weights: Dict[str, float] = field(default_factory=lambda: {
"ema_trend": 1.0,
"rsi": 1.5,
"bollinger": 1.5,
"candlestick": 1.0,
"divergence": 1.5,
})
mtf_agreement_threshold: int = 2 # of 3 timeframes
cooldown_bars: int = 5
default_risk_pct: float = 1.0
default_rr_ratio: float = 2.0
atr_sl_multiplier: float = 1.5
min_rr_ratio: float = 1.2
@dataclass
class NewsConfig:
"""Economic calendar & sentiment."""
tracked_currencies: List[str] = field(default_factory=lambda: ["USD", "JPY", "EUR", "GBP", "XAU"])
min_impact: str = "medium"
pre_event_buffer_minutes: int = 30
post_event_buffer_minutes: int = 15
rss_feeds: List[str] = field(default_factory=lambda: [
"https://www.forexlive.com/feed/",
"https://www.fxstreet.com/rss",
])
@dataclass
class XauStrategyConfig:
"""XAU/USD oversold-bounce strategy (BUY only).
1-year optimized: 89% WR, PF 4.58, +5041p (118 trades).
Entry: M15 RSI<38 + price above EMA200 on M15, H1, H4.
Exit: TP=0.9×ATR, SL=2.0×ATR.
"""
enabled: bool = True
rsi_entry_threshold: float = 38.0 # Wilder RSI scale; equivalent to standard RSI ~30
tp_atr_multiplier: float = 0.9
sl_atr_multiplier: float = 2.0
blocked_hours_utc: List[int] = field(default_factory=lambda: [8, 9, 11, 14, 15, 20])
@dataclass
class EurStrategyConfig:
"""EUR/USD pullback-buy strategy (BUY only).
Fixes: no entries at BB resistance, no overbought RSI, no chasing.
Entry: M15 RSI 30–55 (pullback zone) + BB position < 0.75
+ price > EMA200 on M15 & H1 + near EMA21 (not chasing).
Exit: TP=0.7×ATR, SL=1.5×ATR.
"""
enabled: bool = True
rsi_lower: float = 30.0
rsi_upper: float = 55.0
bb_max_position: float = 0.75
chase_max_atr_from_ema21: float = 1.5
tp_atr_multiplier: float = 0.7
sl_atr_multiplier: float = 1.0
blocked_hours_utc: List[int] = field(default_factory=lambda: [0, 1, 2, 3, 4, 5, 6, 16, 17, 18, 19, 21, 22, 23])
@dataclass
class GbpStrategyConfig:
"""GBP/USD pullback-buy strategy (BUY only).
1-year optimized: hour 17 blocked.
Entry: M15 RSI 30–55 + BB < 0.75 + price > EMA200 on M15 & H1
+ within 1.5×ATR of EMA21.
Exit: TP=0.7×ATR, SL=1.0×ATR.
"""
enabled: bool = True
rsi_lower: float = 30.0
rsi_upper: float = 55.0
bb_min_position: float = 0.0
bb_max_position: float = 0.75
chase_max_atr_from_ema21: float = 1.5
tp_atr_multiplier: float = 0.7
sl_atr_multiplier: float = 1.0
blocked_hours_utc: List[int] = field(default_factory=lambda: [0, 1, 2, 3, 4, 5, 6, 14, 15, 16, 17, 19, 21, 22, 23])
@dataclass
class FilterConfig:
"""Regime and session filters for live signals."""
regime_filter: bool = False
regime_filter_timeframe: Timeframe = Timeframe.H4
regime_filter_min_adx: float = 25.0
session_filter: bool = True
session_start_hour: int = 7
session_end_hour: int = 16
blocked_hours_utc: List[int] = field(default_factory=lambda: [0, 1, 2, 5, 6, 8, 12, 13, 14, 15, 16, 17, 21, 22, 23])
sell_filter: bool = True
sell_allowed_pairs: List[str] = field(default_factory=lambda: ["XAU/USD"])
@dataclass
class PlatformConfig:
"""Top-level configuration."""
technical: TechnicalConfig = field(default_factory=TechnicalConfig)
signals: SignalConfig = field(default_factory=SignalConfig)
news: NewsConfig = field(default_factory=NewsConfig)
backtest: FilterConfig = field(default_factory=FilterConfig)
xau_strategy: XauStrategyConfig = field(default_factory=XauStrategyConfig)
eur_strategy: EurStrategyConfig = field(default_factory=EurStrategyConfig)
gbp_strategy: GbpStrategyConfig = field(default_factory=GbpStrategyConfig)
symbol: str = USDJPY
display_name: str = DISPLAY
pip_value: float = PIP_VALUE
primary_timeframe: Timeframe = Timeframe.H1
confirmation_timeframes: List[Timeframe] = field(
default_factory=lambda: [Timeframe.M15, Timeframe.H4]
)
data_lookback_days: int = 60
twelve_data_api_key: str = "f563b22ffdfd4924955decbe1a8c8701"
refresh_interval: int = 300
scan_pairs: List[str] = field(
default_factory=lambda: [EURUSD, GBPUSD, XAUUSD]
)
scan_timeframes: List[Timeframe] = field(
default_factory=lambda: [Timeframe.M5, Timeframe.M15, Timeframe.H1, Timeframe.H4]
)
candle_buffer_seconds: int = 10
ws_cooldown_seconds: int = 300
log_level: str = "INFO"