178 lines
5.5 KiB
JavaScript
178 lines
5.5 KiB
JavaScript
import { NextResponse } from 'next/server';
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
export async function GET() {
|
|
try {
|
|
// 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
|
|
}
|
|
});
|
|
|
|
// 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
|
|
}, { status: 500 });
|
|
}
|
|
}
|
|
|
|
export async function POST(request) {
|
|
try {
|
|
// For updating specific metrics (not implemented in this version)
|
|
return NextResponse.json({
|
|
success: false,
|
|
message: 'POST method not implemented - data comes from database'
|
|
}, { status: 501 });
|
|
|
|
} catch (error) {
|
|
console.error('Error updating persistent data:', error);
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: error.message
|
|
}, { status: 500 });
|
|
}
|
|
} |