Files
ForexBot2/config.py
T
harwinder 98daf71a52 Add web dashboard (Redis + FastAPI + WebSocket), scope XAU penalties
Signal daemon (signal_web.py): candle-boundary scanner mirroring
telegram_bot.py, publishes serialized SignalReport JSON to Redis.
Web API (web/app.py): thin FastAPI reader behind Apache, serves
/api/signals REST + /ws WebSocket from Redis pub/sub.
Frontend (web/static/index.html): 3-pair grid, color-coded signals,
indicator breakdown per timeframe, trade setup display.

Also: XAU-specific penalty scoping in signal_aggregator (softer
confidence penalties for gold, original strict values for forex),
pair-aware session filter routing XAU to its own blocked hours.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-14 23:15:37 -04:00

268 lines
8.7 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 = 0.5
@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://investinglive.com/feed/",
"https://www.fxstreet.com/rss",
])
@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.
"""
enabled: bool = True
rsi_entry_threshold: float = 45.0
tp_atr_multiplier: float = 0.9
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
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
@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])
# 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:
"""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"