🧠 Implement AI Learning System for Stop Loss Decisions
- Add stop-loss-decision-learner.js: Core learning engine
- Add enhanced-autonomous-risk-manager.js: Learning-enhanced decisions
- Add AI learning API and dashboard components
- Add database schema for decision tracking
- Integrate with existing automation system
- Demo scripts and documentation
Result: AI learns from every decision and improves over time! 🚀
This commit is contained in:
569
lib/enhanced-autonomous-risk-manager.js
Normal file
569
lib/enhanced-autonomous-risk-manager.js
Normal file
@@ -0,0 +1,569 @@
|
||||
/**
|
||||
* Enhanced Autonomous AI Risk Management System with Learning
|
||||
*
|
||||
* This system automatically handles risk situations AND learns from every decision.
|
||||
* It records decisions, tracks outcomes, and continuously improves its decision-making.
|
||||
*/
|
||||
|
||||
const StopLossDecisionLearner = require('./stop-loss-decision-learner');
|
||||
const { exec } = require('child_process');
|
||||
const util = require('util');
|
||||
const execAsync = util.promisify(exec);
|
||||
|
||||
class EnhancedAutonomousRiskManager {
|
||||
constructor() {
|
||||
this.isActive = false;
|
||||
this.learner = new StopLossDecisionLearner();
|
||||
this.emergencyThreshold = 1.0; // Will be updated by learning system
|
||||
this.riskThreshold = 2.0;
|
||||
this.mediumRiskThreshold = 5.0;
|
||||
this.pendingDecisions = new Map(); // Track decisions awaiting outcomes
|
||||
this.lastAnalysis = null;
|
||||
}
|
||||
|
||||
async log(message) {
|
||||
const timestamp = new Date().toISOString();
|
||||
console.log(`[${timestamp}] 🤖 Enhanced Risk AI: ${message}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main analysis function that integrates learning-based decision making
|
||||
*/
|
||||
async analyzePosition(monitor) {
|
||||
try {
|
||||
if (!monitor || !monitor.hasPosition) {
|
||||
return {
|
||||
action: 'NO_ACTION',
|
||||
reasoning: 'No position to analyze',
|
||||
confidence: 1.0
|
||||
};
|
||||
}
|
||||
|
||||
const { position, stopLossProximity } = monitor;
|
||||
const distance = parseFloat(stopLossProximity.distancePercent);
|
||||
|
||||
// Update thresholds based on learning
|
||||
await this.updateThresholdsFromLearning();
|
||||
|
||||
// Get AI recommendation based on learned patterns
|
||||
const smartRecommendation = await this.learner.getSmartRecommendation({
|
||||
distanceFromSL: distance,
|
||||
symbol: position.symbol,
|
||||
marketConditions: {
|
||||
price: position.entryPrice, // Current price context
|
||||
unrealizedPnl: position.unrealizedPnl,
|
||||
side: position.side
|
||||
}
|
||||
});
|
||||
|
||||
let decision;
|
||||
|
||||
// Enhanced decision logic using learning
|
||||
if (distance < this.emergencyThreshold) {
|
||||
decision = await this.handleEmergencyRisk(monitor, smartRecommendation);
|
||||
} else if (distance < this.riskThreshold) {
|
||||
decision = await this.handleHighRisk(monitor, smartRecommendation);
|
||||
} else if (distance < this.mediumRiskThreshold) {
|
||||
decision = await this.handleMediumRisk(monitor, smartRecommendation);
|
||||
} else {
|
||||
decision = await this.handleSafePosition(monitor, smartRecommendation);
|
||||
}
|
||||
|
||||
// Record this decision for learning
|
||||
const decisionId = await this.recordDecisionForLearning(monitor, decision, smartRecommendation);
|
||||
decision.decisionId = decisionId;
|
||||
|
||||
this.lastAnalysis = { monitor, decision, timestamp: new Date() };
|
||||
|
||||
return decision;
|
||||
} catch (error) {
|
||||
await this.log(`❌ Error in position analysis: ${error.message}`);
|
||||
return {
|
||||
action: 'ERROR',
|
||||
reasoning: `Analysis error: ${error.message}`,
|
||||
confidence: 0.1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async handleEmergencyRisk(monitor, smartRecommendation) {
|
||||
const { position, stopLossProximity } = monitor;
|
||||
const distance = parseFloat(stopLossProximity.distancePercent);
|
||||
|
||||
await this.log(`🚨 EMERGENCY: Position ${distance}% from stop loss!`);
|
||||
|
||||
// Use learning-based recommendation if highly confident
|
||||
if (smartRecommendation.learningBased && smartRecommendation.confidence > 0.8) {
|
||||
await this.log(`🧠 Using learned strategy: ${smartRecommendation.suggestedAction} (${(smartRecommendation.confidence * 100).toFixed(1)}% confidence)`);
|
||||
|
||||
return {
|
||||
action: smartRecommendation.suggestedAction,
|
||||
reasoning: `AI Learning: ${smartRecommendation.reasoning}`,
|
||||
confidence: smartRecommendation.confidence,
|
||||
urgency: 'CRITICAL',
|
||||
learningEnhanced: true,
|
||||
supportingData: smartRecommendation.supportingData
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback to rule-based emergency logic
|
||||
return {
|
||||
action: 'EMERGENCY_EXIT',
|
||||
reasoning: 'Price critically close to stop loss. Autonomous exit to preserve capital.',
|
||||
confidence: 0.9,
|
||||
urgency: 'CRITICAL',
|
||||
parameters: {
|
||||
exitPercentage: 100,
|
||||
maxSlippage: 0.5
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async handleHighRisk(monitor, smartRecommendation) {
|
||||
const { position, stopLossProximity } = monitor;
|
||||
const distance = parseFloat(stopLossProximity.distancePercent);
|
||||
|
||||
await this.log(`⚠️ HIGH RISK: Position ${distance}% from stop loss`);
|
||||
|
||||
// Check learning recommendation
|
||||
if (smartRecommendation.learningBased && smartRecommendation.confidence > 0.7) {
|
||||
return {
|
||||
action: smartRecommendation.suggestedAction,
|
||||
reasoning: `AI Learning: ${smartRecommendation.reasoning}`,
|
||||
confidence: smartRecommendation.confidence,
|
||||
urgency: 'HIGH',
|
||||
learningEnhanced: true
|
||||
};
|
||||
}
|
||||
|
||||
// Enhanced market analysis for high-risk situations
|
||||
const marketAnalysis = await this.analyzeMarketConditions(position.symbol);
|
||||
|
||||
if (marketAnalysis.trend === 'BULLISH' && position.side === 'LONG') {
|
||||
return {
|
||||
action: 'TIGHTEN_STOP_LOSS',
|
||||
reasoning: 'Market still favorable. Tightening stop loss for better risk management.',
|
||||
confidence: 0.7,
|
||||
urgency: 'HIGH',
|
||||
parameters: {
|
||||
newStopLossDistance: distance * 0.7 // Tighten by 30%
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
action: 'PARTIAL_EXIT',
|
||||
reasoning: 'Market conditions uncertain. Reducing position size to manage risk.',
|
||||
confidence: 0.75,
|
||||
urgency: 'HIGH',
|
||||
parameters: {
|
||||
exitPercentage: 50,
|
||||
keepStopLoss: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async handleMediumRisk(monitor, smartRecommendation) {
|
||||
const { position, stopLossProximity } = monitor;
|
||||
const distance = parseFloat(stopLossProximity.distancePercent);
|
||||
|
||||
await this.log(`🟡 MEDIUM RISK: Position ${distance}% from stop loss`);
|
||||
|
||||
// Learning-based decision for medium risk
|
||||
if (smartRecommendation.learningBased && smartRecommendation.confidence > 0.6) {
|
||||
return {
|
||||
action: smartRecommendation.suggestedAction,
|
||||
reasoning: `AI Learning: ${smartRecommendation.reasoning}`,
|
||||
confidence: smartRecommendation.confidence,
|
||||
urgency: 'MEDIUM',
|
||||
learningEnhanced: true
|
||||
};
|
||||
}
|
||||
|
||||
// Default medium risk response
|
||||
return {
|
||||
action: 'ENHANCED_MONITORING',
|
||||
reasoning: 'Increased monitoring frequency. Preparing contingency plans.',
|
||||
confidence: 0.6,
|
||||
urgency: 'MEDIUM',
|
||||
parameters: {
|
||||
monitoringInterval: 30, // seconds
|
||||
alertThreshold: this.riskThreshold
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async handleSafePosition(monitor, smartRecommendation) {
|
||||
const { position } = monitor;
|
||||
|
||||
// Even in safe positions, check for optimization opportunities
|
||||
if (smartRecommendation.learningBased && smartRecommendation.confidence > 0.8) {
|
||||
if (smartRecommendation.suggestedAction === 'SCALE_POSITION') {
|
||||
return {
|
||||
action: 'SCALE_POSITION',
|
||||
reasoning: `AI Learning: ${smartRecommendation.reasoning}`,
|
||||
confidence: smartRecommendation.confidence,
|
||||
urgency: 'LOW',
|
||||
learningEnhanced: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
action: 'MONITOR',
|
||||
reasoning: 'Position is safe. Continuing standard monitoring.',
|
||||
confidence: 0.8,
|
||||
urgency: 'LOW'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Record decision for learning purposes
|
||||
*/
|
||||
async recordDecisionForLearning(monitor, decision, smartRecommendation) {
|
||||
try {
|
||||
const { position, stopLossProximity } = monitor;
|
||||
const distance = parseFloat(stopLossProximity.distancePercent);
|
||||
|
||||
const decisionData = {
|
||||
tradeId: position.id || `position_${Date.now()}`,
|
||||
symbol: position.symbol,
|
||||
decision: decision.action,
|
||||
distanceFromSL: distance,
|
||||
reasoning: decision.reasoning,
|
||||
currentPrice: position.entryPrice,
|
||||
confidenceScore: decision.confidence,
|
||||
expectedOutcome: this.predictOutcome(decision.action, distance),
|
||||
marketConditions: await this.getCurrentMarketConditions(position.symbol),
|
||||
learningRecommendation: smartRecommendation
|
||||
};
|
||||
|
||||
const decisionId = await this.learner.recordDecision(decisionData);
|
||||
|
||||
// Store decision for outcome tracking
|
||||
this.pendingDecisions.set(decisionId, {
|
||||
...decisionData,
|
||||
timestamp: new Date(),
|
||||
monitor: monitor
|
||||
});
|
||||
|
||||
await this.log(`📝 Recorded decision ${decisionId} for learning: ${decision.action}`);
|
||||
|
||||
return decisionId;
|
||||
} catch (error) {
|
||||
await this.log(`❌ Error recording decision for learning: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assess outcomes of previous decisions
|
||||
*/
|
||||
async assessDecisionOutcomes() {
|
||||
try {
|
||||
for (const [decisionId, decisionData] of this.pendingDecisions.entries()) {
|
||||
const timeSinceDecision = Date.now() - decisionData.timestamp.getTime();
|
||||
|
||||
// Assess after sufficient time has passed (5 minutes minimum)
|
||||
if (timeSinceDecision > 5 * 60 * 1000) {
|
||||
const outcome = await this.determineDecisionOutcome(decisionData);
|
||||
|
||||
if (outcome) {
|
||||
await this.learner.assessDecisionOutcome({
|
||||
decisionId,
|
||||
actualOutcome: outcome.result,
|
||||
timeToOutcome: Math.floor(timeSinceDecision / 60000), // minutes
|
||||
pnlImpact: outcome.pnlImpact,
|
||||
additionalContext: outcome.context
|
||||
});
|
||||
|
||||
// Remove from pending decisions
|
||||
this.pendingDecisions.delete(decisionId);
|
||||
await this.log(`✅ Assessed outcome for decision ${decisionId}: ${outcome.result}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
await this.log(`❌ Error assessing decision outcomes: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async determineDecisionOutcome(decisionData) {
|
||||
try {
|
||||
// Get current position status
|
||||
const currentStatus = await this.getCurrentPositionStatus(decisionData.symbol);
|
||||
|
||||
if (!currentStatus) {
|
||||
return {
|
||||
result: 'POSITION_CLOSED',
|
||||
pnlImpact: 0,
|
||||
context: { reason: 'Position no longer exists' }
|
||||
};
|
||||
}
|
||||
|
||||
// Compare current situation with when decision was made
|
||||
const originalDistance = decisionData.distanceFromSL;
|
||||
const currentDistance = currentStatus.distanceFromSL;
|
||||
const pnlChange = currentStatus.unrealizedPnl - (decisionData.monitor.position?.unrealizedPnl || 0);
|
||||
|
||||
// Determine if decision was beneficial
|
||||
if (decisionData.decision === 'EMERGENCY_EXIT' && currentDistance < 0.5) {
|
||||
return {
|
||||
result: 'AVOIDED_MAJOR_LOSS',
|
||||
pnlImpact: Math.abs(pnlChange), // Positive impact
|
||||
context: { originalDistance, currentDistance }
|
||||
};
|
||||
}
|
||||
|
||||
if (decisionData.decision === 'TIGHTEN_STOP_LOSS' && pnlChange > 0) {
|
||||
return {
|
||||
result: 'IMPROVED_PROFIT',
|
||||
pnlImpact: pnlChange,
|
||||
context: { originalDistance, currentDistance }
|
||||
};
|
||||
}
|
||||
|
||||
if (decisionData.decision === 'HOLD' && currentDistance > originalDistance) {
|
||||
return {
|
||||
result: 'CORRECT_HOLD',
|
||||
pnlImpact: pnlChange,
|
||||
context: { distanceImproved: currentDistance - originalDistance }
|
||||
};
|
||||
}
|
||||
|
||||
// Default assessment
|
||||
return {
|
||||
result: pnlChange >= 0 ? 'NEUTRAL_POSITIVE' : 'NEUTRAL_NEGATIVE',
|
||||
pnlImpact: pnlChange,
|
||||
context: { originalDistance, currentDistance }
|
||||
};
|
||||
} catch (error) {
|
||||
await this.log(`❌ Error determining decision outcome: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentPositionStatus(symbol) {
|
||||
try {
|
||||
const { stdout } = await execAsync('curl -s http://localhost:9001/api/automation/position-monitor');
|
||||
const data = JSON.parse(stdout);
|
||||
|
||||
if (data.success && data.monitor?.hasPosition) {
|
||||
return {
|
||||
distanceFromSL: parseFloat(data.monitor.stopLossProximity?.distancePercent || 0),
|
||||
unrealizedPnl: data.monitor.position?.unrealizedPnl || 0
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async updateThresholdsFromLearning() {
|
||||
try {
|
||||
// Get learned optimal thresholds
|
||||
const patterns = await this.learner.analyzeDecisionPatterns();
|
||||
|
||||
if (patterns?.distanceOptimization) {
|
||||
const optimization = patterns.distanceOptimization;
|
||||
|
||||
if (optimization.emergencyRange?.optimalThreshold) {
|
||||
this.emergencyThreshold = optimization.emergencyRange.optimalThreshold;
|
||||
}
|
||||
if (optimization.highRiskRange?.optimalThreshold) {
|
||||
this.riskThreshold = optimization.highRiskRange.optimalThreshold;
|
||||
}
|
||||
if (optimization.mediumRiskRange?.optimalThreshold) {
|
||||
this.mediumRiskThreshold = optimization.mediumRiskRange.optimalThreshold;
|
||||
}
|
||||
|
||||
await this.log(`🔄 Updated thresholds from learning: Emergency=${this.emergencyThreshold.toFixed(2)}%, Risk=${this.riskThreshold.toFixed(2)}%, Medium=${this.mediumRiskThreshold.toFixed(2)}%`);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.log(`❌ Error updating thresholds from learning: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
predictOutcome(action, distance) {
|
||||
// Predict what we expect to happen based on the action
|
||||
const predictions = {
|
||||
'EMERGENCY_EXIT': 'AVOID_MAJOR_LOSS',
|
||||
'PARTIAL_EXIT': 'REDUCE_RISK',
|
||||
'TIGHTEN_STOP_LOSS': 'BETTER_RISK_REWARD',
|
||||
'SCALE_POSITION': 'INCREASED_PROFIT',
|
||||
'HOLD': 'MAINTAIN_POSITION',
|
||||
'ENHANCED_MONITORING': 'EARLY_WARNING'
|
||||
};
|
||||
|
||||
return predictions[action] || 'UNKNOWN_OUTCOME';
|
||||
}
|
||||
|
||||
async analyzeMarketConditions(symbol) {
|
||||
// Enhanced market analysis for better decision making
|
||||
try {
|
||||
const { stdout } = await execAsync('curl -s http://localhost:9001/api/automation/position-monitor');
|
||||
const data = JSON.parse(stdout);
|
||||
|
||||
if (data.success && data.monitor?.position) {
|
||||
const pnl = data.monitor.position.unrealizedPnl;
|
||||
const trend = pnl > 0 ? 'BULLISH' : pnl < -1 ? 'BEARISH' : 'SIDEWAYS';
|
||||
|
||||
return {
|
||||
trend,
|
||||
strength: Math.abs(pnl),
|
||||
timeOfDay: new Date().getHours(),
|
||||
volatility: Math.random() * 0.1 // Mock volatility
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
// Fallback analysis
|
||||
}
|
||||
|
||||
return {
|
||||
trend: 'UNKNOWN',
|
||||
strength: 0,
|
||||
timeOfDay: new Date().getHours(),
|
||||
volatility: 0.05
|
||||
};
|
||||
}
|
||||
|
||||
async getCurrentMarketConditions(symbol) {
|
||||
const conditions = await this.analyzeMarketConditions(symbol);
|
||||
return {
|
||||
...conditions,
|
||||
dayOfWeek: new Date().getDay(),
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced Beach Mode with learning integration
|
||||
*/
|
||||
async beachMode() {
|
||||
await this.log('🏖️ ENHANCED BEACH MODE: Autonomous operation with AI learning');
|
||||
this.isActive = true;
|
||||
|
||||
// Main monitoring loop
|
||||
const monitoringLoop = async () => {
|
||||
if (!this.isActive) return;
|
||||
|
||||
try {
|
||||
// Check current positions
|
||||
const { stdout } = await execAsync('curl -s http://localhost:9001/api/automation/position-monitor');
|
||||
const data = JSON.parse(stdout);
|
||||
|
||||
if (data.success) {
|
||||
const decision = await this.analyzePosition(data.monitor);
|
||||
await this.executeDecision(decision);
|
||||
}
|
||||
|
||||
// Assess outcomes of previous decisions
|
||||
await this.assessDecisionOutcomes();
|
||||
|
||||
} catch (error) {
|
||||
await this.log(`Error in beach mode cycle: ${error.message}`);
|
||||
}
|
||||
|
||||
// Schedule next check
|
||||
if (this.isActive) {
|
||||
setTimeout(monitoringLoop, 60000); // Check every minute
|
||||
}
|
||||
};
|
||||
|
||||
// Start monitoring
|
||||
monitoringLoop();
|
||||
|
||||
// Generate learning reports periodically
|
||||
setInterval(async () => {
|
||||
if (this.isActive) {
|
||||
const report = await this.learner.generateLearningReport();
|
||||
if (report) {
|
||||
await this.log(`📊 Learning Update: ${report.summary.totalDecisions} decisions, ${(report.summary.systemConfidence * 100).toFixed(1)}% confidence`);
|
||||
}
|
||||
}
|
||||
}, 15 * 60 * 1000); // Every 15 minutes
|
||||
}
|
||||
|
||||
async executeDecision(decision) {
|
||||
await this.log(`🎯 Executing decision: ${decision.action} - ${decision.reasoning} (Confidence: ${(decision.confidence * 100).toFixed(1)}%)`);
|
||||
|
||||
// Add learning enhancement indicators
|
||||
if (decision.learningEnhanced) {
|
||||
await this.log(`🧠 Decision enhanced by AI learning system`);
|
||||
}
|
||||
|
||||
// Implementation would depend on your trading API
|
||||
switch (decision.action) {
|
||||
case 'EMERGENCY_EXIT':
|
||||
await this.log('🚨 Implementing emergency exit protocol');
|
||||
break;
|
||||
case 'PARTIAL_EXIT':
|
||||
await this.log('📉 Executing partial position closure');
|
||||
break;
|
||||
case 'TIGHTEN_STOP_LOSS':
|
||||
await this.log('🎯 Adjusting stop loss parameters');
|
||||
break;
|
||||
case 'SCALE_POSITION':
|
||||
await this.log('📈 Scaling position size');
|
||||
break;
|
||||
case 'ENHANCED_MONITORING':
|
||||
await this.log('👁️ Activating enhanced monitoring');
|
||||
break;
|
||||
default:
|
||||
await this.log(`ℹ️ Monitoring: ${decision.reasoning}`);
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.isActive = false;
|
||||
this.log('🛑 Enhanced autonomous risk management stopped');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get learning system status and insights
|
||||
*/
|
||||
async getLearningStatus() {
|
||||
try {
|
||||
const report = await this.learner.generateLearningReport();
|
||||
return {
|
||||
isLearning: true,
|
||||
totalDecisions: this.pendingDecisions.size + (report?.summary?.totalDecisions || 0),
|
||||
systemConfidence: report?.summary?.systemConfidence || 0.3,
|
||||
currentThresholds: {
|
||||
emergency: this.emergencyThreshold,
|
||||
risk: this.riskThreshold,
|
||||
mediumRisk: this.mediumRiskThreshold
|
||||
},
|
||||
pendingAssessments: this.pendingDecisions.size,
|
||||
lastAnalysis: this.lastAnalysis,
|
||||
insights: report?.insights
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
isLearning: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export for use in other modules
|
||||
module.exports = EnhancedAutonomousRiskManager;
|
||||
|
||||
// Direct execution for testing
|
||||
if (require.main === module) {
|
||||
const riskManager = new EnhancedAutonomousRiskManager();
|
||||
|
||||
console.log('🤖 Enhanced Autonomous Risk Manager with AI Learning');
|
||||
console.log('🧠 Now learning from every decision to become smarter!');
|
||||
console.log('🏖️ Perfect for beach mode - gets better while you relax!');
|
||||
|
||||
riskManager.beachMode();
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
riskManager.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user