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:
@@ -430,6 +430,9 @@ export default function Config() {
|
||||
const [cycleSimilarity, setCycleSimilarity] = useState(0.30)
|
||||
const [minEv, setMinEv] = useState(0.0)
|
||||
const [minScore, setMinScore] = useState(0)
|
||||
const [tradeBudget, setTradeBudget] = useState(5000)
|
||||
const [horizonMin, setHorizonMin] = useState(30)
|
||||
const [horizonMax, setHorizonMax] = useState(180)
|
||||
const [retentionDays, setRetentionDays] = useState(90)
|
||||
const [maturityThreshold, setMaturityThreshold] = useState(35)
|
||||
const [weekendEnabled, setWeekendEnabled] = useState(true)
|
||||
@@ -441,6 +444,9 @@ export default function Config() {
|
||||
setCycleSimilarity(cs.similarity_threshold ?? 0.30)
|
||||
setMinEv(cs.min_ev_threshold ?? 0.0)
|
||||
setMinScore(cs.min_score_threshold ?? 0)
|
||||
setTradeBudget(cs.trade_budget_eur ?? 5000)
|
||||
setHorizonMin(cs.preferred_horizon_min ?? 30)
|
||||
setHorizonMax(cs.preferred_horizon_max ?? 180)
|
||||
setRetentionDays(cs.journal_retention_days ?? 90)
|
||||
setMaturityThreshold(cs.maturity_threshold_pct ?? 35)
|
||||
setWeekendEnabled(cs.weekend_cycle_enabled ?? true)
|
||||
@@ -725,6 +731,63 @@ export default function Config() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Trade Parameters */}
|
||||
<div className="card">
|
||||
<h2 className="text-base font-bold text-white flex items-center gap-2 mb-1">
|
||||
<DollarSign className="w-4 h-4 text-emerald-400" /> Trade Parameters
|
||||
</h2>
|
||||
<p className="text-xs text-slate-500 mb-4">
|
||||
Passed into every AI cycle — controls capital sizing and filters out patterns outside your investment horizon.
|
||||
</p>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
<div>
|
||||
<label className="text-xs text-slate-500 mb-2 block">
|
||||
Simulation budget: <span className="text-emerald-400 font-mono font-bold">€{tradeBudget.toLocaleString()}</span>
|
||||
</label>
|
||||
<input type="range" min="500" max="50000" step="500"
|
||||
value={tradeBudget}
|
||||
onChange={e => setTradeBudget(parseInt(e.target.value))}
|
||||
className="w-full accent-emerald-500" />
|
||||
<div className="flex justify-between text-[10px] text-slate-600 mt-1">
|
||||
<span>€500</span><span>€50,000</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-500 mt-1">
|
||||
Max per position: <span className="text-slate-300 font-mono">€{Math.round(tradeBudget * 0.25).toLocaleString()}</span> (25%)
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs text-slate-500 mb-2 block">
|
||||
Min horizon: <span className="text-blue-400 font-mono font-bold">{horizonMin}d</span>
|
||||
</label>
|
||||
<input type="range" min="1" max="90" step="1"
|
||||
value={horizonMin}
|
||||
onChange={e => setHorizonMin(Math.min(parseInt(e.target.value), horizonMax - 5))}
|
||||
className="w-full accent-blue-500" />
|
||||
<div className="flex justify-between text-[10px] text-slate-600 mt-1">
|
||||
<span>1d</span><span>90d</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-500 mt-1">Patterns shorter than {horizonMin}d penalized in R/R</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs text-slate-500 mb-2 block">
|
||||
Max horizon: <span className="text-blue-400 font-mono font-bold">{horizonMax}d</span>
|
||||
</label>
|
||||
<input type="range" min="30" max="365" step="5"
|
||||
value={horizonMax}
|
||||
onChange={e => setHorizonMax(Math.max(parseInt(e.target.value), horizonMin + 5))}
|
||||
className="w-full accent-blue-500" />
|
||||
<div className="flex justify-between text-[10px] text-slate-600 mt-1">
|
||||
<span>30d</span><span>365d</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-500 mt-1">Patterns longer than {horizonMax}d penalized in R/R</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 p-3 rounded bg-emerald-900/10 border border-emerald-700/20 text-xs text-emerald-300">
|
||||
Active mandate: budget <span className="font-mono">€{tradeBudget.toLocaleString()}</span> · horizon{' '}
|
||||
<span className="font-mono">{horizonMin}–{horizonMax}d</span> · AI will size + filter suggestions accordingly
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Auto-Cycle settings */}
|
||||
<div className="card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
@@ -901,6 +964,9 @@ export default function Config() {
|
||||
similarity_threshold: cycleSimilarity,
|
||||
min_ev_threshold: minEv,
|
||||
min_score_threshold: minScore,
|
||||
trade_budget_eur: tradeBudget,
|
||||
preferred_horizon_min: horizonMin,
|
||||
preferred_horizon_max: horizonMax,
|
||||
journal_retention_days: retentionDays,
|
||||
maturity_threshold_pct: maturityThreshold,
|
||||
weekend_cycle_enabled: weekendEnabled,
|
||||
|
||||
Reference in New Issue
Block a user