'use client' import { useState, useEffect } from 'react' import type { BotTrade, TrumpPost } from '@/types' import { getTrades, getPosts } from '@/lib/api' function fmtMoney(n: number, opts: { sign?: boolean; decimals?: number } = {}) { const { decimals = 2, sign = false } = opts if (n == null || isNaN(n)) return '—' const abs = Math.abs(n) const s = abs.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }) if (n < 0) return '-$' + s if (sign && n > 0) return '+$' + s return '$' + s } function fmtPct(n: number) { const s = n.toFixed(2) + '%' return n >= 0 ? '+' + s : 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' } function SourceIcon({ source }: { source: string }) { if (source === 'x') return
𝕏
return
T
} export default function TradesPage() { const [trades, setTrades] = useState([]) const [posts, setPosts] = useState([]) const [loading, setLoading] = useState(true) const [assetFilter, setAssetFilter] = useState('all') const [sideFilter, setSideFilter] = useState('all') useEffect(() => { Promise.all([ getTrades(200, 1).catch(() => []), getPosts(500, 1).catch(() => []), ]).then(([t, p]) => { setTrades(t) setPosts(p) }).finally(() => setLoading(false)) }, []) const filtered = trades.filter(t => { if (assetFilter !== 'all' && t.asset !== assetFilter) return false if (sideFilter !== 'all' && t.side !== sideFilter) return false return true }) const totalPnl = filtered.reduce((s, t) => s + t.pnl_usd, 0) const wins = filtered.filter(t => t.pnl_usd > 0).length const avgHold = filtered.length > 0 ? Math.round(filtered.reduce((s, t) => s + t.hold_seconds, 0) / filtered.length) : 0 return (

Trades

Every trade your bot executed. Transparent and auditable.

30 days
Total trades
{filtered.length}
Filtered
Win rate
{filtered.length ? ((wins / filtered.length) * 100).toFixed(1) + '%' : '—'}
{wins}W · {filtered.length - wins}L
Net P&L
{fmtMoney(totalPnl, { sign: true, decimals: 0 })}
All assets
Avg hold
{avgHold ? fmtHold(avgHold) : '—'}
Per trade
{(['all', 'BTC', 'ETH'] as const).map(a => ( ))}
{(['all', 'long', 'short'] as const).map(s => ( ))}
{loading &&
Loading…
} {!loading && (
{filtered.length === 0 && ( )} {filtered.map(t => { const triggerPost = posts.find(p => p.id === t.trigger_post_id) const roiPct = ((t.exit_price - t.entry_price) / t.entry_price) * 100 * (t.side === 'long' ? 1 : -1) return ( ) })}
Asset Side Entry Exit Hold Trigger P&L
No trades found
{t.asset}
{t.side === 'long' ? '↗ LONG' : '↘ SHORT'} ${t.entry_price.toLocaleString()} ${t.exit_price.toLocaleString()} {fmtHold(t.hold_seconds)} {triggerPost ? (
{triggerPost.text.slice(0, 50)}…
) : ( )}
= 0 ? 'up' : 'down'}`} style={{ fontWeight: 600, fontSize: 14 }}> {fmtMoney(t.pnl_usd, { sign: true })} = 0 ? 'up' : 'down'}`} style={{ fontSize: 11, opacity: 0.7 }}>{fmtPct(roiPct)}
)}
) }