Fixed major price data sync issues: - Removed hardcoded price (77.63) from position monitor - Added real-time oracle data instead of stale TWAP pricing - Implemented cache-busting headers for fresh data - Updated fallback prices to current market levels - Real-time P&L tracking with trend indicators (📈📉➡️) - Enhanced stop loss proximity alerts with color-coded risk levels - Analysis progress indicators during automation cycles - Performance metrics (runtime, cycles, trades, errors) - Fresh data validation and improved error handling - Price accuracy: 77.63 → 84.47 (matches Drift UI) - P&L accuracy: -.91 → -.59 (correct calculation) - Risk assessment: CRITICAL → MEDIUM (proper evaluation) - Stop loss distance: 0.91% → 4.8% (safe distance) - CLI monitor script with 8-second updates - Web dashboard component (PositionMonitor.tsx) - Real-time automation status tracking - Database and error monitoring improvements This fixes the automation showing false emergency alerts when position was actually performing normally.
332 lines
15 KiB
TypeScript
332 lines
15 KiB
TypeScript
'use client'
|
||
|
||
import React, { useState, useEffect } from 'react'
|
||
|
||
interface AIAnalytics {
|
||
generated: string
|
||
overview: {
|
||
totalLearningRecords: number
|
||
totalTrades: number
|
||
totalSessions: number
|
||
activeSessions: number
|
||
}
|
||
improvements: {
|
||
confidenceImprovement: number
|
||
accuracyImprovement: number | null
|
||
trend: string
|
||
}
|
||
pnl: {
|
||
totalTrades: number
|
||
totalPnL: number
|
||
totalPnLPercent: number
|
||
winRate: number
|
||
avgTradeSize: number
|
||
}
|
||
currentPosition: any
|
||
realTimeMetrics: {
|
||
daysSinceAIStarted: number
|
||
learningRecordsPerDay: number
|
||
tradesPerDay: number
|
||
lastUpdate: string
|
||
isLearningActive: boolean
|
||
}
|
||
learningProof: {
|
||
hasImprovement: boolean
|
||
improvementDirection: string
|
||
confidenceChange: number
|
||
sampleSize: number
|
||
isStatisticallySignificant: boolean
|
||
}
|
||
}
|
||
|
||
interface PositionData {
|
||
hasPosition: boolean
|
||
symbol?: string
|
||
unrealizedPnl?: number
|
||
riskLevel?: string
|
||
}
|
||
|
||
export default function Dashboard() {
|
||
const [positions, setPositions] = useState<PositionData>({ hasPosition: false })
|
||
const [loading, setLoading] = useState(true)
|
||
const [aiAnalytics, setAiAnalytics] = useState<AIAnalytics | null>(null)
|
||
const [analyticsLoading, setAnalyticsLoading] = useState(true)
|
||
|
||
const fetchData = async () => {
|
||
try {
|
||
// Fetch position data
|
||
const positionResponse = await fetch('/api/check-position')
|
||
const positionData = await positionResponse.json()
|
||
setPositions(positionData)
|
||
|
||
// Fetch AI analytics
|
||
setAnalyticsLoading(true)
|
||
const analyticsResponse = await fetch('/api/ai-analytics')
|
||
const analyticsData = await analyticsResponse.json()
|
||
setAiAnalytics(analyticsData)
|
||
setAnalyticsLoading(false)
|
||
} catch (error) {
|
||
console.error('Error fetching data:', error)
|
||
setAnalyticsLoading(false)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
useEffect(() => {
|
||
fetchData()
|
||
// Refresh every 30 seconds
|
||
const interval = setInterval(fetchData, 30000)
|
||
return () => clearInterval(interval)
|
||
}, [])
|
||
|
||
return (
|
||
<div className="space-y-8">
|
||
{/* Quick Overview Cards */}
|
||
<div className="space-y-6">
|
||
{/* Position Monitor */}
|
||
<div className="bg-gray-800 rounded-lg p-4 border border-gray-700">
|
||
<div className="flex justify-between items-center">
|
||
<h2 className="text-lg font-semibold text-white flex items-center">
|
||
<span className="mr-2">🔍</span>Position Monitor
|
||
</h2>
|
||
<span className="text-sm text-gray-400">
|
||
Last update: {new Date().toLocaleTimeString()}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Position Status */}
|
||
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6">
|
||
{positions.hasPosition ? (
|
||
<div className="space-y-4">
|
||
<h3 className="text-lg font-medium text-white flex items-center">
|
||
<span className="mr-2">📈</span>Active Position
|
||
</h3>
|
||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||
<div className="text-center">
|
||
<p className="text-sm text-gray-400">Symbol</p>
|
||
<p className="text-lg font-semibold text-blue-400">{positions.symbol}</p>
|
||
</div>
|
||
<div className="text-center">
|
||
<p className="text-sm text-gray-400">Unrealized PnL</p>
|
||
<p className={`text-lg font-semibold ${
|
||
(positions.unrealizedPnl || 0) >= 0 ? 'text-green-400' : 'text-red-400'
|
||
}`}>
|
||
${(positions.unrealizedPnl || 0).toFixed(2)}
|
||
</p>
|
||
</div>
|
||
<div className="text-center">
|
||
<p className="text-sm text-gray-400">Risk Level</p>
|
||
<p className={`text-lg font-semibold ${
|
||
positions.riskLevel === 'LOW' ? 'text-green-400' :
|
||
positions.riskLevel === 'MEDIUM' ? 'text-yellow-400' : 'text-red-400'
|
||
}`}>
|
||
{positions.riskLevel}
|
||
</p>
|
||
</div>
|
||
<div className="text-center">
|
||
<p className="text-sm text-gray-400">Status</p>
|
||
<div className="flex items-center justify-center space-x-1">
|
||
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
|
||
<span className="text-sm text-green-400">Active</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="text-center py-8">
|
||
<p className="text-gray-400 text-lg flex items-center justify-center">
|
||
<span className="mr-2">📊</span>No Open Positions
|
||
</p>
|
||
<p className="text-gray-500 mt-2">Scanning for opportunities...</p>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Automation Status */}
|
||
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6">
|
||
<h3 className="text-lg font-medium text-white mb-4 flex items-center">
|
||
<span className="mr-2">🤖</span>Automation Status
|
||
</h3>
|
||
<div className="text-center py-4">
|
||
<p className="text-red-400 font-medium flex items-center justify-center">
|
||
<span className="w-2 h-2 bg-red-400 rounded-full mr-2"></span>STOPPED
|
||
</p>
|
||
<p className="text-gray-500 mt-2"></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* AI Learning Analytics */}
|
||
<div className="card card-gradient">
|
||
{analyticsLoading ? (
|
||
<div className="flex items-center justify-center py-12">
|
||
<div className="spinner"></div>
|
||
<span className="ml-2 text-gray-400">Loading AI learning analytics...</span>
|
||
</div>
|
||
) : aiAnalytics ? (
|
||
<div className="p-6">
|
||
<h2 className="text-xl font-bold text-white mb-6 flex items-center">
|
||
<span className="mr-2">🧠</span>AI Learning Analytics & Performance
|
||
</h2>
|
||
|
||
{/* Overview Stats */}
|
||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||
<div className="text-2xl font-bold text-blue-400">{aiAnalytics.overview.totalLearningRecords}</div>
|
||
<div className="text-sm text-gray-400">Learning Records</div>
|
||
</div>
|
||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||
<div className="text-2xl font-bold text-green-400">{aiAnalytics.overview.totalTrades}</div>
|
||
<div className="text-sm text-gray-400">AI Trades Executed</div>
|
||
</div>
|
||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||
<div className="text-2xl font-bold text-purple-400">{aiAnalytics.realTimeMetrics.daysSinceAIStarted}</div>
|
||
<div className="text-sm text-gray-400">Days Active</div>
|
||
</div>
|
||
<div className="bg-gray-800/50 rounded-lg p-4 text-center">
|
||
<div className={`text-2xl font-bold ${aiAnalytics.learningProof.isStatisticallySignificant ? 'text-green-400' : 'text-yellow-400'}`}>
|
||
{aiAnalytics.learningProof.isStatisticallySignificant ? '✓' : '⚠'}
|
||
</div>
|
||
<div className="text-sm text-gray-400">Statistical Significance</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Learning Improvements */}
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||
<div className="bg-gray-800/30 rounded-lg p-4">
|
||
<h3 className="text-lg font-semibold text-white mb-3">Learning Progress</h3>
|
||
<div className="space-y-2">
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Confidence Change:</span>
|
||
<span className={`font-semibold ${aiAnalytics.improvements.confidenceImprovement >= 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||
{aiAnalytics.improvements.confidenceImprovement > 0 ? '+' : ''}{aiAnalytics.improvements.confidenceImprovement.toFixed(2)}%
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Trend Direction:</span>
|
||
<span className={`font-semibold ${aiAnalytics.improvements.trend === 'IMPROVING' ? 'text-green-400' : 'text-yellow-400'}`}>
|
||
{aiAnalytics.improvements.trend}
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Sample Size:</span>
|
||
<span className="text-white font-semibold">{aiAnalytics.learningProof.sampleSize}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="bg-gray-800/30 rounded-lg p-4">
|
||
<h3 className="text-lg font-semibold text-white mb-3">Trading Performance</h3>
|
||
<div className="space-y-2">
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Total PnL:</span>
|
||
<span className={`font-semibold ${aiAnalytics.pnl.totalPnL >= 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||
${aiAnalytics.pnl.totalPnL.toFixed(2)}
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">PnL Percentage:</span>
|
||
<span className={`font-semibold ${aiAnalytics.pnl.totalPnLPercent >= 0 ? 'text-green-400' : 'text-red-400'}`}>
|
||
{aiAnalytics.pnl.totalPnLPercent > 0 ? '+' : ''}{aiAnalytics.pnl.totalPnLPercent.toFixed(2)}%
|
||
</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Win Rate:</span>
|
||
<span className="text-white font-semibold">{(aiAnalytics.pnl.winRate * 100).toFixed(1)}%</span>
|
||
</div>
|
||
<div className="flex justify-between">
|
||
<span className="text-gray-400">Avg Trade Size:</span>
|
||
<span className="text-white font-semibold">${aiAnalytics.pnl.avgTradeSize.toFixed(2)}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Proof of Learning */}
|
||
<div className="bg-gradient-to-r from-blue-900/30 to-purple-900/30 rounded-lg p-4 border border-blue-500/30">
|
||
<h3 className="text-lg font-semibold text-white mb-3 flex items-center">
|
||
<span className="mr-2">📈</span>Proof of AI Learning Effectiveness
|
||
</h3>
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
||
<div className="text-center">
|
||
<div className="text-lg font-bold text-blue-400">{aiAnalytics.overview.totalLearningRecords}</div>
|
||
<div className="text-gray-400">Learning Samples Collected</div>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="text-lg font-bold text-green-400">{aiAnalytics.overview.totalTrades}</div>
|
||
<div className="text-gray-400">AI Decisions Executed</div>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className={`text-lg font-bold ${aiAnalytics.learningProof.isStatisticallySignificant ? 'text-green-400' : 'text-yellow-400'}`}>
|
||
{aiAnalytics.learningProof.isStatisticallySignificant ? 'PROVEN' : 'LEARNING'}
|
||
</div>
|
||
<div className="text-gray-400">Statistical Confidence</div>
|
||
</div>
|
||
</div>
|
||
<div className="mt-4 text-center text-sm text-gray-300">
|
||
🧠 AI learning system has collected <strong>{aiAnalytics.overview.totalLearningRecords} samples</strong>
|
||
and executed <strong>{aiAnalytics.overview.totalTrades} trades</strong> with
|
||
<strong> {aiAnalytics.learningProof.isStatisticallySignificant ? 'statistically significant' : 'emerging'}</strong> learning patterns.
|
||
</div>
|
||
</div>
|
||
|
||
{/* Real-time Metrics */}
|
||
<div className="mt-6 text-center text-xs text-gray-500">
|
||
Last updated: {new Date(aiAnalytics.realTimeMetrics.lastUpdate).toLocaleString()}
|
||
• Learning Active: {aiAnalytics.realTimeMetrics.isLearningActive ? '✅' : '❌'}
|
||
• {aiAnalytics.realTimeMetrics.learningRecordsPerDay.toFixed(1)} records/day
|
||
• {aiAnalytics.realTimeMetrics.tradesPerDay.toFixed(1)} trades/day
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="flex items-center justify-center py-12">
|
||
<div className="text-center">
|
||
<span className="text-red-400 text-lg">⚠️</span>
|
||
<p className="text-gray-400 mt-2">Unable to load AI analytics</p>
|
||
<button
|
||
onClick={fetchData}
|
||
className="mt-4 px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded text-white text-sm"
|
||
>
|
||
Retry
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Overview Section */}
|
||
<div className="card card-gradient">
|
||
{loading ? (
|
||
<div className="flex items-center justify-center py-12">
|
||
<div className="spinner"></div>
|
||
<span className="ml-2 text-gray-400">Loading overview...</span>
|
||
</div>
|
||
) : (
|
||
<div className="p-6">
|
||
<h2 className="text-xl font-bold text-white mb-6">Trading Overview</h2>
|
||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||
<div className="text-center">
|
||
<div className="text-3xl mb-2">🎯</div>
|
||
<div className="text-lg font-semibold text-white">Strategy Performance</div>
|
||
<div className="text-sm text-gray-400 mt-2">AI-powered analysis with continuous learning</div>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="text-3xl mb-2">🔄</div>
|
||
<div className="text-lg font-semibold text-white">Automated Execution</div>
|
||
<div className="text-sm text-gray-400 mt-2">24/7 market monitoring and trade execution</div>
|
||
</div>
|
||
<div className="text-center">
|
||
<div className="text-3xl mb-2">📊</div>
|
||
<div className="text-lg font-semibold text-white">Risk Management</div>
|
||
<div className="text-sm text-gray-400 mt-2">Advanced stop-loss and position sizing</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|