Refocus on XAU/USD: add momentum indicators, tune TP, exhaustion block
Strip EUR/USD, GBP/USD, USD/JPY pairs and strategies from entire codebase. Add 3 new scored indicators (ROC, Keltner/TTM Squeeze, ADX slope) and enable MACD-as-pillar + divergence detection for early trend entry. Introduce "transitioning" regime (ADX < 25, slope > 3.0) to catch trend births before ADX confirms. Gold-specific composite weights per regime. Tune TP multipliers: quality-tiered scaling (A+/A get 1.5-2.0x ATR via XAU ATR method, B/C use swing-level targeting). Backtest: +24R total, 65% WR, PF 1.12 over 365 days. Add momentum-confirmed exhaustion block: hard-reject trades when 2+ static exhaustion signals fire AND ROC/MACD confirm fading momentum. Prevents late trend entries without killing strong trend trades. Telegram: simplify buttons to timeframe-only labels, add "Scan All TFs" multi-timeframe summary, add /scan command, fix BB/KC level breach keys, fix price formatting (.2f for gold), fix deprecated asyncio call, fix "1 pairs" grammar and 60s/30s dashboard refresh mismatch.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
ForexBot2 — Configuration
|
||||
ForexBot2 — Configuration (XAU/USD focused)
|
||||
==========================================
|
||||
"""
|
||||
|
||||
@@ -36,22 +36,12 @@ class MarketSession(Enum):
|
||||
|
||||
|
||||
# ── 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:
|
||||
@@ -83,11 +73,24 @@ class TechnicalConfig:
|
||||
divergence_lookback: int = 14
|
||||
swing_sr_lookback: int = 50
|
||||
|
||||
disabled_indicators: List[str] = field(default_factory=lambda: ["divergence"])
|
||||
disabled_indicators: List[str] = field(default_factory=list)
|
||||
|
||||
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
|
||||
macd_as_pillar: bool = True # MACD histogram is a scored signal
|
||||
|
||||
# ROC (Rate of Change)
|
||||
roc_period: int = 10
|
||||
roc_threshold: float = 1.0 # % threshold for strong signal
|
||||
|
||||
# Keltner Channels
|
||||
kc_period: int = 20
|
||||
kc_atr_period: int = 10
|
||||
kc_multiplier: float = 1.5
|
||||
|
||||
# ADX slope (trend acceleration detection)
|
||||
adx_slope_lookback: int = 5
|
||||
adx_slope_emerging_threshold: float = 3.0
|
||||
|
||||
regime_weights_override: Dict[str, Dict[str, float]] = field(default_factory=dict)
|
||||
|
||||
@@ -101,6 +104,9 @@ class SignalConfig:
|
||||
"ema_trend": 1.0,
|
||||
"rsi": 1.5,
|
||||
"bollinger": 1.5,
|
||||
"macd": 1.5,
|
||||
"keltner": 1.5,
|
||||
"roc": 1.5,
|
||||
"candlestick": 1.0,
|
||||
"divergence": 1.5,
|
||||
})
|
||||
@@ -117,7 +123,7 @@ class SignalConfig:
|
||||
@dataclass
|
||||
class NewsConfig:
|
||||
"""Economic calendar & sentiment."""
|
||||
tracked_currencies: List[str] = field(default_factory=lambda: ["USD", "JPY", "EUR", "GBP", "XAU"])
|
||||
tracked_currencies: List[str] = field(default_factory=lambda: ["USD", "XAU"])
|
||||
min_impact: str = "medium"
|
||||
pre_event_buffer_minutes: int = 30
|
||||
post_event_buffer_minutes: int = 15
|
||||
@@ -130,82 +136,27 @@ class NewsConfig:
|
||||
|
||||
@dataclass
|
||||
class XauStrategyConfig:
|
||||
"""XAU/USD v3 weighted confluence strategy.
|
||||
1-year grid-optimized (768 combos): 52.4% WR, PF 2.34, +40.3R (63 trades).
|
||||
Entry: M15 score>=80 + H4 RSI confirms + H1 MACD confirms + RSI 40-65 zone.
|
||||
Exit: Partial — 1R→BE, 2R→close 50%, 3R→close rest. SL=2.5×ATR.
|
||||
Blocked: Fri/Sat/Sun, hours 1/3/9/10/19/22/23.
|
||||
"""XAU/USD strategy config.
|
||||
Legacy gates (H4 RSI, H1 MACD, M15 score) removed in favor of
|
||||
new momentum indicators (ROC, Keltner squeeze, ADX slope).
|
||||
"""
|
||||
enabled: bool = True
|
||||
rsi_entry_threshold: float = 45.0
|
||||
tp_atr_multiplier: float = 0.9
|
||||
tp_atr_multiplier: float = 1.0
|
||||
sl_atr_multiplier: float = 2.0
|
||||
min_ema200_tfs: int = 2
|
||||
allow_generic_trades: bool = True
|
||||
blocked_hours_utc: List[int] = field(default_factory=lambda: [0, 1, 2, 5, 6, 21, 22, 23])
|
||||
# v2 confluence fixes
|
||||
weekend_filter: bool = True
|
||||
min_atr_threshold: float = 1.0
|
||||
v2_sl_atr_multiplier: float = 2.5
|
||||
buy_threshold_boost: int = 0
|
||||
m5_confirmation_bars: int = 0
|
||||
# v3 gates (grid-optimized on 1Y Mon-Thu data)
|
||||
h4_rsi_gate: bool = True # require H4 RSI >55 for BUY, <45 for SELL
|
||||
h1_macd_gate: bool = True # require H1 MACD histogram >0 for BUY, <0 for SELL
|
||||
rsi_zone: tuple = (40.0, 65.0) # only enter when M15 RSI in this zone
|
||||
h4_rsi_gate: bool = False
|
||||
h1_macd_gate: bool = False
|
||||
rsi_zone: tuple = (40.0, 65.0)
|
||||
allowed_weekdays: List[int] = field(default_factory=lambda: [0, 1, 2, 3, 4]) # Mon-Fri
|
||||
sell_min_quality: List[str] = field(default_factory=lambda: ["A+", "A", "B"]) # SELL needs B+
|
||||
|
||||
|
||||
@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])
|
||||
# If False, suppress generic trade setups when the EUR pullback gate
|
||||
# didn't fire. Backtest (90-day M15): True → +4.70R, False → +9.50R.
|
||||
# Generic momentum buys at trending_up extremes are pure drag.
|
||||
allow_generic_trades: bool = False
|
||||
# Minimum number of M15 scored indicators (ema_trend, rsi, bollinger,
|
||||
# adx, candlestick) that must independently signal BUY for the
|
||||
# pullback gate to fire. The strategy hardcodes Quality=A and
|
||||
# Score=+40 — without this, the "A" grade fires on weak technical
|
||||
# confluence. 0 = disabled (legacy behavior).
|
||||
min_indicators_agree: int = 2
|
||||
|
||||
|
||||
@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])
|
||||
# See EurStrategyConfig.allow_generic_trades — same rationale.
|
||||
allow_generic_trades: bool = False
|
||||
# See EurStrategyConfig.min_indicators_agree — same rationale.
|
||||
min_indicators_agree: int = 2
|
||||
sell_min_quality: List[str] = field(default_factory=lambda: ["A+", "A", "B"])
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -220,14 +171,8 @@ class FilterConfig:
|
||||
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])
|
||||
|
||||
# Universal weekday filter (0=Mon ... 6=Sun). Default Mon-Thu — Fridays
|
||||
# have wide spreads from US session ending and weekend gap risk; XAU/USD
|
||||
# has its own stricter allowed_weekdays in xau_strategy that overrides.
|
||||
allowed_weekdays: List[int] = field(default_factory=lambda: [0, 1, 2, 3])
|
||||
|
||||
sell_filter: bool = True
|
||||
sell_allowed_pairs: List[str] = field(default_factory=lambda: ["XAU/USD"])
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlatformConfig:
|
||||
@@ -237,12 +182,10 @@ class PlatformConfig:
|
||||
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
|
||||
symbol: str = XAUUSD
|
||||
display_name: str = "XAU/USD"
|
||||
pip_value: float = 0.10
|
||||
|
||||
primary_timeframe: Timeframe = Timeframe.H1
|
||||
confirmation_timeframes: List[Timeframe] = field(
|
||||
@@ -256,7 +199,7 @@ class PlatformConfig:
|
||||
refresh_interval: int = 300
|
||||
|
||||
scan_pairs: List[str] = field(
|
||||
default_factory=lambda: [EURUSD, GBPUSD, XAUUSD]
|
||||
default_factory=lambda: [XAUUSD]
|
||||
)
|
||||
scan_timeframes: List[Timeframe] = field(
|
||||
default_factory=lambda: [Timeframe.M5, Timeframe.M15, Timeframe.H1, Timeframe.H4]
|
||||
|
||||
Reference in New Issue
Block a user