- Fixed component showing mock data (1120 analyses, 66.7% win rate) instead of real data - Updated fallback logic to show empty/zero values when API fails instead of fake data - Dashboard will now display actual 9,413 analyses and real PATTERN RECOGNITION phase - Removed misleading fallback statistics that showed fake trading performance - Component now properly uses real AI learning API data when available The dashboard should now show the correct learning system status with real data.
527 lines
19 KiB
TypeScript
527 lines
19 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
|
|
interface LearningData {
|
|
// AI Learning API data
|
|
totalAnalyses?: number;
|
|
totalDecisions?: number;
|
|
totalOutcomes?: number;
|
|
daysActive?: number;
|
|
avgAccuracy?: number;
|
|
winRate?: number;
|
|
confidenceLevel?: number;
|
|
phase?: string;
|
|
nextMilestone?: string;
|
|
recommendation?: string;
|
|
|
|
// Legacy learning system data
|
|
learningSystem: {
|
|
enabled: boolean;
|
|
learningActive?: boolean;
|
|
activeDecisions?: number;
|
|
message?: string;
|
|
recommendation?: string;
|
|
report?: {
|
|
summary?: {
|
|
totalDecisions?: number;
|
|
successRate?: number;
|
|
systemConfidence?: number;
|
|
};
|
|
insights?: {
|
|
thresholds?: any;
|
|
confidenceLevel?: number;
|
|
};
|
|
recommendations?: Array<{
|
|
type: string;
|
|
message: string;
|
|
priority: string;
|
|
} | string>;
|
|
};
|
|
};
|
|
visibility?: {
|
|
decisionTrackingActive?: boolean;
|
|
learningDatabaseConnected?: boolean;
|
|
aiEnhancementsActive?: boolean;
|
|
lastUpdateTime?: string;
|
|
};
|
|
automationStatus?: any;
|
|
realTradingData?: {
|
|
statistics?: {
|
|
totalTrades?: number;
|
|
wins?: number;
|
|
losses?: number;
|
|
winRate?: number;
|
|
totalPnl?: number;
|
|
winsPnl?: number;
|
|
lossesPnl?: number;
|
|
avgWin?: number;
|
|
avgLoss?: number;
|
|
profitFactor?: number;
|
|
};
|
|
trades?: Array<{
|
|
symbol: string;
|
|
side: string;
|
|
size: number;
|
|
entryPrice: number;
|
|
exitPrice: number;
|
|
pnl: number;
|
|
status: string;
|
|
timestamp: number;
|
|
outcome: string;
|
|
}>;
|
|
totalAnalyses?: number;
|
|
avgAccuracy?: number;
|
|
confidenceLevel?: number;
|
|
phase?: string;
|
|
nextMilestone?: string;
|
|
recommendation?: string;
|
|
daysActive?: number;
|
|
} | null;
|
|
}
|
|
|
|
const EnhancedAILearningPanel = () => {
|
|
const [learningData, setLearningData] = useState<LearningData | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const fetchLearningStatus = async () => {
|
|
try {
|
|
setLoading(true);
|
|
|
|
// Get learning status, automation status, and real Drift trading data
|
|
const [learningResponse, statusResponse, aiLearningResponse] = await Promise.all([
|
|
fetch('/api/automation/learning-status'),
|
|
fetch('/api/automation/status'),
|
|
fetch('/api/ai-learning-status')
|
|
]);
|
|
|
|
const learningData = await learningResponse.json();
|
|
const statusData = await statusResponse.json();
|
|
const aiLearningData = await aiLearningResponse.json();
|
|
|
|
const aiData = aiLearningData.success ? aiLearningData.data : {
|
|
// Fallback data when AI learning API is unavailable
|
|
totalAnalyses: 0,
|
|
totalDecisions: 0,
|
|
totalOutcomes: 0,
|
|
daysActive: 0,
|
|
avgAccuracy: 0,
|
|
winRate: 0,
|
|
confidenceLevel: 0,
|
|
phase: 'UNKNOWN',
|
|
nextMilestone: '',
|
|
recommendation: 'Learning API unavailable',
|
|
statistics: {
|
|
totalTrades: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
winRate: 0,
|
|
totalPnl: 0,
|
|
winsPnl: 0,
|
|
lossesPnl: 0,
|
|
avgWin: 0,
|
|
avgLoss: 0,
|
|
profitFactor: 0
|
|
}
|
|
};
|
|
|
|
// Merge current status with real AI learning data
|
|
const safeData = {
|
|
// Include AI learning data at the top level
|
|
totalAnalyses: aiData.totalAnalyses || 0,
|
|
totalDecisions: aiData.totalDecisions || 0,
|
|
totalOutcomes: aiData.totalOutcomes || 0,
|
|
daysActive: aiData.daysActive || 0,
|
|
avgAccuracy: aiData.avgAccuracy || 0,
|
|
winRate: aiData.winRate || 0,
|
|
confidenceLevel: aiData.confidenceLevel || 0,
|
|
phase: aiData.phase || 'UNKNOWN',
|
|
nextMilestone: aiData.nextMilestone || '',
|
|
recommendation: aiData.recommendation || '',
|
|
|
|
learningSystem: {
|
|
enabled: learningData.learningSystem?.enabled || (aiData.totalAnalyses > 0),
|
|
message: (aiData.totalAnalyses > 0) ?
|
|
`Learning system active with ${aiData.totalAnalyses} analyses` :
|
|
(learningData.message || 'Learning system not available'),
|
|
activeDecisions: learningData.learningSystem?.activeDecisions || aiData.totalDecisions || 0
|
|
},
|
|
visibility: learningData.visibility || {
|
|
decisionTrackingActive: aiData.totalDecisions > 0,
|
|
learningDatabaseConnected: aiData.totalAnalyses > 0,
|
|
aiEnhancementsActive: aiData.totalDecisions > 0,
|
|
lastUpdateTime: new Date().toISOString()
|
|
},
|
|
automationStatus: statusData,
|
|
realTradingData: aiData
|
|
};
|
|
|
|
setLearningData(safeData);
|
|
setError(null);
|
|
} catch (err) {
|
|
console.error('Error fetching learning status:', err);
|
|
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
|
|
// Set default data structure on error
|
|
setLearningData({
|
|
totalAnalyses: 0,
|
|
totalDecisions: 0,
|
|
totalOutcomes: 0,
|
|
daysActive: 0,
|
|
avgAccuracy: 0,
|
|
winRate: 0,
|
|
confidenceLevel: 0,
|
|
phase: 'UNKNOWN',
|
|
nextMilestone: '',
|
|
recommendation: '',
|
|
learningSystem: {
|
|
enabled: false,
|
|
message: 'Failed to fetch learning status',
|
|
activeDecisions: 0
|
|
},
|
|
visibility: {
|
|
decisionTrackingActive: false,
|
|
learningDatabaseConnected: false,
|
|
aiEnhancementsActive: false,
|
|
lastUpdateTime: new Date().toISOString()
|
|
},
|
|
automationStatus: null,
|
|
realTradingData: {
|
|
// Error fallback - show empty data
|
|
statistics: {
|
|
totalTrades: 0,
|
|
wins: 0,
|
|
losses: 0,
|
|
winRate: 0,
|
|
totalPnl: 0,
|
|
winsPnl: 0,
|
|
lossesPnl: 0,
|
|
avgWin: 0,
|
|
avgLoss: 0,
|
|
profitFactor: 0
|
|
},
|
|
totalAnalyses: 0,
|
|
avgAccuracy: 0,
|
|
confidenceLevel: 0,
|
|
phase: 'ERROR',
|
|
nextMilestone: 'Fix API connection',
|
|
recommendation: 'Learning system API unavailable',
|
|
daysActive: 0
|
|
}
|
|
});
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchLearningStatus();
|
|
|
|
// Refresh every 30 seconds
|
|
const interval = setInterval(fetchLearningStatus, 30000);
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 border border-purple-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-purple-500 rounded-full animate-pulse"></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-gray-400">Loading learning status...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-red-900/20 to-orange-900/20 rounded-xl p-6 border border-red-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-red-500 rounded-full"></div>
|
|
<h3 className="text-lg font-semibold text-red-400">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-red-400">Error: {error}</div>
|
|
<button
|
|
onClick={fetchLearningStatus}
|
|
className="mt-3 px-4 py-2 bg-red-600/20 hover:bg-red-600/30 text-red-400 rounded-lg transition-colors"
|
|
>
|
|
Retry
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!learningData) {
|
|
return null;
|
|
}
|
|
|
|
const { learningSystem, visibility } = learningData;
|
|
|
|
// Safety check for learningSystem
|
|
if (!learningSystem) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-gray-900/20 to-gray-800/20 rounded-xl p-6 border border-gray-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-gray-500 rounded-full"></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-gray-400">Loading learning system data...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const renderLearningStatus = () => {
|
|
// Show as active if we have real AI learning data from the new API
|
|
const hasLearningData = (learningData?.totalAnalyses || 0) > 0;
|
|
const hasDecisions = (learningData?.totalDecisions || 0) > 0;
|
|
const hasTradeData = (learningData?.realTradingData?.statistics?.totalTrades || 0) > 0;
|
|
const isSystemActive = hasLearningData || hasDecisions || hasTradeData;
|
|
|
|
if (!isSystemActive) {
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-2">
|
|
<div className="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
|
<span className="text-yellow-400 font-medium">Learning System Not Active</span>
|
|
</div>
|
|
|
|
<div className="bg-yellow-900/20 rounded-lg p-4 border border-yellow-500/30">
|
|
<div className="text-yellow-300 text-sm">
|
|
{learningSystem?.message || 'The AI learning system is not currently integrated with the automation.'}
|
|
</div>
|
|
{learningSystem?.recommendation && (
|
|
<div className="text-yellow-400 text-sm mt-2 font-medium">
|
|
💡 {learningSystem.recommendation}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="text-gray-400 text-sm">
|
|
• Decision recording: Not active<br/>
|
|
• Learning database: Not connected<br/>
|
|
• AI enhancements: Not applied
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-2">
|
|
<div className="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
|
<span className="text-green-400 font-medium">AI Learning Active</span>
|
|
</div>
|
|
|
|
{learningSystem?.report && (
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div className="bg-blue-900/20 rounded-lg p-4 border border-blue-500/30">
|
|
<div className="text-blue-300 text-sm font-medium">Total Decisions</div>
|
|
<div className="text-2xl font-bold text-blue-400">
|
|
{learningSystem.report.summary?.totalDecisions || 0}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-purple-900/20 rounded-lg p-4 border border-purple-500/30">
|
|
<div className="text-purple-300 text-sm font-medium">Success Rate</div>
|
|
<div className="text-2xl font-bold text-purple-400">
|
|
{learningSystem.report.summary?.successRate || 0}%
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-green-900/20 rounded-lg p-4 border border-green-500/30">
|
|
<div className="text-green-300 text-sm font-medium">Confidence</div>
|
|
<div className="text-2xl font-bold text-green-400">
|
|
{learningSystem.report.summary?.systemConfidence || 0}%
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="bg-gray-800/50 rounded-lg p-4 border border-gray-600/30">
|
|
<div className="text-gray-300 text-sm font-medium mb-2">🔍 Learning Visibility</div>
|
|
<div className="grid grid-cols-2 gap-2 text-sm">
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.decisionTrackingActive ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.decisionTrackingActive ? 'text-green-400' : 'text-gray-400'}>
|
|
Decision Tracking
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.learningDatabaseConnected ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.learningDatabaseConnected ? 'text-green-400' : 'text-gray-400'}>
|
|
Database Connected
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.aiEnhancementsActive ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.aiEnhancementsActive ? 'text-green-400' : 'text-gray-400'}>
|
|
AI Enhancements
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${(learningSystem?.activeDecisions || 0) > 0 ? 'bg-blue-500' : 'bg-gray-500'}`}></div>
|
|
<span className={(learningSystem?.activeDecisions || 0) > 0 ? 'text-blue-400' : 'text-gray-400'}>
|
|
Active Decisions ({learningSystem?.activeDecisions || 0})
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{learningSystem?.report?.insights && (
|
|
<div className="bg-purple-900/20 rounded-lg p-4 border border-purple-500/30">
|
|
<div className="text-purple-300 text-sm font-medium mb-2">🎯 Learning Insights</div>
|
|
<div className="text-sm text-gray-300">
|
|
{learningSystem.report.insights.thresholds && (
|
|
<div>Current Thresholds: {JSON.stringify(learningSystem.report.insights.thresholds)}</div>
|
|
)}
|
|
{learningSystem.report.insights.confidenceLevel && (
|
|
<div>Confidence Level: {learningSystem.report.insights.confidenceLevel}%</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{learningSystem?.report?.recommendations && learningSystem.report.recommendations.length > 0 && (
|
|
<div className="bg-yellow-900/20 rounded-lg p-4 border border-yellow-500/30">
|
|
<div className="text-yellow-300 text-sm font-medium mb-2">💡 AI Recommendations</div>
|
|
<div className="space-y-1">
|
|
{learningSystem.report.recommendations.map((rec: any, index: number) => (
|
|
<div key={index} className="text-sm text-yellow-400">
|
|
• {typeof rec === 'string' ? rec : rec.message || rec.type || 'No message'}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const renderTradingStats = () => {
|
|
const stats = learningData?.realTradingData?.statistics;
|
|
const isAutomationActive = learningData?.automationStatus?.isRunning || learningData?.learningSystem?.enabled;
|
|
|
|
if (!stats) {
|
|
return (
|
|
<div className="bg-gray-800/30 rounded-lg p-4 border border-gray-600/30 mb-6">
|
|
<div className="text-gray-300 text-sm font-medium mb-2">📊 Trading Performance</div>
|
|
<div className="text-gray-400 text-sm">No trading data available yet</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="bg-gradient-to-br from-green-900/20 to-emerald-900/20 rounded-lg p-4 border border-green-500/30 mb-6">
|
|
<div className="text-green-300 text-sm font-medium mb-4 flex items-center justify-between">
|
|
<span>📊 Trading Performance</span>
|
|
{isAutomationActive && (
|
|
<span className="text-xs bg-green-500/20 text-green-400 px-2 py-1 rounded-full">LIVE</span>
|
|
)}
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-green-400">
|
|
{stats?.totalTrades || 0}
|
|
</div>
|
|
<div className="text-green-300 text-xs">Total Trades</div>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-blue-400">
|
|
{stats?.winRate?.toFixed(1) || '0.0'}%
|
|
</div>
|
|
<div className="text-blue-300 text-xs">Win Rate</div>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<div className={`text-2xl font-bold ${(stats?.totalPnl || 0) >= 0 ? 'text-green-400' : 'text-red-400'}`}>
|
|
${(stats?.totalPnl || 0) >= 0 ? '+' : ''}{(stats?.totalPnl || 0).toFixed(2)}
|
|
</div>
|
|
<div className="text-gray-300 text-xs">Total PnL</div>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<div className="text-2xl font-bold text-purple-400">
|
|
{(learningData?.realTradingData?.confidenceLevel || 0).toFixed(1)}%
|
|
</div>
|
|
<div className="text-purple-300 text-xs">AI Confidence</div>
|
|
</div>
|
|
</div>
|
|
|
|
{stats && (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Winning Trades:</span>
|
|
<span className="text-green-400">{stats.wins || 0}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Losing Trades:</span>
|
|
<span className="text-red-400">{stats.losses || 0}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Avg Win:</span>
|
|
<span className="text-green-400">${(stats.avgWin || 0).toFixed(2)}</span>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Avg Loss:</span>
|
|
<span className="text-red-400">${(stats.avgLoss || 0).toFixed(2)}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Profit Factor:</span>
|
|
<span className="text-purple-400">{(stats.profitFactor || 0).toFixed(2)}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-400">Win PnL:</span>
|
|
<span className="text-green-400">${(stats.winsPnl || 0).toFixed(2)}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 border border-purple-500/30">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center space-x-3">
|
|
<div className={`w-3 h-3 rounded-full ${learningSystem?.enabled ? 'bg-green-500 animate-pulse' : 'bg-yellow-500'}`}></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
|
|
<button
|
|
onClick={fetchLearningStatus}
|
|
className="px-3 py-1 bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded-lg transition-colors text-sm"
|
|
>
|
|
Refresh
|
|
</button>
|
|
</div>
|
|
|
|
{renderTradingStats()}
|
|
{renderLearningStatus()}
|
|
|
|
{visibility?.lastUpdateTime && (
|
|
<div className="mt-4 pt-4 border-t border-gray-600/30">
|
|
<div className="text-gray-500 text-xs">
|
|
Last updated: {new Date(visibility.lastUpdateTime).toLocaleTimeString()}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EnhancedAILearningPanel;
|