fix: weekend-aware cycle — IVGate, pandas MultiIndex, ticker aliases, day/session in AI prompt
- auto_cycle.py: detect weekend/market session, build cycle_meta with day_of_week/is_weekend/market_note; IVGate skips iv_rank>=99 on weekends to avoid artificial weekend option premium cascade; inject portfolio context (open trades + price moves + concentration) before AI scoring; pass portfolio_context_block + run_id to both AI scorer and suggester - ai_analyzer.py: _build_temporal_news_block injects market session banner (WEEKEND warning, pre/after-market note, or open session label) so AI knows markets are closed and defers execution to Monday - iv_engine.py: add WHEAT/EUR/USD ticker aliases; skip saving IV snapshots on weekends to protect history; resolve aliases before slash-format conversion in _resolve_ticker - technical_indicators.py: fix pandas MultiIndex from yfinance>=0.2 (droplevel+squeeze); use period proportional to lookback instead of fixed period=1d - database.py: asset_class ticker-based fallback (_asset_class_from_ticker); one-time backfill migration for all NULL asset_class rows; ai_call_logs table + save/get helpers; normalize_ticker public function Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -970,9 +970,13 @@ def partition_news_by_age(news: List[Dict], delta_minutes: float) -> Dict[str, L
|
||||
|
||||
|
||||
def _build_temporal_news_block(partitioned: Dict[str, List], cycle_meta: Dict) -> str:
|
||||
"""Build the news section of the IA prompt with temporal framing."""
|
||||
"""Build the news section of the IA prompt with temporal framing + market session context."""
|
||||
delta_min = cycle_meta.get("delta_minutes", 180)
|
||||
calib = cycle_meta.get("calibration_label", "")
|
||||
day_of_week = cycle_meta.get("day_of_week", "")
|
||||
is_weekend = cycle_meta.get("is_weekend", False)
|
||||
market_session = cycle_meta.get("market_session", "")
|
||||
market_note = cycle_meta.get("market_note", "")
|
||||
|
||||
def _fmt_news(articles: List[Dict], limit: int = 6) -> str:
|
||||
lines = []
|
||||
@@ -989,7 +993,27 @@ def _build_temporal_news_block(partitioned: Dict[str, List], cycle_meta: Dict) -
|
||||
recent = partitioned.get("recent_24h", [])
|
||||
older = partitioned.get("older", [])
|
||||
|
||||
# Market session banner
|
||||
if is_weekend:
|
||||
session_banner = (
|
||||
f"\n## 📅 STATUT DES MARCHÉS — {day_of_week.upper()}\n"
|
||||
f"⚠️ WEEKEND — Marchés FERMÉS. {market_note}\n"
|
||||
"→ Les patterns peuvent être identifiés mais NE PEUVENT PAS être exécutés avant lundi matin.\n"
|
||||
"→ Utilise ce cycle pour préparer des ordres à cours limité pour l'ouverture de lundi.\n"
|
||||
"→ Les prix affichés sont ceux de la CLÔTURE DE VENDREDI — ne pas interpréter les mouvements intraday.\n"
|
||||
"→ La volatilité implicite des options est artificiellement élevée ce weekend (prime weekend des market makers) — les IVR affichés sont surestimés.\n"
|
||||
)
|
||||
elif market_session in ("pre_market", "after_hours", "overnight"):
|
||||
session_banner = (
|
||||
f"\n## 📅 STATUT DES MARCHÉS — {day_of_week} {market_session.upper()}\n"
|
||||
f"{market_note}\n"
|
||||
"→ Les prix peuvent ne pas refléter la session régulière — liquidité réduite.\n"
|
||||
)
|
||||
else:
|
||||
session_banner = f"\n## 📅 STATUT DES MARCHÉS — {day_of_week} | {market_session.upper()}\n{market_note}\n" if day_of_week else ""
|
||||
|
||||
block = f"""
|
||||
{session_banner}
|
||||
## ⏱ CONTEXTE TEMPOREL DU CYCLE
|
||||
- Dernier cycle il y a : {delta_min:.0f} minutes
|
||||
- Calibration : {calib}
|
||||
|
||||
Reference in New Issue
Block a user