- Created persistent learning status API with trading statistics - Added comprehensive PnL and win rate display to AI Learning panel - Implemented trading stats tracking with win/loss ratios - Added persistent data storage for historical trading performance - Enhanced learning panel with real-time trading metrics - Fixed learning data visibility when bot is not running - Added sample trading data for demonstration
163 lines
4.9 KiB
JavaScript
163 lines
4.9 KiB
JavaScript
import { NextResponse } from 'next/server';
|
|
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
const persistentData = await loadPersistentData();
|
|
|
|
// Get current automation status if available
|
|
let currentStatus = 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') {
|
|
const 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';
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.warn('Could not get current automation status:', error.message);
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
persistentData: {
|
|
...persistentData,
|
|
isLive: currentStatus?.isActive || 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'
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error in persistent status API:', error);
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: error.message,
|
|
persistentData: defaultPersistentData
|
|
}, { 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);
|
|
|
|
return NextResponse.json({
|
|
success: saved,
|
|
message: saved ? 'Persistent data updated' : 'Failed to save data',
|
|
data: updatedData
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error updating persistent data:', error);
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: error.message
|
|
}, { status: 500 });
|
|
}
|
|
} |