feat: time-aware trade maturity classification
- Add _trade_maturity() helper: classifies trades by % of horizon elapsed (trop_tot <10%, debut 10-35%, mature 35-75%, fin_horizon >75%) - Fix horizon_days fallback chain in log_trade_entries (default 30→90) - journal.py: enrich each MTM trade with maturity dict + horizon_days - reasoning.py: portfolio report segments trades by maturity; GPT-4o draws lessons only from matures (≥35% elapsed), never from trop_tot - auto_cycle.py: 90d window, maturity-aware prompt with timing rules - JournalDeBord.tsx: maturity badge with emoji, label, progress bar and day counter (Xj / Yj Z%) replacing plain days_held column Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -394,7 +394,7 @@ function TradeMtmSection({ days }: { days: number }) {
|
||||
<th className="text-right px-3 py-2 font-medium">Date</th>
|
||||
<th className="text-right px-3 py-2 font-medium">Prix entrée</th>
|
||||
<th className="text-right px-3 py-2 font-medium">Prix actuel</th>
|
||||
<th className="text-right px-3 py-2 font-medium">J</th>
|
||||
<th className="text-right px-3 py-2 font-medium">Maturité</th>
|
||||
<th className="text-right px-3 py-2 font-medium">P&L th.</th>
|
||||
<th className="px-3 py-2 font-medium w-8"></th>
|
||||
</tr>
|
||||
@@ -451,8 +451,37 @@ function TradeMtmSection({ days }: { days: number }) {
|
||||
<td className="px-3 py-2 text-right font-mono text-slate-300 text-[11px]">
|
||||
{t.current_price != null ? t.current_price.toFixed(2) : '—'}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-right text-slate-600 text-[11px]">
|
||||
{t.days_held != null ? t.days_held : '—'}
|
||||
<td className="px-3 py-2 text-right">
|
||||
{t.maturity ? (
|
||||
<div className="flex flex-col items-end gap-0.5">
|
||||
<span className={clsx('text-[10px] font-semibold',
|
||||
t.maturity.status === 'trop_tot' ? 'text-slate-500' :
|
||||
t.maturity.status === 'debut' ? 'text-yellow-400' :
|
||||
t.maturity.status === 'mature' ? 'text-emerald-400' :
|
||||
'text-orange-400'
|
||||
)}>
|
||||
{t.maturity.emoji} {t.maturity.label}
|
||||
</span>
|
||||
<span className="text-[9px] text-slate-600 font-mono">
|
||||
{t.days_held ?? 0}j / {t.horizon_days ?? 90}j ({t.maturity.ratio_pct}%)
|
||||
</span>
|
||||
<div className="w-16 h-1 bg-slate-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={clsx('h-full rounded-full',
|
||||
t.maturity.status === 'trop_tot' ? 'bg-slate-600' :
|
||||
t.maturity.status === 'debut' ? 'bg-yellow-500' :
|
||||
t.maturity.status === 'mature' ? 'bg-emerald-500' :
|
||||
'bg-orange-500'
|
||||
)}
|
||||
style={{ width: `${Math.min(t.maturity.ratio_pct, 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<span className="text-slate-700 text-[11px]">
|
||||
{t.days_held != null ? `${t.days_held}j` : '—'}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-3 py-2 text-right">
|
||||
<PnlBadge pnl={t.pnl_pct} />
|
||||
|
||||
Reference in New Issue
Block a user