fix: replace fake learning data with real database performance metrics
This commit is contained in:
@@ -1,158 +1,172 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const PERSISTENT_DATA_FILE = path.join(process.cwd(), 'data', 'learning-persistent.json');
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const persistentData = await loadPersistentData();
|
||||
|
||||
// Get current automation status if available
|
||||
let currentStatus = null;
|
||||
let learningStatus = null;
|
||||
try {
|
||||
const { getAutomationInstance } = await import('../../../../lib/automation-singleton.js');
|
||||
const automation = await getAutomationInstance();
|
||||
if (automation) {
|
||||
currentStatus = automation.getStatus();
|
||||
|
||||
// If automation has learning status, get it too
|
||||
if (typeof automation.getLearningStatus === 'function') {
|
||||
learningStatus = await automation.getLearningStatus();
|
||||
if (learningStatus && learningStatus.report) {
|
||||
// Update some data from current learning status
|
||||
persistentData.lastUpdated = new Date().toISOString();
|
||||
persistentData.systemStatus = learningStatus.enabled ? 'active' : 'standby';
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Could not get current automation status:', error.message);
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
persistentData: {
|
||||
...persistentData,
|
||||
isLive: currentStatus?.isActive || currentStatus?.isRunning || learningStatus?.enabled || false,
|
||||
currentRunTime: currentStatus?.startTime || null,
|
||||
enhancedSummary: {
|
||||
totalDecisions: persistentData.learningDecisions,
|
||||
successRate: persistentData.winRate,
|
||||
systemConfidence: persistentData.winRate > 60 ? 0.8 : persistentData.winRate > 40 ? 0.6 : 0.3,
|
||||
isActive: persistentData.systemStatus === 'active',
|
||||
totalTrades: persistentData.totalTrades,
|
||||
totalPnL: persistentData.totalPnL
|
||||
},
|
||||
tradingStats: {
|
||||
totalTrades: persistentData.totalTrades,
|
||||
winningTrades: persistentData.winningTrades,
|
||||
losingTrades: persistentData.losingTrades,
|
||||
winRate: persistentData.winRate,
|
||||
totalPnL: persistentData.totalPnL,
|
||||
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'
|
||||
// Calculate real performance metrics
|
||||
let totalTrades = trades.length;
|
||||
let winningTrades = 0;
|
||||
let losingTrades = 0;
|
||||
let totalPnL = 0;
|
||||
let winAmounts = [];
|
||||
let lossAmounts = [];
|
||||
let bestTrade = 0;
|
||||
let worstTrade = 0;
|
||||
|
||||
trades.forEach(trade => {
|
||||
const profit = trade.profit || 0;
|
||||
totalPnL += profit;
|
||||
|
||||
if (profit > 0) {
|
||||
winningTrades++;
|
||||
winAmounts.push(profit);
|
||||
if (profit > bestTrade) bestTrade = profit;
|
||||
} else if (profit < 0) {
|
||||
losingTrades++;
|
||||
lossAmounts.push(profit);
|
||||
if (profit < worstTrade) worstTrade = profit;
|
||||
}
|
||||
});
|
||||
|
||||
const winRate = totalTrades > 0 ? (winningTrades / totalTrades) * 100 : 0;
|
||||
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;
|
||||
|
||||
// Get learning decisions count
|
||||
const learningData = await prisma.ai_learning_data.findMany({
|
||||
where: {
|
||||
createdAt: {
|
||||
gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // Last 30 days
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 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) {
|
||||
console.error('Error in persistent status API:', error);
|
||||
await prisma.$disconnect();
|
||||
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error.message,
|
||||
persistentData: defaultPersistentData
|
||||
error: error.message
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request) {
|
||||
try {
|
||||
const updateData = await request.json();
|
||||
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);
|
||||
|
||||
// For updating specific metrics (not implemented in this version)
|
||||
return NextResponse.json({
|
||||
success: saved,
|
||||
message: saved ? 'Persistent data updated' : 'Failed to save data',
|
||||
data: updatedData
|
||||
});
|
||||
success: false,
|
||||
message: 'POST method not implemented - data comes from database'
|
||||
}, { status: 501 });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error updating persistent data:', error);
|
||||
|
||||
Reference in New Issue
Block a user