Files
trading_bot_v3/lib/automation-with-learning.js
mindesbunister 44968c3bb3 feat: integrate AI learning system with trading automation
- AutomationWithLearning class with decision recording and outcome assessment
- Enhanced API endpoints with learning status visibility
- Singleton automation manager for seamless learning system integration
- EnhancedAILearningPanel component for real-time learning visibility
- Learning-enhanced trade execution with AI adjustments to SL/TP
- Automatic decision tracking and outcome-based learning

 Key Features:
- Records trading decisions before execution
- Enhances analysis with learned patterns
- Tracks trade outcomes for continuous improvement
- Provides full visibility into AI decision-making process
- Integrates SimplifiedStopLossLearner with real trading flow

- Whether learning system is active
- How many decisions are being tracked
- Real-time learning statistics and insights
- AI enhancements applied to trading decisions
2025-07-27 12:11:40 +02:00

456 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 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())
}
};
}
module.exports = AutomationWithLearning;
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 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
const tradeResult = await super.executeTrade(enhancedAnalysis);
// 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,
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,
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,
distanceFromSL,
marketConditions: {
recommendation: analysis.recommendation,
confidence: analysis.confidence,
timeframe: this.config.selectedTimeframes
}
});
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
});
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;
}
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
};
}
}
// Override getStatus to include learning information
getStatus() {
const baseStatus = super.getStatus();
return {
...baseStatus,
learningSystem: {
enabled: this.learningEnabled,
hasLearner: !!this.learner,
activeDecisions: this.activeTrades.size,
trackedTrades: Array.from(this.activeTrades.keys())
}
};
}
}
module.exports = AutomationWithLearning;