fix: replace fake learning data with real database performance metrics

This commit is contained in:
mindesbunister
2025-07-30 09:01:00 +02:00
parent c1da9fc01b
commit d39ddaff40
2 changed files with 147 additions and 133 deletions

View File

@@ -1,158 +1,172 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import fs from 'fs/promises'; import { PrismaClient } from '@prisma/client';
import path from 'path';
const PERSISTENT_DATA_FILE = path.join(process.cwd(), 'data', 'learning-persistent.json'); const prisma = new PrismaClient();
// Default persistent data structure
const defaultPersistentData = {
totalTrades: 0,
winningTrades: 0,
losingTrades: 0,
totalPnL: 0,
winRate: 0,
avgWinAmount: 0,
avgLossAmount: 0,
bestTrade: 0,
worstTrade: 0,
learningDecisions: 0,
aiEnhancements: 0,
riskThresholds: {
emergency: 1,
risk: 2,
mediumRisk: 5
},
lastUpdated: new Date().toISOString(),
systemStatus: 'learning',
dataCollected: true
};
async function ensureDataDirectory() {
const dataDir = path.join(process.cwd(), 'data');
try {
await fs.access(dataDir);
} catch {
await fs.mkdir(dataDir, { recursive: true });
}
}
async function loadPersistentData() {
try {
await ensureDataDirectory();
const data = await fs.readFile(PERSISTENT_DATA_FILE, 'utf8');
return JSON.parse(data);
} catch (error) {
// File doesn't exist or is invalid, return default data
return defaultPersistentData;
}
}
async function savePersistentData(data) {
try {
await ensureDataDirectory();
await fs.writeFile(PERSISTENT_DATA_FILE, JSON.stringify(data, null, 2));
return true;
} catch (error) {
console.error('Error saving persistent data:', error);
return false;
}
}
export async function GET() { export async function GET() {
try { try {
const persistentData = await loadPersistentData(); // Get real trading data from database
const trades = await prisma.trades.findMany({
orderBy: { createdAt: 'desc' },
take: 50, // Last 50 trades for meaningful statistics
select: {
id: true,
symbol: true,
side: true,
amount: true,
entryPrice: true,
exitPrice: true,
profit: true,
leverage: true,
confidence: true,
createdAt: true,
outcome: true
}
});
// Get current automation status if available // Calculate real performance metrics
let currentStatus = null; let totalTrades = trades.length;
let learningStatus = null; let winningTrades = 0;
try { let losingTrades = 0;
const { getAutomationInstance } = await import('../../../../lib/automation-singleton.js'); let totalPnL = 0;
const automation = await getAutomationInstance(); let winAmounts = [];
if (automation) { let lossAmounts = [];
currentStatus = automation.getStatus(); let bestTrade = 0;
let worstTrade = 0;
// If automation has learning status, get it too trades.forEach(trade => {
if (typeof automation.getLearningStatus === 'function') { const profit = trade.profit || 0;
learningStatus = await automation.getLearningStatus(); totalPnL += profit;
if (learningStatus && learningStatus.report) {
// Update some data from current learning status
persistentData.lastUpdated = new Date().toISOString();
persistentData.systemStatus = learningStatus.enabled ? 'active' : 'standby';
}
}
}
} catch (error) {
console.warn('Could not get current automation status:', error.message);
}
return NextResponse.json({ if (profit > 0) {
success: true, winningTrades++;
persistentData: { winAmounts.push(profit);
...persistentData, if (profit > bestTrade) bestTrade = profit;
isLive: currentStatus?.isActive || currentStatus?.isRunning || learningStatus?.enabled || false, } else if (profit < 0) {
currentRunTime: currentStatus?.startTime || null, losingTrades++;
enhancedSummary: { lossAmounts.push(profit);
totalDecisions: persistentData.learningDecisions, if (profit < worstTrade) worstTrade = profit;
successRate: persistentData.winRate, }
systemConfidence: persistentData.winRate > 60 ? 0.8 : persistentData.winRate > 40 ? 0.6 : 0.3, });
isActive: persistentData.systemStatus === 'active',
totalTrades: persistentData.totalTrades, const winRate = totalTrades > 0 ? (winningTrades / totalTrades) * 100 : 0;
totalPnL: persistentData.totalPnL const avgWinAmount = winAmounts.length > 0 ? winAmounts.reduce((a, b) => a + b, 0) / winAmounts.length : 0;
}, const avgLossAmount = lossAmounts.length > 0 ? lossAmounts.reduce((a, b) => a + b, 0) / lossAmounts.length : 0;
tradingStats: {
totalTrades: persistentData.totalTrades, // Get learning decisions count
winningTrades: persistentData.winningTrades, const learningData = await prisma.ai_learning_data.findMany({
losingTrades: persistentData.losingTrades, where: {
winRate: persistentData.winRate, createdAt: {
totalPnL: persistentData.totalPnL, gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // Last 30 days
avgWinAmount: persistentData.avgWinAmount,
avgLossAmount: persistentData.avgLossAmount,
bestTrade: persistentData.bestTrade,
worstTrade: persistentData.worstTrade
},
learningMetrics: {
totalDecisions: persistentData.learningDecisions,
aiEnhancements: persistentData.aiEnhancements,
riskThresholds: persistentData.riskThresholds,
dataQuality: persistentData.totalTrades > 10 ? 'Good' : persistentData.totalTrades > 5 ? 'Fair' : 'Limited'
} }
} }
}); });
// Get recent trades for display
const recentTrades = trades.slice(0, 3).map(trade => ({
id: trade.id,
symbol: trade.symbol,
type: trade.side?.toUpperCase() || 'UNKNOWN',
entry: trade.entryPrice || 0,
exit: trade.exitPrice || 0,
pnl: trade.profit || 0,
outcome: (trade.profit || 0) > 0 ? 'WIN' : (trade.profit || 0) < 0 ? 'LOSS' : 'BREAK-EVEN',
timestamp: trade.createdAt.toISOString()
}));
// Get current automation status
let isActive = false;
let currentRunTime = null;
try {
const { getAutomationInstance } = await import('../../../../lib/automation-singleton.js');
const automation = await getAutomationInstance();
if (automation) {
isActive = automation.isRunning || false;
currentRunTime = automation.stats?.startTime || null;
}
} catch (error) {
console.warn('Could not get automation status:', error.message);
}
const persistentData = {
totalTrades,
winningTrades,
losingTrades,
totalPnL: Math.round(totalPnL * 100) / 100,
winRate: Math.round(winRate * 10) / 10,
avgWinAmount: Math.round(avgWinAmount * 100) / 100,
avgLossAmount: Math.round(avgLossAmount * 100) / 100,
bestTrade: Math.round(bestTrade * 100) / 100,
worstTrade: Math.round(worstTrade * 100) / 100,
learningDecisions: learningData.length,
aiEnhancements: Math.floor(learningData.length / 7), // Enhancement every 7 decisions
riskThresholds: {
emergency: totalPnL < -50 ? 1 : 3,
risk: totalPnL < -30 ? 2 : 5,
mediumRisk: totalPnL < -10 ? 5 : 8
},
lastUpdated: new Date().toISOString(),
systemStatus: isActive ? 'active' : 'standby',
dataCollected: totalTrades > 0,
recentTrades,
isLive: isActive,
currentRunTime,
enhancedSummary: {
totalDecisions: learningData.length,
successRate: winRate,
systemConfidence: winRate > 60 ? 0.8 : winRate > 40 ? 0.6 : winRate > 20 ? 0.3 : 0.1,
isActive,
totalTrades,
totalPnL: Math.round(totalPnL * 100) / 100
},
tradingStats: {
totalTrades,
winningTrades,
losingTrades,
winRate: Math.round(winRate * 10) / 10,
totalPnL: Math.round(totalPnL * 100) / 100,
avgWinAmount: Math.round(avgWinAmount * 100) / 100,
avgLossAmount: Math.round(avgLossAmount * 100) / 100,
bestTrade: Math.round(bestTrade * 100) / 100,
worstTrade: Math.round(worstTrade * 100) / 100
},
learningMetrics: {
totalDecisions: learningData.length,
aiEnhancements: Math.floor(learningData.length / 7),
riskThresholds: {
emergency: totalPnL < -50 ? 1 : 3,
risk: totalPnL < -30 ? 2 : 5,
mediumRisk: totalPnL < -10 ? 5 : 8
},
dataQuality: totalTrades > 10 ? 'Good' : totalTrades > 5 ? 'Fair' : 'Limited'
}
};
await prisma.$disconnect();
return NextResponse.json({
success: true,
persistentData
});
} catch (error) { } catch (error) {
console.error('Error in persistent status API:', error); console.error('Error in persistent status API:', error);
await prisma.$disconnect();
return NextResponse.json({ return NextResponse.json({
success: false, success: false,
error: error.message, error: error.message
persistentData: defaultPersistentData
}, { status: 500 }); }, { status: 500 });
} }
} }
export async function POST(request) { export async function POST(request) {
try { try {
const updateData = await request.json(); // For updating specific metrics (not implemented in this version)
const currentData = await loadPersistentData();
// Update the persistent data
const updatedData = {
...currentData,
...updateData,
lastUpdated: new Date().toISOString()
};
// Recalculate derived metrics
if (updatedData.totalTrades > 0) {
updatedData.winRate = (updatedData.winningTrades / updatedData.totalTrades) * 100;
}
const saved = await savePersistentData(updatedData);
return NextResponse.json({ return NextResponse.json({
success: saved, success: false,
message: saved ? 'Persistent data updated' : 'Failed to save data', message: 'POST method not implemented - data comes from database'
data: updatedData }, { status: 501 });
});
} catch (error) { } catch (error) {
console.error('Error updating persistent data:', error); console.error('Error updating persistent data:', error);

Binary file not shown.