Consolidate setup numbers; clearer staleness message
- Overview Top Setups shows the primary target's probability (concrete,
distance-calibrated) instead of the overlapping confidence number. The
stale 100% confidences were leftovers from the old model and self-heal
on rescan; confidence stays in the detail view + gate.
- Each metric now has one home: composite = ranking, target probability =
actionability, confidence = direction conviction.
- Staleness message states the real basis (% of entry->target distance
already covered), not the raw % from entry, so narrow setups read
correctly ("67% of the move is gone").
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,14 +18,17 @@ function entryDrift(setup: TradeSetup, currentPrice?: number) {
|
||||
if (currentPrice == null || !setup.entry_price) return null;
|
||||
const pct = ((currentPrice - setup.entry_price) / setup.entry_price) * 100;
|
||||
const towardTarget = setup.direction === 'long' ? currentPrice >= setup.entry_price : currentPrice <= setup.entry_price;
|
||||
// Past the stop entirely = invalidated; moved >1/3 of the way to target = stale
|
||||
// Judge staleness by how much of the entry→target distance is already gone,
|
||||
// not the raw % move — an 8%-wide setup is "used up" far faster than a 40% one.
|
||||
const span = Math.abs(setup.target - setup.entry_price);
|
||||
const moved = Math.abs(currentPrice - setup.entry_price);
|
||||
const progressPct = span > 0 ? (moved / span) * 100 : 0;
|
||||
const beyondStop = setup.direction === 'long' ? currentPrice <= setup.stop_loss : currentPrice >= setup.stop_loss;
|
||||
let status: 'fresh' | 'stale' | 'invalidated' = 'fresh';
|
||||
if (beyondStop) status = 'invalidated';
|
||||
else if (span > 0 && moved / span > 0.33) status = 'stale';
|
||||
return { pct, towardTarget, status };
|
||||
else if (towardTarget && progressPct > 33) status = 'stale';
|
||||
else if (!towardTarget && progressPct > 33) status = 'stale';
|
||||
return { pct, progressPct, towardTarget, status };
|
||||
}
|
||||
|
||||
function riskClass(risk: TradeSetup['risk_level']) {
|
||||
@@ -115,7 +118,9 @@ function SetupCard({ setup, action, currentPrice }: { setup?: TradeSetup; action
|
||||
)}
|
||||
{drift && drift.status === 'stale' && (
|
||||
<p className="text-[11px] text-amber-400">
|
||||
⚠ Price has moved {drift.pct >= 0 ? '+' : ''}{drift.pct.toFixed(1)}% from entry{drift.towardTarget ? ' toward target' : ' against the setup'} — entry may be stale.
|
||||
{drift.towardTarget
|
||||
? `⚠ ${drift.progressPct.toFixed(0)}% of the entry→target move is already gone (${drift.pct >= 0 ? '+' : ''}${drift.pct.toFixed(1)}% from entry) — little reward left.`
|
||||
: `⚠ Price has moved ${Math.abs(drift.pct).toFixed(1)}% against the setup (toward the stop) — entry may be stale.`}
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user