- 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! 🚀
570 lines
18 KiB
JavaScript
570 lines
18 KiB
JavaScript
/**
|
||
* 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);
|
||
});
|
||
}
|