feat: 50-signal macro engine — vol surface, sectors, EM, carry, long bonds
data_fetcher.py - MACRO_GAUGE_CONFIG: 15 → 29 tickers (+silver, vvix, skew, ovx, gvz, usdjpy, xlk, xlf, xlp, xlu, eem, emb, fxi, tlt) - 5 new derived metrics: silver_gold_ratio, xlk_xlp_momentum, xlf_spx_ratio, eem_spx_ratio, vol_surface_regime (composite classification) - ThreadPoolExecutor max_workers raised to 20 - score_macro_scenarios: +15 new variables; each of 8 scenarios enriched with vol-surface (SKEW, VVIX), sector rotation (XLK, XLF, XLP, XLU), EM/carry (EEM, EMB, USDJPY), long bonds (TLT), silver signals ai_analyzer.py - macro_ctx: 5 → 21 fields per pattern (vol surface, sectors, EM, carry, long bonds, silver/gold ratio — all with interpretation comments) - macro_section in scoring prompt: describes surface de vol regime, sector rotation, global/carry signals with explicit GPT instructions for pilier 3e - DEFAULT_ANALYSIS_TEMPLATE: pilier 3e expanded with SKEW/VVIX/OVX/GVZ guidance SIGNALS_FUTURES.md: reference document listing 30+ signals not yet available (FRED, CFTC COT, EIA, Baltic Dry, LME, credit spreads, hedge fund positioning, central bank balance sheets) with implementation priority and cost estimate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -286,7 +286,13 @@ PILIER 3 — SIGNAUX DE PRIX (35 pts max)
|
||||
3b. Énergie & Matières prem. (0-7): or, pétrole, gaz, cuivre, blé — direction et momentum
|
||||
3c. Forex (0-7): USD index, EUR/USD, paires émergentes — cohérence avec pattern
|
||||
3d. Actions & Indices (0-7): SPX, NDX, rotation sectorielle, breadth, sentiment
|
||||
3e. Volatilité (VIX/IV) (0-7): régime de vol, coût options, skew — favorable à la stratégie ?
|
||||
3e. Volatilité & Surface de vol (0-7):
|
||||
- Régime VIX (niveau absolu et tendance)
|
||||
- SKEW Index: si >135 → queues chères → PRÉFÉRER spreads (budget = max loss limité)
|
||||
si <115 → vol bon marché → envisager straddles/strangles si catalyseur binaire
|
||||
- VVIX: si >100 → straddles/strangles trop chers → préférer directionnels
|
||||
- OVX (>40) / GVZ (>22): vol sectorielle élevée sur le sous-jacent → primes gonflées, spreads
|
||||
- Régime surface: contango_calm (idéal vendre vol) vs backwardation_panic (primes explosées)
|
||||
|
||||
PILIER 4 — RISQUE / RÉCOMPENSE (15 pts max)
|
||||
4a. Asymétrie R/R (0-10): ratio gain potentiel / prime payée / perte max pour ~1000€
|
||||
@@ -419,11 +425,42 @@ def score_patterns_with_context(
|
||||
"dominant_scenario": dominant,
|
||||
"scenario_scores": scenarios.get("scores", {}),
|
||||
"asset_class_bias": bias_for_class,
|
||||
# ── Signaux historiques (phase 1) ─────────────────────────────
|
||||
"vix": gauges.get("vix", {}).get("value"),
|
||||
"yield_slope_pct": gauges.get("slope_10y3m", {}).get("value"),
|
||||
"gold_copper_ratio": gauges.get("gold_copper_ratio", {}).get("value"),
|
||||
"brent_1d_pct": gauges.get("brent", {}).get("change_pct"),
|
||||
"spx_vs_200d_pct": gauges.get("spx_vs_200d", {}).get("value"),
|
||||
# ── Surface de volatilité (phase 2) ──────────────────────────
|
||||
# SKEW >135 = queues chères → spreads; <115 = vol bon marché → straddles
|
||||
"skew_index": gauges.get("skew", {}).get("value"),
|
||||
# VVIX >100 = straddles/strangles trop chers → préférer directionnels
|
||||
"vvix": gauges.get("vvix", {}).get("value"),
|
||||
# Vol sectorielle spécifique au sous-jacent
|
||||
"oil_vol_ovx": gauges.get("ovx", {}).get("value"),
|
||||
"gold_vol_gvz": gauges.get("gvz", {}).get("value"),
|
||||
# Régime composite: contango_calm|normal|tail_risk_elevated|backwardation_panic|complacency_hedged
|
||||
"vol_surface_regime": gauges.get("vol_surface_regime", {}).get("note"),
|
||||
# ── Rotation sectorielle (phase 2) ────────────────────────────
|
||||
# Positif = tech > défensifs = risk-on; négatif = rotation défensive
|
||||
"tech_vs_staples_pct": gauges.get("xlk_xlp_momentum", {}).get("value"),
|
||||
# Négatif = banques < marché = stress économique anticipé
|
||||
"financials_vs_spx_pct": gauges.get("xlf_spx_ratio", {}).get("value"),
|
||||
# ── Global / Marchés émergents (phase 2) ─────────────────────
|
||||
"em_equity_1d_pct": gauges.get("eem", {}).get("change_pct"),
|
||||
"em_bonds_1d_pct": gauges.get("emb", {}).get("change_pct"),
|
||||
"china_equity_1d_pct": gauges.get("fxi", {}).get("change_pct"),
|
||||
# Ratio EM vs SPX: positif = croissance globale; négatif = fuite vers US
|
||||
"em_vs_us_divergence_pct": gauges.get("eem_spx_ratio", {}).get("value"),
|
||||
# ── Carry / Risk-off (phase 2) ────────────────────────────────
|
||||
# Négatif = JPY s'apprécie = carry unwind = risk-off global
|
||||
"usdjpy_1d_pct": gauges.get("usdjpy", {}).get("change_pct"),
|
||||
# ── Long bonds / Qualité (phase 2) ────────────────────────────
|
||||
# Positif = flight to quality = risk-off; négatif = taux longs remontent
|
||||
"long_bond_tlt_1d_pct": gauges.get("tlt", {}).get("change_pct"),
|
||||
# ── Métaux (phase 2) ──────────────────────────────────────────
|
||||
# Ratio Ag/Au: >0.016 = argent > or = risk-on industriel; <0.012 = defensive metals
|
||||
"silver_gold_ratio": gauges.get("silver_gold_ratio", {}).get("value"),
|
||||
}
|
||||
|
||||
pattern_blocks.append({
|
||||
@@ -451,17 +488,50 @@ def score_patterns_with_context(
|
||||
macro_section = ""
|
||||
if macro_regime:
|
||||
sc = macro_regime.get("scenarios", {})
|
||||
gauges_g = macro_regime.get("gauges", {})
|
||||
dom = sc.get("dominant", "incertain")
|
||||
sc_scores = sc.get("scores", {})
|
||||
# Extract key new signals for global macro summary
|
||||
_skew = gauges_g.get("skew", {}).get("value")
|
||||
_vvix = gauges_g.get("vvix", {}).get("value")
|
||||
_ovx = gauges_g.get("ovx", {}).get("value")
|
||||
_vol_r = gauges_g.get("vol_surface_regime", {}).get("note", "normal")
|
||||
_tech_st = gauges_g.get("xlk_xlp_momentum", {}).get("value")
|
||||
_xlf_spx = gauges_g.get("xlf_spx_ratio", {}).get("value")
|
||||
_eem_c = gauges_g.get("eem", {}).get("change_pct")
|
||||
_usdjpy_c = gauges_g.get("usdjpy", {}).get("change_pct")
|
||||
_tlt_c = gauges_g.get("tlt", {}).get("change_pct")
|
||||
_sgr = gauges_g.get("silver_gold_ratio", {}).get("value")
|
||||
|
||||
def _fmt(v, unit="", decimals=1):
|
||||
return f"{v:.{decimals}f}{unit}" if v is not None else "n/d"
|
||||
|
||||
macro_section = f"""
|
||||
RÉGIME MACRO ACTUEL (30 compteurs agrégés):
|
||||
RÉGIME MACRO ACTUEL (50 compteurs — 29 tickers + 9 métriques dérivées):
|
||||
- Scénario dominant: {dom.upper()} | Scores: {json.dumps(sc_scores, ensure_ascii=False)}
|
||||
- Instruction: Intègre ce régime dans les piliers prix (3a taux, 3b énergie, 3d indices, 3e VIX).
|
||||
Chaque pattern reçoit un champ "macro_regime.asset_class_bias" indiquant la compatibilité
|
||||
(bullish+/bullish/neutral/bearish/bearish+/defensive) de sa classe d'actif avec le scénario dominant.
|
||||
→ "bullish+" = conditions très favorables pour ce pattern → majore 3b ou 3d selon la classe
|
||||
→ "bearish" ou "bearish+" = conditions défavorables → minore 3b ou 3d
|
||||
Indique dans "summary": [GOLDILOCKS|STAGFLATION|RÉCESSION|DÉSINFLATION|CRISE] + [SUPPORTING|NEUTRAL|CONTRA]
|
||||
|
||||
SURFACE DE VOLATILITÉ (pilier 3e — impact direct stratégie options):
|
||||
- SKEW Index: {_fmt(_skew, '', 0)} | Régime vol: {_vol_r} | VVIX: {_fmt(_vvix, '', 0)} | OVX: {_fmt(_ovx, '', 0)}
|
||||
→ SKEW >135 = queues chères → SPREADS (pas de straddles). VVIX >100 = primes gonflées → directionnels.
|
||||
→ {_vol_r} = {"contango calme: idéal spreads bon marché" if _vol_r == "contango_calm" else "backwardation/panique: options très chères, primes à vendre" if _vol_r == "backwardation_panic" else "tail risk élevé: protection queues = faveur spreads définis" if _vol_r == "tail_risk_elevated" else "environnement normal"}
|
||||
|
||||
ROTATION SECTORIELLE & RISQUE (pilier 3d + 3e):
|
||||
- Tech vs Défensifs (XLK-XLP): {_fmt(_tech_st, '%pts')} | Financières vs S&P: {_fmt(_xlf_spx, '%pts')}
|
||||
→ {"Risk-on sectoriel fort" if _tech_st and _tech_st > 0.5 else "Rotation défensive ⚠️" if _tech_st and _tech_st < -0.5 else "Neutre sectoriel"}
|
||||
→ {"Banques saines = pas de récession" if _xlf_spx and _xlf_spx > 0.3 else "Stress bancaire anticipé ⚠️" if _xlf_spx and _xlf_spx < -0.3 else ""}
|
||||
|
||||
GLOBAL / CARRY / QUALITÉ (pilier 3a + 3d):
|
||||
- EM Actions J+1: {_fmt(_eem_c, '%')} | USD/JPY J+1: {_fmt(_usdjpy_c, '%')} | TLT (20Y bonds) J+1: {_fmt(_tlt_c, '%')}
|
||||
- Ratio Ag/Or: {_fmt(_sgr, '', 5)}
|
||||
→ {"EM surperforme = croissance globale" if _eem_c and _eem_c > 0.5 else "EM stress = fuite vers US ⚠️" if _eem_c and _eem_c < -1.0 else ""}
|
||||
→ {"JPY s'apprécie = carry unwind = risk-off ⚠️" if _usdjpy_c and _usdjpy_c < -0.8 else "JPY faible = risk-on carry actif" if _usdjpy_c and _usdjpy_c > 0.5 else ""}
|
||||
→ {"TLT monte = flight to quality = bonds longs demandés" if _tlt_c and _tlt_c > 0.3 else "TLT baisse = taux longs remontent = inflation/risk-on" if _tlt_c and _tlt_c < -0.3 else ""}
|
||||
|
||||
Instructions de notation:
|
||||
- Intègre le régime dans 3a (taux: slope+TLT), 3b (énergie+OVX), 3d (indices+XLF+EM), 3e (SKEW+VVIX+régime)
|
||||
- "macro_regime.asset_class_bias" dans chaque pattern → majore/minore 3b ou 3d
|
||||
- "macro_regime.skew_index" + "vol_surface_regime" → influence directe sur le choix de stratégie dans "recommended_trade"
|
||||
- Indique dans "summary": [GOLDILOCKS|STAGFLATION|RÉCESSION|DÉSINFLATION|CRISE] + [SUPPORTING|NEUTRAL|CONTRA]
|
||||
"""
|
||||
|
||||
user = f"""CONTEXTE GLOBAL:
|
||||
|
||||
Reference in New Issue
Block a user