feat: trade mandate (budget + horizon) wired end-to-end

- database.py: add trade_budget_eur / preferred_horizon_min/max config
  defaults and include them in cycle config migrations
- auto_cycle.py: read trade params from config and inject into cycle_meta
- ai_analyzer.py: inject INVESTOR TRADE MANDATE block into scoring and
  suggestion prompts so GPT-4o penalises horizon mismatches and sizes
  within the capital cap
- Config.tsx: Trade Parameters card with budget + horizon sliders and live
  mandate summary
- TradeIdeas.tsx: horizon filter pills (< 1M / 1-3M / 3-6M / > 6M) and
  budget/horizon indicator pulled from saved config
- useApi.ts: extend useUpdateCycleConfig type with new config fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 17:24:38 +02:00
parent 9b98594c07
commit a68a08d9af
6 changed files with 151 additions and 6 deletions

View File

@@ -619,10 +619,25 @@ Scoring instructions:
_portfolio_sc_section = f"\n{portfolio_context_block}\n" if portfolio_context_block else ""
_inst_sc_section = f"\n{institutional_block}\n" if institutional_block else ""
# Trade mandate block from cycle_meta
_budget = _cm.get("trade_budget_eur", 5000)
_h_min = _cm.get("preferred_horizon_min", 30)
_h_max = _cm.get("preferred_horizon_max", 180)
_max_pos = round(_budget * 0.25)
_trade_mandate_sc = (
f"\n## INVESTOR TRADE MANDATE\n"
f"- Available capital budget: €{_budget:,.0f}\n"
f"- Preferred horizon: {_h_min}{_h_max} days\n"
f"- Max capital per position: €{_max_pos:,.0f} (25% of budget)\n"
f"⚠️ Patterns whose horizon_days is outside [{_h_min}, {_h_max}] should receive a penalty"
f" in the R/R pillar (poor timing fit). Size trade suggestions within the budget cap.\n"
)
user = f"""GLOBAL CONTEXT:
- Geopolitical risk score: {geo_score.get('score', 50)}/100 ({geo_score.get('level', 'medium')})
- Top risks: {geo_score.get('top_risks', [])}
{temporal_section_sc}
{_trade_mandate_sc}
{macro_section}
{_fred_sc_section}
{_pd_sc_section}
@@ -1411,7 +1426,20 @@ Additional rules:
portfolio_section = f"\n{portfolio_context_block}\n" if portfolio_context_block else ""
convergence_section = f"\n{convergence_block}\n" if convergence_block else ""
_sg_budget = _cycle_meta.get("trade_budget_eur", 5000)
_sg_h_min = _cycle_meta.get("preferred_horizon_min", 30)
_sg_h_max = _cycle_meta.get("preferred_horizon_max", 180)
_sg_max_pos = round(_sg_budget * 0.25)
_suggest_mandate = (
f"\n## INVESTOR TRADE MANDATE\n"
f"- Available capital budget: €{_sg_budget:,.0f} | Max per position: €{_sg_max_pos:,.0f}\n"
f"- Target horizon: {_sg_h_min}{_sg_h_max} days\n"
f"⚠️ Only propose patterns whose horizon_days is within [{_sg_h_min}, {_sg_h_max}]."
f" Patterns outside this window will be rejected. Size each trade so capital ≤ €{_sg_max_pos:,.0f}.\n"
)
user = f"""You are a senior geopolitical and financial strategist, expert in options.
{_suggest_mandate}
{macro_block}{geo_block}{lessons_block}{reliability_block}{iv_block}
{temporal_news_block}
## Market prices (D-1 change)