Files
trading_bot_v3/lib/automation-with-learning-v2.js
mindesbunister d5bf485e72 fix: Complete automation v2 page runtime error fixes
- Fixed ES modules error by converting automation-with-learning-v2.js to pure ES6
- Fixed singleton pattern in automation-singleton.js for proper async handling
- Fixed EnhancedAILearningPanel to handle recommendation objects correctly
- Updated API routes to use correct import paths (../../../../lib/)
- Created proper db.js utility with ES6 exports
- Fixed simplified-stop-loss-learner imports and exports

 Automation v2 page now loads without errors
 AI learning system fully integrated and operational
 Learning status API working with detailed reports
 Recommendation rendering fixed for object structure
2025-07-27 12:38:32 +02:00

449 lines
15 KiB
JavaScript

// Enhanced automation with integrated AI learning system
// Dynamic import for ES6 modules
async function importSimpleAutomation() {
try {
const module = await import('./simple-automation.js');
// Extract the class from the singleton instance
return module.simpleAutomation.constructor;
} catch (error) {
console.warn('⚠️ Could not import SimpleAutomation, using fallback');
// Fallback - create a basic class structure
return class BasicAutomation {
constructor() {
this.isRunning = false;
this.config = null;
this.stats = { totalCycles: 0, totalTrades: 0 };
}
async start(config) {
return { success: false, message: 'Base automation not available' };
}
async stop() {
return { success: true, message: 'Stopped' };
}
getStatus() {
return { isRunning: this.isRunning, stats: this.stats };
}
};
}
}
// Import learning system
async function importSimplifiedStopLossLearner() {
try {
const { SimplifiedStopLossLearner } = await import('./simplified-stop-loss-learner-fixed.js');
return SimplifiedStopLossLearner;
} catch (error) {
console.warn('⚠️ SimplifiedStopLossLearner not available, continuing without learning');
return null;
}
}
class AutomationWithLearning {
constructor() {
this.baseAutomation = null;
this.learner = null;
this.activeTrades = new Map(); // Track active trades for outcome assessment
this.learningDecisions = new Map(); // Track decisions for learning
this.learningEnabled = false;
this.isRunning = false;
this.config = null;
this.stats = { totalCycles: 0, totalTrades: 0 };
}
async initializeBaseAutomation() {
if (!this.baseAutomation) {
const SimpleAutomationClass = await importSimpleAutomation();
this.baseAutomation = new SimpleAutomationClass();
}
return this.baseAutomation;
}
async initializeLearningSystem() {
try {
const SimplifiedStopLossLearnerClass = await importSimplifiedStopLossLearner();
if (SimplifiedStopLossLearnerClass) {
this.learner = new SimplifiedStopLossLearnerClass();
console.log('✅ AI Learning System initialized successfully');
// Generate initial learning report
if (typeof this.learner.generateLearningReport === 'function') {
const report = await this.learner.generateLearningReport();
console.log('📊 Current Learning Status:', report.summary);
}
return true;
}
} catch (error) {
console.warn('⚠️ Could not initialize learning system:', error.message);
}
return false;
}
async start(config) {
try {
// Initialize base automation
await this.initializeBaseAutomation();
// Initialize learning system
await this.initializeLearningSystem();
// Use base automation if available, otherwise implement basic functionality
let result;
if (this.baseAutomation && typeof this.baseAutomation.start === 'function') {
result = await this.baseAutomation.start(config);
} else {
// Basic start functionality
this.isRunning = true;
this.config = config;
result = { success: true, message: 'Basic automation started' };
}
if (result.success && this.learner) {
console.log('🧠 AI LEARNING SYSTEM: Activated and ready to learn from trades');
console.log('📊 The system will now record decisions and improve over time');
this.learningEnabled = true;
}
return result;
} catch (error) {
console.error('❌ Error starting automation with learning:', error);
return { success: false, message: error.message };
}
}
async stop() {
try {
let result;
if (this.baseAutomation && typeof this.baseAutomation.stop === 'function') {
result = await this.baseAutomation.stop();
} else {
this.isRunning = false;
result = { success: true, message: 'Basic automation stopped' };
}
this.learningEnabled = false;
return result;
} catch (error) {
console.error('❌ Error stopping automation:', error);
return { success: false, message: error.message };
}
}
getStatus() {
let baseStatus;
if (this.baseAutomation && typeof this.baseAutomation.getStatus === 'function') {
baseStatus = this.baseAutomation.getStatus();
} else {
baseStatus = {
isRunning: this.isRunning,
config: this.config,
stats: this.stats
};
}
return {
...baseStatus,
learningSystem: {
enabled: this.learningEnabled,
hasLearner: !!this.learner,
activeDecisions: this.activeTrades.size,
trackedTrades: Array.from(this.activeTrades.keys())
}
};
}
async getLearningStatus() {
if (!this.learningEnabled || !this.learner) {
return {
enabled: false,
message: 'Learning system not available'
};
}
try {
let report = null;
// Try to get comprehensive learning report
if (typeof this.learner.generateLearningReport === 'function') {
report = await this.learner.generateLearningReport();
} else if (typeof this.learner.getLearningStatus === 'function') {
report = await this.learner.getLearningStatus();
}
return {
enabled: true,
learningActive: this.learningEnabled,
activeDecisions: this.activeTrades.size,
report: report || { summary: { message: 'Learning system active but no data available yet' } }
};
} catch (error) {
console.error('❌ Error getting learning status:', error);
return {
enabled: true,
learningActive: this.learningEnabled,
error: error.message
};
}
}
async executeTrade(analysis) {
try {
console.log('🧠 LEARNING-ENHANCED TRADE EXECUTION');
// Record decision before execution for learning
let decisionId = null;
if (this.learningEnabled && this.learner) {
decisionId = await this.recordTradingDecision(analysis);
}
// Enhance analysis with learning-based adjustments
const enhancedAnalysis = await this.enhanceAnalysisWithLearning(analysis);
// Execute the trade using enhanced analysis
let tradeResult;
if (this.baseAutomation && typeof this.baseAutomation.executeTrade === 'function') {
tradeResult = await this.baseAutomation.executeTrade(enhancedAnalysis);
} else {
// Basic trade execution simulation
tradeResult = {
success: true,
message: 'Trade simulated (learning system active)',
simulation: true
};
}
// Track trade for outcome assessment
if (tradeResult.success && decisionId) {
this.trackTradeForLearning(decisionId, tradeResult, enhancedAnalysis);
}
return tradeResult;
} catch (error) {
console.error('❌ Error in learning-enhanced trade execution:', error);
return { success: false, error: error.message };
}
}
async recordTradingDecision(analysis) {
if (!this.learner || typeof this.learner.recordDecision !== 'function') {
return null;
}
try {
const decisionData = {
symbol: this.config?.symbol || 'SOLUSD',
recommendation: analysis.recommendation,
confidence: analysis.confidence,
stopLoss: this.extractStopLoss(analysis),
takeProfit: this.extractTakeProfit(analysis),
entryPrice: analysis.entry?.price || analysis.currentPrice,
marketConditions: {
timeframe: this.config?.selectedTimeframes || ['1h'],
analysis: analysis.reasoning || analysis.summary
},
timestamp: new Date().toISOString()
};
const decisionId = await this.learner.recordDecision(decisionData);
console.log(`📝 LEARNING: Recorded decision ${decisionId}`);
return decisionId;
} catch (error) {
console.error('❌ Error recording decision:', error);
return null;
}
}
async enhanceAnalysisWithLearning(analysis) {
if (!this.learningEnabled || !this.learner) {
console.log('📊 Using original analysis (learning not available)');
return analysis;
}
try {
// Get learning-based recommendations if available
if (typeof this.learner.getSmartRecommendation === 'function') {
const currentPrice = analysis.entry?.price || analysis.currentPrice || 178;
const originalStopLoss = this.extractStopLoss(analysis);
if (originalStopLoss) {
const distanceFromSL = Math.abs(currentPrice - originalStopLoss);
const learningRecommendation = await this.learner.getSmartRecommendation({
symbol: this.config?.symbol || 'SOLUSD',
distanceFromSL,
marketConditions: {
recommendation: analysis.recommendation,
confidence: analysis.confidence,
timeframe: this.config?.selectedTimeframes || ['1h']
}
});
if (learningRecommendation && learningRecommendation.confidence > 70) {
console.log(`🧠 LEARNING ENHANCEMENT: ${learningRecommendation.action} (${learningRecommendation.confidence}% confidence)`);
console.log(`💡 Reasoning: ${learningRecommendation.reasoning}`);
// Apply learning-based adjustments
if (learningRecommendation.action === 'TIGHTEN_STOP_LOSS') {
analysis = this.adjustStopLoss(analysis, learningRecommendation.suggestedValue);
} else if (learningRecommendation.action === 'ADJUST_TAKE_PROFIT') {
analysis = this.adjustTakeProfit(analysis, learningRecommendation.suggestedValue);
}
// Add learning metadata to analysis
analysis.learningEnhanced = true;
analysis.learningConfidence = learningRecommendation.confidence;
analysis.learningReasoning = learningRecommendation.reasoning;
}
}
}
return analysis;
} catch (error) {
console.error('❌ Error enhancing analysis with learning:', error);
return analysis; // Return original analysis if learning fails
}
}
adjustStopLoss(analysis, newStopLoss) {
if (newStopLoss) {
if (analysis.stopLoss && typeof analysis.stopLoss === 'object') {
analysis.stopLoss.price = newStopLoss;
} else {
analysis.stopLoss = newStopLoss;
}
console.log(`🔧 LEARNING ADJUSTMENT: Stop-loss adjusted to $${newStopLoss}`);
}
return analysis;
}
adjustTakeProfit(analysis, newTakeProfit) {
if (newTakeProfit) {
if (analysis.takeProfits && analysis.takeProfits.tp1) {
analysis.takeProfits.tp1.price = newTakeProfit;
} else if (analysis.takeProfit) {
analysis.takeProfit = newTakeProfit;
} else {
analysis.takeProfit = newTakeProfit;
}
console.log(`🎯 LEARNING ADJUSTMENT: Take-profit adjusted to $${newTakeProfit}`);
}
return analysis;
}
trackTradeForLearning(decisionId, tradeResult, analysis) {
if (!decisionId) return;
this.activeTrades.set(decisionId, {
tradeResult,
analysis,
timestamp: new Date().toISOString(),
symbol: this.config?.symbol || 'SOLUSD'
});
console.log(`📊 LEARNING: Tracking trade ${decisionId} for outcome assessment`);
// Set up outcome assessment check (will check position status later)
setTimeout(() => {
this.assessTradeOutcome(decisionId);
}, 300000); // Check after 5 minutes
}
async assessTradeOutcome(decisionId) {
if (!this.learningEnabled || !this.learner || !this.activeTrades.has(decisionId)) {
return;
}
try {
const tradeInfo = this.activeTrades.get(decisionId);
// Check current position status via API
const baseUrl = process.env.INTERNAL_API_URL || 'http://localhost:3000';
const response = await fetch(`${baseUrl}/api/automation/position-monitor`);
const positionData = await response.json();
let outcome = null;
let actualPnL = 0;
if (positionData.success) {
// Determine outcome based on position status
if (!positionData.monitor.hasPosition) {
// Position closed - check if it was profitable
outcome = 'POSITION_CLOSED';
// Try to get actual P&L from position history
try {
const historyResponse = await fetch(`${baseUrl}/api/drift/position-history`);
const historyData = await historyResponse.json();
if (historyData.success && historyData.trades.length > 0) {
// Find the most recent trade
const recentTrade = historyData.trades[0];
actualPnL = recentTrade.pnl;
outcome = actualPnL > 0 ? 'WIN' : 'LOSS';
}
} catch (historyError) {
console.warn('⚠️ Could not fetch trade history for outcome assessment');
}
} else {
// Position still open - check if it's profitable
const currentPnL = positionData.monitor.position?.unrealizedPnl || 0;
actualPnL = currentPnL;
outcome = currentPnL > 0 ? 'CURRENTLY_PROFITABLE' : 'CURRENTLY_LOSING';
}
}
// Record outcome for learning
if (outcome && typeof this.learner.assessDecisionOutcome === 'function') {
const outcomeData = {
decisionId,
outcome,
actualPnL,
timestamp: new Date().toISOString(),
positionInfo: positionData.monitor
};
await this.learner.assessDecisionOutcome(outcomeData);
console.log(`🧠 LEARNING: Assessed outcome for decision ${decisionId}: ${outcome} (P&L: $${actualPnL.toFixed(2)})`);
// Clean up tracked trade
this.activeTrades.delete(decisionId);
}
} catch (error) {
console.error('❌ Error assessing trade outcome:', error);
}
}
extractStopLoss(analysis) {
if (analysis.stopLoss && typeof analysis.stopLoss === 'object') {
return analysis.stopLoss.price;
} else if (analysis.stopLoss && typeof analysis.stopLoss === 'number') {
return analysis.stopLoss;
} else if (analysis.levels?.stopLoss) {
return analysis.levels.stopLoss;
}
return null;
}
extractTakeProfit(analysis) {
if (analysis.takeProfits && analysis.takeProfits.tp1?.price) {
return analysis.takeProfits.tp1.price;
} else if (analysis.takeProfit && typeof analysis.takeProfit === 'number') {
return analysis.takeProfit;
} else if (analysis.levels?.takeProfit) {
return analysis.levels.takeProfit;
}
return null;
}
}
export default AutomationWithLearning;