/** * Trading Bot v4 - Analytics Dashboard * * Comprehensive view of trading performance and statistics */ 'use client' import { useState, useEffect } from 'react' interface Stats { period: string realTrades: { total: number winning: number losing: number winRate: string totalPnL: string avgWin: string avgLoss: string profitFactor: string } testTrades: { count: number note: string } } interface NetPosition { symbol: string longUSD: number shortUSD: number netUSD: number netSOL: number netDirection: 'long' | 'short' | 'flat' tradeCount: number } interface PositionSummary { summary: { individualTrades: number testTrades: number totalIndividualExposure: string netExposure: string explanation: string } netPositions: NetPosition[] } export default function AnalyticsPage() { const [stats, setStats] = useState(null) const [positions, setPositions] = useState(null) const [loading, setLoading] = useState(true) const [selectedDays, setSelectedDays] = useState(30) useEffect(() => { loadData() }, [selectedDays]) const loadData = async () => { setLoading(true) try { const [statsRes, positionsRes] = await Promise.all([ fetch(`/api/analytics/stats?days=${selectedDays}`), fetch('/api/analytics/positions'), ]) const statsData = await statsRes.json() const positionsData = await positionsRes.json() setStats(statsData.stats) setPositions(positionsData.summary) } catch (error) { console.error('Failed to load analytics:', error) } setLoading(false) } if (loading) { return (

Loading analytics...

) } return (
{/* Header */}

📊 Analytics Dashboard

Trading performance and statistics

{/* Time Period Selector */}
Period:
{/* Position Summary */} {positions && (

📍 Current Positions

Open Trades
{positions.summary.individualTrades}
Test Trades
{positions.summary.testTrades}
Total Exposure
{positions.summary.totalIndividualExposure}
Net Exposure
{positions.summary.netExposure}
{positions.netPositions.length > 0 && (

Net Positions (Drift View)

{positions.netPositions.map((pos, i) => (
🎯
{pos.symbol}
{pos.tradeCount} trade{pos.tradeCount > 1 ? 's' : ''}
{pos.netDirection.toUpperCase()}: {Math.abs(pos.netSOL).toFixed(4)} SOL
${Math.abs(pos.netUSD).toFixed(2)}
))}
)} {positions.summary.individualTrades === 0 && (
📭

No open positions

)}
)} {/* Trading Statistics */} {stats && (

📈 Performance ({stats.period})

{/* Main Stats Grid */}
Total Trades
{stats.realTrades.total}
{stats.testTrades.count} test trade{stats.testTrades.count !== 1 ? 's' : ''} excluded
Win Rate
{stats.realTrades.winRate}
{stats.realTrades.winning}W / {stats.realTrades.losing}L
Total P&L
= 0 ? 'text-green-400' : 'text-red-400'}`}> {stats.realTrades.totalPnL}
Profit Factor
{stats.realTrades.profitFactor}
{/* Detailed Stats */}

Winning Trades

Count: {stats.realTrades.winning}
Average Win: {stats.realTrades.avgWin}

Losing Trades

Count: {stats.realTrades.losing}
Average Loss: {stats.realTrades.avgLoss}
{stats.realTrades.total === 0 && (
📊

No trading data yet

Start trading to see your performance statistics

)}
)} {/* Info Note */}
💡

Understanding Position Netting

Drift perpetual futures automatically NET opposite positions in the same market. If you have both LONG and SHORT positions in SOL-PERP, Drift shows only the net exposure. The database tracks individual trades for complete history, while this dashboard shows your actual market exposure.

) }