fix: filtres Journal de Bord — direction + asset_class tous onglets

Direction (Ouvert) : t.direction n'existe pas dans trade_entry_prices → utilisait
undefined, excluait tout. Remplacé par _isBearishStr(t.strategy) comme Fermés.

Asset class (Ouvert, Fermés, Non loggés) : l'IA retournait parfois "commodities",
"currencies", "fx", "equity" au lieu des clés canoniques. Double correction :
- Frontend : _normalizeAssetClass() mappe les variantes → energy|metals|agriculture|
  indices|equities|forex dans les 3 sections filtrées
- Backend database.py : _normalize_asset_class() appliqué à l'INSERT dans
  trade_entry_prices et skipped_trades (nouveaux trades normalisés au stockage)
- Prompt ai_analyzer.py : suggested_trades[].asset_class contraint à l'enum explicite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-20 18:44:14 +02:00
parent a21699805b
commit 7c0ff703b0
3 changed files with 43 additions and 9 deletions

View File

@@ -1173,14 +1173,14 @@ Retourne UNIQUEMENT ce JSON:
"strategy": "<Long Call|Long Put|Bull Call Spread|Bear Put Spread|Long Straddle|Iron Condor|Short Strangle|Cash-Secured Put|Covered Call — respecter règles IVR>",
"underlying": "<ticker Yahoo Finance>",
"rationale": "<pourquoi ce trade dans ce contexte macro+géo+vol>",
"asset_class": "<classe>",
"asset_class": "<energy|metals|agriculture|indices|equities|forex>",
"expected_move_pct": <float, RENDEMENT OPTION en % pour CE trade si thèse confirmée. Long Call: 80-250%, Spread: 40-120%, Straddle: 60-180%.>
}},
{{
"strategy": "<autre stratégie respectant les règles IVR>",
"underlying": "<ticker Yahoo Finance>",
"rationale": "<rationale>",
"asset_class": "<classe>",
"asset_class": "<energy|metals|agriculture|indices|equities|forex>",
"expected_move_pct": <float, rendement option attendu en % pour ce trade spécifique>
}}
]

View File

@@ -1027,6 +1027,26 @@ def _normalize_yf_ticker(ticker: str) -> str:
return t
def _normalize_asset_class(cls: str) -> str:
"""Map AI-returned asset_class variants to canonical keys used in the UI."""
if not cls:
return ""
c = cls.lower().strip()
if any(k in c for k in ("energy", "oil", "gas", "petrol", "brent", "wti")):
return "energy"
if any(k in c for k in ("metal", "gold", "silver", "copper", "mining", "precious")):
return "metals"
if any(k in c for k in ("agri", "grain", "corn", "wheat", "soy", "crop", "coton", "coffee", "cocoa")):
return "agriculture"
if any(k in c for k in ("index", "indic", "indices", "spx", "nasdaq", "dow", "s&p", "russell", "cac", "dax")):
return "indices"
if any(k in c for k in ("equit", "stock", "action", "share", "sector", "xle", "xlf", "xlk")):
return "equities"
if any(k in c for k in ("forex", "currency", "fx", "devise", "change", "eur", "usd", "jpy", "dxy")):
return "forex"
return c
def log_trade_entries(run_id: str, scored_patterns: List[Dict[str, Any]], quotes: Dict[str, Any]):
"""
For each scored pattern's trade_rankings, record entry price if the trade
@@ -1191,7 +1211,7 @@ def log_trade_entries(run_id: str, scored_patterns: List[Dict[str, Any]], quotes
)
updated_count += 1
else:
_trade_asset_class = (
_trade_asset_class = _normalize_asset_class(
trade.get("asset_class") or
sp.get("asset_class") or
_orig.get("asset_class") or
@@ -1387,7 +1407,7 @@ def log_skipped_trade(run_id: str, pattern_id: str, pattern_name: str,
expected_move_pct, skip_reason, skip_detail, asset_class)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(run_id, pattern_id, pattern_name, underlying, strategy, score,
expected_move_pct, skip_reason, skip_detail, asset_class)
expected_move_pct, skip_reason, skip_detail, _normalize_asset_class(asset_class))
)
conn.commit()
conn.close()