Add persistent learning data and PnL display
- 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
This commit is contained in:
132
lib/persistent-learning-data.js
Normal file
132
lib/persistent-learning-data.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// Helper functions for updating persistent learning data
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const PERSISTENT_DATA_FILE = path.join(process.cwd(), 'data', 'learning-persistent.json');
|
||||
|
||||
async function loadPersistentData() {
|
||||
try {
|
||||
const data = await fs.readFile(PERSISTENT_DATA_FILE, 'utf8');
|
||||
return JSON.parse(data);
|
||||
} catch (error) {
|
||||
// Return default structure if file doesn't exist
|
||||
return {
|
||||
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 savePersistentData(data) {
|
||||
try {
|
||||
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 updateTradingStats(tradeData) {
|
||||
try {
|
||||
const persistentData = await loadPersistentData();
|
||||
|
||||
// Update trade counts
|
||||
persistentData.totalTrades += 1;
|
||||
|
||||
// Determine if trade was winning or losing
|
||||
const isWin = tradeData.pnl > 0;
|
||||
if (isWin) {
|
||||
persistentData.winningTrades += 1;
|
||||
} else {
|
||||
persistentData.losingTrades += 1;
|
||||
}
|
||||
|
||||
// Update PnL
|
||||
persistentData.totalPnL += tradeData.pnl;
|
||||
|
||||
// Update best/worst trades
|
||||
if (tradeData.pnl > persistentData.bestTrade) {
|
||||
persistentData.bestTrade = tradeData.pnl;
|
||||
}
|
||||
if (tradeData.pnl < persistentData.worstTrade) {
|
||||
persistentData.worstTrade = tradeData.pnl;
|
||||
}
|
||||
|
||||
// Recalculate averages and win rate
|
||||
persistentData.winRate = (persistentData.winningTrades / persistentData.totalTrades) * 100;
|
||||
|
||||
if (persistentData.winningTrades > 0) {
|
||||
// Calculate average win amount (we need to track this separately for accuracy)
|
||||
const winTrades = persistentData.winTrades || [];
|
||||
winTrades.push(isWin ? tradeData.pnl : null);
|
||||
const wins = winTrades.filter(t => t !== null && t > 0);
|
||||
persistentData.avgWinAmount = wins.reduce((sum, win) => sum + win, 0) / wins.length;
|
||||
}
|
||||
|
||||
if (persistentData.losingTrades > 0) {
|
||||
// Calculate average loss amount
|
||||
const lossTrades = persistentData.lossTrades || [];
|
||||
lossTrades.push(!isWin ? tradeData.pnl : null);
|
||||
const losses = lossTrades.filter(t => t !== null && t < 0);
|
||||
persistentData.avgLossAmount = losses.reduce((sum, loss) => sum + loss, 0) / losses.length;
|
||||
}
|
||||
|
||||
// Update timestamp
|
||||
persistentData.lastUpdated = new Date().toISOString();
|
||||
persistentData.systemStatus = 'active';
|
||||
|
||||
// Save updated data
|
||||
await savePersistentData(persistentData);
|
||||
|
||||
console.log(`📊 Persistent data updated: Trade PnL ${tradeData.pnl}, Total: ${persistentData.totalTrades} trades, ${persistentData.winRate.toFixed(1)}% win rate`);
|
||||
|
||||
return persistentData;
|
||||
} catch (error) {
|
||||
console.error('Error updating trading stats:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateLearningDecision() {
|
||||
try {
|
||||
const persistentData = await loadPersistentData();
|
||||
persistentData.learningDecisions += 1;
|
||||
persistentData.lastUpdated = new Date().toISOString();
|
||||
await savePersistentData(persistentData);
|
||||
return persistentData;
|
||||
} catch (error) {
|
||||
console.error('Error updating learning decision count:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateAIEnhancement() {
|
||||
try {
|
||||
const persistentData = await loadPersistentData();
|
||||
persistentData.aiEnhancements += 1;
|
||||
persistentData.lastUpdated = new Date().toISOString();
|
||||
await savePersistentData(persistentData);
|
||||
return persistentData;
|
||||
} catch (error) {
|
||||
console.error('Error updating AI enhancement count:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user