a708609f8b
Add EURUSD pair with dynamic pair info lookup. Telegram bot now shows 4 scan buttons: EUR/USD 15M, EUR/USD 1H, USD/JPY 15M, USD/JPY 1H. Each indicator displays directional arrows in the message output. Price formatting adapts per pair (5dp for EUR, 3dp for JPY).
167 lines
3.9 KiB
Python
167 lines
3.9 KiB
Python
"""
|
||
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"
|
||
|
||
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},
|
||
}
|
||
|
||
# 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
|
||
|
||
stoch_k: int = 14
|
||
stoch_d: int = 3
|
||
stoch_overbought: float = 80.0
|
||
stoch_oversold: float = 20.0
|
||
|
||
adx_period: int = 14
|
||
adx_strong_trend: float = 25.0
|
||
adx_very_strong: float = 50.0
|
||
|
||
ichimoku_tenkan: int = 9
|
||
ichimoku_kijun: int = 26
|
||
ichimoku_senkou_b: int = 52
|
||
|
||
volume_ma_period: int = 20
|
||
pivot_lookback: int = 1
|
||
divergence_lookback: int = 14
|
||
|
||
disabled_indicators: List[str] = field(default_factory=list)
|
||
|
||
|
||
@dataclass
|
||
class SignalConfig:
|
||
"""Signal scoring & filtering."""
|
||
min_confidence: float = 55.0
|
||
|
||
weights: Dict[str, float] = field(default_factory=lambda: {
|
||
"trend": 0.25,
|
||
"momentum": 0.20,
|
||
"volatility": 0.15,
|
||
"price_action": 0.15,
|
||
"multi_timeframe": 0.15,
|
||
"sentiment": 0.10,
|
||
})
|
||
|
||
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 # SL distance = 1.5 × ATR
|
||
|
||
|
||
@dataclass
|
||
class NewsConfig:
|
||
"""Economic calendar & sentiment."""
|
||
tracked_currencies: List[str] = field(default_factory=lambda: ["USD", "JPY", "EUR"])
|
||
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 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 = False
|
||
session_start_hour: int = 7
|
||
session_end_hour: int = 16
|
||
|
||
|
||
@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)
|
||
|
||
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
|
||
|
||
log_level: str = "INFO"
|