from datetime import datetime, timedelta, timezone from utils.indicators import atr class Filters: def __init__(self, cfg: dict): self.cfg = cfg self.news = [(datetime.fromisoformat(d), int(b), int(a)) for d, b, a in cfg.get("news_blackouts", [])] def spread_ok(self, symbol, info, tick) -> bool: lim = self.cfg["max_spread_points"] return (tick.ask - tick.bid) / info.point <= lim.get(symbol, lim["default"]) def session_ok(self) -> bool: h = datetime.now(timezone.utc).hour return any(a <= h < b for a, b in self.cfg["sessions_utc"]) def news_ok(self) -> bool: now = datetime.now(timezone.utc).replace(tzinfo=None) return not any(t - timedelta(minutes=b) <= now <= t + timedelta(minutes=a) for t, b, a in self.news) def regime_ok(self, df) -> bool: r = self.cfg.get("regime", {}) if not r.get("enabled"): return True a = atr(df, 14) return a.iloc[-1] / a.iloc[-100:].mean() >= r["min_atr_ratio"] def all_ok(self, symbol, info, tick, df): if not self.session_ok(): return False, "hors session" if not self.news_ok(): return False, "fenêtre news" if not self.spread_ok(symbol, info, tick): return False, "spread élevé" if not self.regime_ok(df): return False, "volatilité trop faible" return True, ""