'use client' import { useState, useEffect } from 'react' import { getPerformance, getTrades } from '@/lib/api' import type { BotPerformance, BotTrade } from '@/types' function fmtMoney(n: number) { if (n == null || isNaN(n)) return '—' const abs = Math.abs(n) const s = abs.toLocaleString('en-US', { maximumFractionDigits: 0 }) if (n < 0) return '-$' + s if (n > 0) return '+$' + s return '$' + s } function fmtHold(s: number) { if (s < 60) return s + 's' const m = Math.floor(s / 60) if (m < 60) return m + 'm' return Math.floor(m / 60) + 'h ' + (m % 60) + 'm' } export default function AnalyticsPage() { const [perf, setPerf] = useState(null) const [trades, setTrades] = useState([]) const [period, setPeriod] = useState('30d') useEffect(() => { Promise.all([ getPerformance().catch(() => null), getTrades(200, 1).catch(() => []), ]).then(([p, t]) => { setPerf(p) setTrades(t) }) }, []) const winRate = perf ? perf.win_rate * 100 : 0 const bestTrade = trades.length ? Math.max(...trades.map(t => t.pnl_usd)) : 0 const worstTrade = trades.length ? Math.min(...trades.map(t => t.pnl_usd)) : 0 const avgTrade = trades.length ? trades.reduce((s, t) => s + t.pnl_usd, 0) / trades.length : 0 const metrics = [ { k: 'Max drawdown', v: perf ? perf.max_drawdown_pct.toFixed(1) + '%' : '—', sub: 'Worst peak-to-trough', down: true }, { k: 'Total trades', v: String(perf?.total_trades ?? '—'), sub: 'Bot executions' }, { k: 'Avg hold time', v: perf ? fmtHold(perf.avg_hold_seconds) : '—', sub: 'Per trade' }, { k: 'Avg trade P&L', v: fmtMoney(avgTrade), sub: 'Mean per trade', up: avgTrade > 0 }, { k: 'Best trade', v: fmtMoney(bestTrade), sub: 'Largest single win', up: true }, { k: 'Worst trade', v: fmtMoney(worstTrade), sub: 'Largest single loss', down: true }, ] return (

Analytics

Deep dive into {period} of signals and trades.

{['7d', '30d', '90d', 'All'].map(p => ( ))}
{/* Summary card */}
Performance · {period}
{perf ? fmtMoney(perf.net_pnl_usd) : '—'}
= 0.5 ? 'up' : 'down'}`}>{winRate.toFixed(1)}% win rate {perf?.total_trades ?? 0} trades
{/* Metric grid */}
{metrics.map(m => (
{m.k}
{m.v}
{m.sub}
))}
{/* No data message */} {!perf && !trades.length && (

No trade data yet. The bot will populate analytics once it starts executing.

)}
) }