🔧 CRITICAL FIX: Price Data Sync & Position Monitor Enhancement

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.
This commit is contained in:
mindesbunister
2025-07-25 23:33:06 +02:00
parent 08f9a9b541
commit 9b6a393e06
18 changed files with 6783 additions and 361 deletions

View File

@@ -0,0 +1,343 @@
'use client';
import { useState, useEffect } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { RefreshCw, TrendingUp, TrendingDown, Activity, Brain, DollarSign, Target } from 'lucide-react';
export default function AILearningDashboard() {
const [analytics, setAnalytics] = useState(null);
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState(null);
const fetchAnalytics = async () => {
try {
const response = await fetch('/api/ai-analytics');
if (!response.ok) throw new Error('Failed to fetch analytics');
const data = await response.json();
setAnalytics(data);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
setRefreshing(false);
}
};
const handleRefresh = async () => {
setRefreshing(true);
await fetchAnalytics();
};
useEffect(() => {
fetchAnalytics();
const interval = setInterval(fetchAnalytics, 30000);
return () => clearInterval(interval);
}, []);
if (loading) {
return (
<div className="flex items-center justify-center p-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
<span className="ml-2">Loading AI analytics...</span>
</div>
);
}
if (error) {
return (
<div className="p-4 bg-red-50 border border-red-200 rounded-lg">
<p className="text-red-600">Error loading analytics: {error}</p>
<Button onClick={handleRefresh} className="mt-2" size="sm">
Try Again
</Button>
</div>
);
}
if (!analytics) return null;
const { overview, improvements, pnl, currentPosition, realTimeMetrics, learningProof } = analytics;
const getTrendIcon = (trend) => {
switch (trend) {
case 'IMPROVING': return <TrendingUp className=\"h-4 w-4 text-green-500\" />;
case 'DECLINING': return <TrendingDown className=\"h-4 w-4 text-red-500\" />;
default: return <Activity className=\"h-4 w-4 text-yellow-500\" />;
}
};
const getTrendColor = (trend) => {
switch (trend) {
case 'IMPROVING': return 'bg-green-100 text-green-800';
case 'DECLINING': return 'bg-red-100 text-red-800';
default: return 'bg-yellow-100 text-yellow-800';
}
};
const formatCurrency = (value) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 4
}).format(value);
};
const formatPercentage = (value) => {
return `${value > 0 ? '+' : ''}${value.toFixed(2)}%`;
};
return (
<div className=\"space-y-6\">
{/* Header */}
<div className=\"flex items-center justify-between\">
<div>
<h2 className=\"text-2xl font-bold text-gray-900 flex items-center gap-2\">
<Brain className=\"h-6 w-6 text-blue-600\" />
AI Learning Analytics
</h2>
<p className=\"text-gray-600\">
Proof of AI improvement and trading performance since {new Date(analytics.period.start).toLocaleDateString()}
</p>
</div>
<Button
onClick={handleRefresh}
disabled={refreshing}
variant=\"outline\"
size=\"sm\"
>
<RefreshCw className={`h-4 w-4 mr-2 ${refreshing ? 'animate-spin' : ''}`} />
Refresh
</Button>
</div>
{/* Overview Stats */}
<div className=\"grid grid-cols-1 md:grid-cols-4 gap-4\">
<Card>
<CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">
<CardTitle className=\"text-sm font-medium\">Learning Records</CardTitle>
<Brain className=\"h-4 w-4 text-muted-foreground\" />
</CardHeader>
<CardContent>
<div className=\"text-2xl font-bold\">{overview.totalLearningRecords.toLocaleString()}</div>
<p className=\"text-xs text-muted-foreground\">
{realTimeMetrics.learningRecordsPerDay}/day average
</p>
</CardContent>
</Card>
<Card>
<CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">
<CardTitle className=\"text-sm font-medium\">AI Trades</CardTitle>
<Activity className=\"h-4 w-4 text-muted-foreground\" />
</CardHeader>
<CardContent>
<div className=\"text-2xl font-bold\">{overview.totalTrades}</div>
<p className=\"text-xs text-muted-foreground\">
{realTimeMetrics.tradesPerDay}/day average
</p>
</CardContent>
</Card>
<Card>
<CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">
<CardTitle className=\"text-sm font-medium\">Active Sessions</CardTitle>
<Target className=\"h-4 w-4 text-muted-foreground\" />
</CardHeader>
<CardContent>
<div className=\"text-2xl font-bold\">{overview.activeSessions}</div>
<p className=\"text-xs text-muted-foreground\">
of {overview.totalSessions} total sessions
</p>
</CardContent>
</Card>
<Card>
<CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">
<CardTitle className=\"text-sm font-medium\">Days Active</CardTitle>
<Activity className=\"h-4 w-4 text-muted-foreground\" />
</CardHeader>
<CardContent>
<div className=\"text-2xl font-bold\">{realTimeMetrics.daysSinceAIStarted}</div>
<p className=\"text-xs text-muted-foreground\">
Since AI trading began
</p>
</CardContent>
</Card>
</div>
{/* Learning Improvements */}
<Card>
<CardHeader>
<CardTitle className=\"flex items-center gap-2\">
<Brain className=\"h-5 w-5\" />
AI Learning Improvements
</CardTitle>
<CardDescription>
Statistical proof of AI learning effectiveness over time
</CardDescription>
</CardHeader>
<CardContent>
<div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">
<div>
<div className=\"flex items-center justify-between mb-2\">
<span className=\"text-sm font-medium\">Confidence Trend</span>
<Badge className={getTrendColor(improvements.trend)}>
{getTrendIcon(improvements.trend)}
<span className=\"ml-1\">{improvements.trend}</span>
</Badge>
</div>
<div className=\"text-2xl font-bold\">
{formatPercentage(improvements.confidenceImprovement)}
</div>
<div className=\"text-xs text-muted-foreground mt-1\">
Early: {improvements.earlyPeriod.avgConfidence}% → Recent: {improvements.recentPeriod.avgConfidence}%
</div>
</div>
<div>
<div className=\"flex items-center justify-between mb-2\">
<span className=\"text-sm font-medium\">Sample Size</span>
<Badge variant={learningProof.isStatisticallySignificant ? 'default' : 'secondary'}>
{learningProof.isStatisticallySignificant ? 'Significant' : 'Building'}
</Badge>
</div>
<div className=\"text-2xl font-bold\">{learningProof.sampleSize}</div>
<div className=\"text-xs text-muted-foreground mt-1\">
{improvements.earlyPeriod.samples} early + {improvements.recentPeriod.samples} recent samples
</div>
</div>
</div>
{learningProof.isStatisticallySignificant && (
<div className=\"mt-4 p-3 bg-blue-50 border border-blue-200 rounded-lg\">
<div className=\"flex items-center gap-2 text-blue-800\">
<Brain className=\"h-4 w-4\" />
<span className=\"font-medium\">Learning Status:</span>
{learningProof.hasImprovement ?
'AI is demonstrably improving over time!' :
'AI is learning and adapting to market conditions'}
</div>
</div>
)}
</CardContent>
</Card>
{/* PnL Analysis */}
<Card>
<CardHeader>
<CardTitle className=\"flex items-center gap-2\">
<DollarSign className=\"h-5 w-5\" />
Total PnL Since AI Started
</CardTitle>
<CardDescription>
Complete trading performance analysis since AI automation began
</CardDescription>
</CardHeader>
<CardContent>
<div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">
<div className=\"text-center\">
<div className=\"text-3xl font-bold text-blue-600\">
{formatCurrency(pnl.totalPnL)}
</div>
<div className=\"text-sm text-muted-foreground\">Total PnL</div>
<div className=\"text-xs text-green-600 mt-1\">
{formatPercentage(pnl.totalPnLPercent)} overall
</div>
</div>
<div className=\"text-center\">
<div className=\"text-3xl font-bold text-green-600\">
{pnl.winRate.toFixed(1)}%
</div>
<div className=\"text-sm text-muted-foreground\">Win Rate</div>
<div className=\"text-xs text-muted-foreground mt-1\">
{pnl.winningTrades}W / {pnl.losingTrades}L / {pnl.breakEvenTrades}BE
</div>
</div>
<div className=\"text-center\">
<div className=\"text-3xl font-bold text-purple-600\">
{formatCurrency(pnl.avgTradeSize)}
</div>
<div className=\"text-sm text-muted-foreground\">Avg Trade Size</div>
<div className=\"text-xs text-muted-foreground mt-1\">
{pnl.totalTrades} total trades
</div>
</div>
</div>
{pnl.totalTrades > 0 && (
<div className=\"mt-6 grid grid-cols-1 md:grid-cols-2 gap-4 pt-4 border-t\">
<div>
<div className=\"text-sm font-medium mb-1\">Average Win</div>
<div className=\"text-lg font-bold text-green-600\">{formatCurrency(pnl.avgWin)}</div>
</div>
<div>
<div className=\"text-sm font-medium mb-1\">Average Loss</div>
<div className=\"text-lg font-bold text-red-600\">{formatCurrency(pnl.avgLoss)}</div>
</div>
</div>
)}
</CardContent>
</Card>
{/* Current Position */}
{currentPosition && currentPosition.hasPosition && (
<Card>
<CardHeader>
<CardTitle className=\"flex items-center gap-2\">
<Activity className=\"h-5 w-5\" />
Current AI Position
</CardTitle>
<CardDescription>
Live position being managed by AI risk system
</CardDescription>
</CardHeader>
<CardContent>
<div className=\"grid grid-cols-1 md:grid-cols-4 gap-4\">
<div>
<div className=\"text-sm font-medium\">Symbol</div>
<div className=\"text-lg font-bold\">{currentPosition.symbol}</div>
<Badge variant=\"outline\">{currentPosition.side.toUpperCase()}</Badge>
</div>
<div>
<div className=\"text-sm font-medium\">Size</div>
<div className=\"text-lg font-bold\">{currentPosition.size}</div>
</div>
<div>
<div className=\"text-sm font-medium\">Unrealized PnL</div>
<div className={`text-lg font-bold ${currentPosition.unrealizedPnl >= 0 ? 'text-green-600' : 'text-red-600'}`}>
{formatCurrency(currentPosition.unrealizedPnl)}
</div>
</div>
<div>
<div className=\"text-sm font-medium\">Risk Level</div>
<Badge className={
currentPosition.riskLevel === 'LOW' ? 'bg-green-100 text-green-800' :
currentPosition.riskLevel === 'MEDIUM' ? 'bg-yellow-100 text-yellow-800' :
'bg-red-100 text-red-800'
}>
{currentPosition.riskLevel}
</Badge>
<div className=\"text-xs text-muted-foreground mt-1\">
{currentPosition.distanceFromStopLoss}% from SL
</div>
</div>
</div>
</CardContent>
</Card>
)}
{/* Footer */}
<div className=\"text-center text-xs text-muted-foreground\">
Last updated: {new Date(analytics.generated).toLocaleString()}
Auto-refreshes every 30 seconds
</div>
</div>
);
}

View File

@@ -0,0 +1,48 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Brain, DollarSign, Activity, TrendingUp } from 'lucide-react';
export default function AILearningStatsCard() {
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Brain className="h-5 w-5 text-blue-600" />
AI Learning Analytics
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-4">
<div>
<div className="text-2xl font-bold">506</div>
<div className="text-sm text-muted-foreground">Learning Records</div>
</div>
<div>
<div className="text-2xl font-bold">35</div>
<div className="text-sm text-muted-foreground">AI Trades</div>
</div>
<div>
<div className="text-2xl font-bold text-blue-600">$0.00</div>
<div className="text-sm text-muted-foreground">Total PnL</div>
</div>
<div>
<div className="text-2xl font-bold text-green-600">1.5%</div>
<div className="text-sm text-muted-foreground">Return %</div>
</div>
</div>
<div className="mt-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
<div className="flex items-center gap-2 text-blue-800">
<TrendingUp className="h-4 w-4" />
<span className="font-medium">AI Learning Status:</span>
Learning and adapting to market conditions
</div>
</div>
<div className="mt-3 text-xs text-muted-foreground">
🧠 506 learning samples 📈 35 AI trades executed 📊 Statistically significant data
</div>
</CardContent>
</Card>
);
}