feat: wavelets

This commit is contained in:
OpenSquared
2026-07-14 16:23:18 +02:00
parent ce948f6b65
commit b693aca2dc
17 changed files with 2144 additions and 10 deletions

View File

@@ -1016,6 +1016,17 @@ def run_cycle_once(trigger: str = "auto") -> Dict[str, Any]:
except Exception as _ce:
logger.warning(f"[Cycle] Régime clustering failed (non-blocking): {_ce}")
# ── Step 5.7: Wavelet signal scan (watchlist instruments) ────────────
_wavelet_results: list = []
try:
from services.wavelet_signals import compute_and_save_wavelet_signals
_wavelet_results = compute_and_save_wavelet_signals(run_id)
summary["wavelet_signals_count"] = len(_wavelet_results)
logger.info(f"[Cycle {run_id[:16]}] Wavelet signals: {len(_wavelet_results)} detected")
except Exception as _we:
logger.warning(f"[Cycle] Wavelet signal scan failed (non-blocking): {_we}")
summary["wavelet_signals_count"] = 0
# ── Step 6: GPT-4o cycle commentary ──────────────────────────────────
logger.info(f"[Cycle {run_id[:16]}] Step 6: generating commentary")
commentary = _generate_cycle_commentary(
@@ -1046,6 +1057,7 @@ def run_cycle_once(trigger: str = "auto") -> Dict[str, Any]:
dominant_regime=dominant,
commentary=commentary,
status="completed",
wavelet_signals_count=summary.get("wavelet_signals_count", 0),
)
_current_status["last_run_at"] = datetime.utcnow().isoformat()
logger.info(f"[Cycle {run_id[:16]}] Completed — {added_count} new patterns, {len(scored)} scored")
@@ -1116,6 +1128,7 @@ def run_cycle_once(trigger: str = "auto") -> Dict[str, Any]:
portfolio_monitor=summary.get("portfolio_monitor"),
commentary=commentary,
options_assessment=_options_assessment,
wavelet_signals=_wavelet_results,
)
if _cycle_report:
from services.database import save_cycle_report
@@ -1352,6 +1365,7 @@ def _generate_cycle_report(
portfolio_monitor: Optional[Dict],
commentary: Optional[str],
options_assessment: Optional[Dict] = None,
wavelet_signals: Optional[List[Dict]] = None,
) -> Optional[Dict]:
"""
Build the full cycle report dict:
@@ -1599,6 +1613,8 @@ Réponds en JSON avec ce schéma EXACT:
# Risk
"portfolio_monitor": portfolio_monitor,
"risk_alerts": portfolio_monitor.get("alerts") if portfolio_monitor else None,
# Wavelet signals detected this cycle (watchlist scan, see services.wavelet_signals)
"wavelet_signals": wavelet_signals or [],
# Top scored patterns
"top_scored": [
{"name": s.get("geo_trigger"), "score": s.get("score"),