diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx index b2eebfa..7d2b916 100644 --- a/frontend/src/pages/DashboardPage.tsx +++ b/frontend/src/pages/DashboardPage.tsx @@ -13,7 +13,6 @@ import { OpenTradesPanel } from '../components/dashboard/OpenTradesPanel'; import { SkeletonCard, SkeletonTable } from '../components/ui/Skeleton'; import { formatPrice } from '../lib/format'; import { tradePnl } from '../lib/paperTrade'; -import { recommendationActionLabel } from '../lib/recommendation'; import { qualifiesSetup, activationSummary, primaryTargetProbability } from '../lib/qualification'; import type { TradeSetup } from '../lib/types'; @@ -60,6 +59,19 @@ function DirectionTag({ direction }: { direction: string }) { ); } +function convictionLabel(action: TradeSetup['recommended_action']): string { + if (!action || action === 'NEUTRAL') return '—'; + if (action.endsWith('_HIGH')) return 'High'; + if (action.endsWith('_MODERATE')) return 'Moderate'; + return '—'; +} + +function convictionClass(action: TradeSetup['recommended_action']): string { + if (action?.endsWith('_HIGH')) return 'text-emerald-300'; + if (action?.endsWith('_MODERATE')) return 'text-amber-300'; + return 'text-gray-400'; +} + export default function DashboardPage() { const trades = useTrades(); const watchlist = useWatchlist(); @@ -200,9 +212,9 @@ export default function DashboardPage() {
- {trades.isLoading && } + {trades.isLoading && } {trades.isError && Failed to load setups} {trades.data && topSetups.length === 0 && ( No qualified actionable setups right now. @@ -214,17 +226,17 @@ export default function DashboardPage() { Ticker Dir - Entry + Current / Target R:R Target Prob - Prod. Rank Residual - Action + Conviction {topSetups.map((setup, i) => { const isTopPick = i === 0; + const displayedPrice = setup.current_price ?? setup.entry_price; return ( - {formatPrice(setup.entry_price)} + +
{formatPrice(displayedPrice)}
+
target {formatPrice(setup.target)}
+ {setup.rr_ratio.toFixed(1)}:1 {(() => { @@ -258,24 +273,18 @@ export default function DashboardPage() { return p != null ? `${Math.round(p)}%` : '—'; })()} - - {setup.strategy_rank != null ? `${Math.round(setup.strategy_rank)}%ile` : '—'} - {setup.momentum_percentile != null ? `${Math.round(setup.momentum_percentile)}%ile` : '—'} - - {recommendationActionLabel(setup.recommended_action)} + + {convictionLabel(setup.recommended_action)} ); })} -
- - Production rank = 80% residual momentum + 20% realized volatility; residual still gates qualification. - +
All setups →