/** * 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 LastTrade { id: string symbol: string direction: string entryPrice: number entryTime: string exitPrice?: number exitTime?: string exitReason?: string realizedPnL?: number realizedPnLPercent?: number positionSizeUSD: number leverage: number stopLossPrice: number takeProfit1Price: number takeProfit2Price: number isTestTrade: boolean signalQualityScore?: number } 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[] } interface VersionStats { version: string tradeCount: number winRate: number totalPnL: number avgPnL: number avgQualityScore: number | null avgMFE: number | null avgMAE: number | null extremePositions: { count: number avgADX: number | null weakADXCount: number winRate: number avgPnL: number } } interface VersionComparison { versions: VersionStats[] descriptions: Record } export default function AnalyticsPage() { const [stats, setStats] = useState(null) const [positions, setPositions] = useState(null) const [lastTrade, setLastTrade] = useState(null) const [versionComparison, setVersionComparison] = useState(null) const [loading, setLoading] = useState(true) const [selectedDays, setSelectedDays] = useState(30) useEffect(() => { loadData() }, [selectedDays]) const loadData = async () => { setLoading(true) try { const [statsRes, positionsRes, lastTradeRes, versionRes] = await Promise.all([ fetch(`/api/analytics/stats?days=${selectedDays}`), fetch('/api/analytics/positions'), fetch('/api/analytics/last-trade'), fetch('/api/analytics/version-comparison'), ]) const statsData = await statsRes.json() const positionsData = await positionsRes.json() const lastTradeData = await lastTradeRes.json() const versionData = await versionRes.json() setStats(statsData.stats) setPositions(positionsData.summary) setLastTrade(lastTradeData.trade) setVersionComparison(versionData.success ? versionData : null) } catch (error) { console.error('Failed to load analytics:', error) } setLoading(false) } const clearManuallyClosed = async () => { if (!confirm('Clear all open trades from database? Use this if you manually closed positions in Drift UI.')) { return } try { const res = await fetch('/api/trading/clear-manual-closes', { method: 'POST', }) if (res.ok) { alert('✅ Manually closed trades cleared from database') loadData() // Reload data } else { const error = await res.json() alert(`❌ Failed to clear: ${error.error}`) } } catch (error) { console.error('Failed to clear trades:', error) alert('❌ Failed to clear trades') } } if (loading) { return (

Loading analytics...

) } return (
{/* Header */}

📊 Analytics Dashboard

Trading performance and statistics

{/* Time Period Selector */}
🎯 TP/SL Optimization
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

)}
)} {/* Indicator Version Comparison */} {versionComparison && versionComparison.versions.length > 0 && (

� TradingView Indicator Versions

Comparing performance across different TradingView indicator strategies to optimize signal quality.

{versionComparison.versions.map((version, idx) => { const isCurrentVersion = version.version === 'v6' return (

{version.version.toUpperCase()} {isCurrentVersion && ( CURRENT )}

{versionComparison.descriptions[version.version] || 'Unknown version'}

{/* Main Metrics Grid */}
Trades
{version.tradeCount}
Win Rate
= 50 ? 'text-green-400' : 'text-red-400'}`}> {version.winRate}%
Total P&L
= 0 ? 'text-green-400' : 'text-red-400'}`}> {version.totalPnL >= 0 ? '+' : ''}${version.totalPnL.toFixed(2)}
Avg P&L
= 0 ? 'text-green-400' : 'text-red-400'}`}> {version.avgPnL >= 0 ? '+' : ''}${version.avgPnL.toFixed(2)}
{/* Advanced Metrics */}
{version.avgQualityScore !== null && (
Avg Quality Score
= 75 ? 'text-green-400' : 'text-yellow-400'}`}> {version.avgQualityScore}/100
)} {version.avgMFE !== null && (
Avg MFE
+{version.avgMFE.toFixed(2)}%
)} {version.avgMAE !== null && (
Avg MAE
{version.avgMAE.toFixed(2)}%
)}
{/* Extreme Position Stats */} {version.extremePositions.count > 0 && (
⚠️ Extreme Positions (< 15% or > 85% range)
Count
{version.extremePositions.count}
{version.extremePositions.avgADX !== null && (
Avg ADX
= 18 ? 'text-green-400' : 'text-orange-400'}`}> {version.extremePositions.avgADX.toFixed(1)}
)}
Weak ADX
{version.extremePositions.weakADXCount}
Win Rate
= 50 ? 'text-green-400' : 'text-red-400'}`}> {version.extremePositions.winRate}%
Avg P&L
= 0 ? 'text-green-400' : 'text-red-400'}`}> {version.extremePositions.avgPnL >= 0 ? '+' : ''}${version.extremePositions.avgPnL.toFixed(2)}
)} {/* Data Collection Notice for v3 */} {isCurrentVersion && version.tradeCount < 20 && (
📊

Data Collection Phase: Need {20 - version.tradeCount} more trades before v3 performance can be reliably evaluated. This version is designed to prevent losses from extreme position entries with weak trends (ADX < 18).

)}
) })}
{/* Legend */}
MFE (Max Favorable Excursion): Best profit % reached during trade lifetime
MAE (Max Adverse Excursion): Worst loss % reached during trade lifetime
Extreme Positions: Trades entered at price range extremes (< 15% or > 85%)
Weak ADX: Trend strength below 18 (indicates sideways/choppy market)
)} {/* Last Trade Details */} {lastTrade && (

🔍 Last Trade

{lastTrade.direction === 'long' ? '📈' : '📉'}
{lastTrade.symbol}
{lastTrade.direction.toUpperCase()} {lastTrade.isTestTrade && ( TEST )}
{lastTrade.exitTime && lastTrade.realizedPnL !== undefined && (
= 0 ? 'text-green-400' : 'text-red-400'}`}> {lastTrade.realizedPnL >= 0 ? '+' : ''}${lastTrade.realizedPnL.toFixed(2)}
{lastTrade.realizedPnLPercent !== undefined && (
= 0 ? 'text-green-400' : 'text-red-400'}`}> {lastTrade.realizedPnLPercent >= 0 ? '+' : ''}{lastTrade.realizedPnLPercent.toFixed(2)}%
)}
)} {!lastTrade.exitTime && (
OPEN
Currently active
)}
Entry
${lastTrade.entryPrice.toFixed(4)}
{new Date(lastTrade.entryTime).toLocaleString()}
Position Size
${lastTrade.positionSizeUSD.toFixed(2)}
{lastTrade.leverage}x leverage
Signal Quality
{lastTrade.signalQualityScore !== undefined ? ( <>
= 80 ? 'text-green-400' : lastTrade.signalQualityScore >= 70 ? 'text-yellow-400' : 'text-orange-400'}`}> {lastTrade.signalQualityScore}/100
{lastTrade.signalQualityScore >= 80 ? 'Excellent' : lastTrade.signalQualityScore >= 70 ? 'Good' : 'Marginal'}
) : ( <>
N/A
No score available
)}
{lastTrade.exitTime && lastTrade.exitPrice && (
Exit
${lastTrade.exitPrice.toFixed(4)}
{new Date(lastTrade.exitTime).toLocaleString()}
)}
Stop Loss
${lastTrade.stopLossPrice.toFixed(4)}
TP1
${lastTrade.takeProfit1Price.toFixed(4)}
TP2
${lastTrade.takeProfit2Price.toFixed(4)}
{lastTrade.exitReason && (
Exit Reason: {lastTrade.exitReason}
)}
)} {/* 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.

) }