feat: simulation portfolio surveillance + patterns grid/filter UI

Portfolio Monitor (v4.4):
- New portfolio_risk.py service: concentration by asset_class, directional
  conflict detection (same underlying, opposite directions), overweight alerts
- AI agent (Step 7b) runs GPT-4o-mini after each cycle log: assessment +
  prioritized actions + rebalance suggestion, persisted in system_logs
- GET /api/journal/portfolio-risk — full risk breakdown + latest AI monitor reco
- POST /api/journal/trade-check — pre-entry conflict & concentration check
- asset_class column added to trade_entry_prices (auto-migration + populated at INSERT)
- Journal: new "Risque Sim." tab with concentration bars, conflict alerts,
  AI recommendations; red badge on tab when danger alerts exist

PatternEditor:
- Grid view default (2-3 cols responsive), list toggle
- Asset class filter chips (energy/metals/agri/equities/indices/forex/rates)
- Sort: Date (default) / Score IA / Prob.
- Period filter: Tout / 7j / 30j
- Result count badge when filters active

Doc: v4.3 → v4.4, updated Journal/PatternEditor/cycle steps/schema/glossary

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-19 15:49:46 +02:00
parent d34b4043fb
commit 58c3767a9d
8 changed files with 749 additions and 38 deletions

View File

@@ -218,6 +218,7 @@ def init_db():
("target_pct", "REAL"),
("stop_loss_pct", "REAL"),
("signal_threshold", "REAL"),
("asset_class", "TEXT"),
]:
try:
c.execute(f"ALTER TABLE trade_entry_prices ADD COLUMN {col} {definition}")
@@ -1049,18 +1050,24 @@ def log_trade_entries(run_id: str, scored_patterns: List[Dict[str, Any]], quotes
)
updated_count += 1
else:
_trade_asset_class = (
trade.get("asset_class") or
sp.get("asset_class") or
_orig.get("asset_class") or
""
)
conn.execute("""INSERT INTO trade_entry_prices
(run_id, pattern_id, pattern_name, underlying, strategy,
entry_price, entry_date, score_at_entry, latest_score,
expected_move_pct, horizon_days, ev_at_entry, ev_net,
trade_score, matched_profile, last_seen_at,
strike_guidance, expiry_days_at_entry)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", (
strike_guidance, expiry_days_at_entry, asset_class)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", (
run_id, pid, pattern_name, ticker_key, strategy,
entry_price, today, eff_score, eff_score,
exp_move, horizon, ev_gross, ev_net,
trade_score, matched, now_ts,
strike_guidance, expiry_days_entry,
strike_guidance, expiry_days_entry, _trade_asset_class,
))
inserted_count += 1
_log.info(f"[TradeLog] NEW trade: pattern='{pattern_name}' {underlying} {strategy} score={eff_score} gain={exp_move:.0f}% profile='{matched}' price={entry_price}")