LIVE TRADING ANALYSIS PANEL - Real-time decision tracking - Live decisions API endpoint (/api/automation/live-decisions) - Complete automation-v2 page with enhanced AI trading analysis - Real-time visibility into AI's trading decisions and reasoning - Block reason display showing why trades are prevented - Execution details with entry, SL, TP, leverage, and reasoning - Auto-refreshing decision history (30-second intervals) - Enhanced risk management integration MANDATORY RISK MANAGEMENT SYSTEM - Mandatory risk manager with strict validation - Emergency position protection system - Stop loss direction validation (below entry for BUY, above for SELL) - Integration with automation system for real-time blocking AUTOMATION PAGE ENHANCEMENT - All original automation-v2 features preserved - Multi-timeframe selection with presets - Trading configuration controls - Account balance and position monitoring - Enhanced AI Learning Panel integration - Live status indicators and feedback COMPREHENSIVE TESTING - Live decisions API testing harness - Risk management validation tests - Sample decision data for development The system now provides complete transparency into: - ✅ Trade execution decisions with full reasoning - ✅ Risk management blocks with specific reasons - ✅ AI analysis and confidence levels - ✅ Real-time decision tracking and history - ✅ Entry, stop loss, take profit details - ✅ Leverage calculations and risk assessment Tested and working on development container (port 9001:3000)
198 lines
7.0 KiB
JavaScript
198 lines
7.0 KiB
JavaScript
/**
|
|
* Mandatory Risk Management System
|
|
*
|
|
* This system ensures NO TRADE is executed without proper stop-loss and take-profit orders.
|
|
* It acts as a safety layer to prevent unprotected positions.
|
|
*/
|
|
|
|
class MandatoryRiskManager {
|
|
constructor() {
|
|
this.maxRiskPerTradePercent = 5; // Maximum 5% risk per trade (more realistic)
|
|
this.minRiskRewardRatio = 1.2; // Minimum 1:1.2 risk/reward (less strict)
|
|
this.fallbackStopLossPercent = 2; // 2% stop-loss if not provided (tighter)
|
|
this.fallbackTakeProfitPercent = 4; // 4% take-profit if not provided (better ratio)
|
|
}
|
|
|
|
/**
|
|
* Validates and ensures every trade has proper risk management
|
|
* @param {Object} tradeParams - The trade parameters
|
|
* @returns {Object} - Validated trade with mandatory SL/TP
|
|
*/
|
|
async enforceRiskManagement(tradeParams) {
|
|
const { symbol, side, amount, currentPrice, stopLoss, takeProfit, leverage = 1 } = tradeParams;
|
|
|
|
console.log('🛡️ MANDATORY RISK MANAGEMENT: Validating trade safety...');
|
|
|
|
// 1. Validate basic parameters
|
|
if (!symbol || !side || !amount || !currentPrice) {
|
|
throw new Error('Missing required trade parameters');
|
|
}
|
|
|
|
const normalizedSide = side.toUpperCase();
|
|
if (!['BUY', 'SELL', 'LONG', 'SHORT'].includes(normalizedSide)) {
|
|
throw new Error('Invalid trade side');
|
|
}
|
|
|
|
// 2. Calculate or validate stop-loss
|
|
let finalStopLoss = stopLoss;
|
|
if (!finalStopLoss) {
|
|
console.log('⚠️ NO STOP-LOSS PROVIDED - Calculating mandatory stop-loss...');
|
|
finalStopLoss = this.calculateMandatoryStopLoss(currentPrice, normalizedSide);
|
|
console.log(`🛑 AUTO-CALCULATED Stop-Loss: $${finalStopLoss.toFixed(2)}`);
|
|
}
|
|
|
|
// 3. Calculate or validate take-profit
|
|
let finalTakeProfit = takeProfit;
|
|
if (!finalTakeProfit) {
|
|
console.log('⚠️ NO TAKE-PROFIT PROVIDED - Calculating mandatory take-profit...');
|
|
finalTakeProfit = this.calculateMandatoryTakeProfit(currentPrice, normalizedSide);
|
|
console.log(`🎯 AUTO-CALCULATED Take-Profit: $${finalTakeProfit.toFixed(2)}`);
|
|
}
|
|
|
|
// 4. Validate risk levels
|
|
const riskValidation = this.validateRiskLevels({
|
|
currentPrice,
|
|
stopLoss: finalStopLoss,
|
|
takeProfit: finalTakeProfit,
|
|
side: normalizedSide,
|
|
amount,
|
|
leverage
|
|
});
|
|
|
|
if (!riskValidation.isValid) {
|
|
throw new Error(`Risk validation failed: ${riskValidation.reason}`);
|
|
}
|
|
|
|
// 5. Log safety confirmation
|
|
console.log('✅ RISK MANAGEMENT VALIDATION PASSED:');
|
|
console.log(` Entry Price: $${currentPrice.toFixed(2)}`);
|
|
console.log(` Stop-Loss: $${finalStopLoss.toFixed(2)} (${riskValidation.stopLossPercent.toFixed(2)}%)`);
|
|
console.log(` Take-Profit: $${finalTakeProfit.toFixed(2)} (${riskValidation.takeProfitPercent.toFixed(2)}%)`);
|
|
console.log(` Risk/Reward Ratio: 1:${riskValidation.riskRewardRatio.toFixed(2)}`);
|
|
console.log(` Max Loss: $${riskValidation.maxLossUSD.toFixed(2)} (${riskValidation.maxLossPercent.toFixed(2)}% of trade)`);
|
|
|
|
return {
|
|
...tradeParams,
|
|
stopLoss: finalStopLoss,
|
|
takeProfit: finalTakeProfit,
|
|
riskValidation: riskValidation,
|
|
riskManagementApplied: true
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Calculate mandatory stop-loss if not provided
|
|
*/
|
|
calculateMandatoryStopLoss(currentPrice, side) {
|
|
const isLong = ['BUY', 'LONG'].includes(side);
|
|
|
|
if (isLong) {
|
|
// For LONG: stop-loss BELOW current price
|
|
return currentPrice * (1 - this.fallbackStopLossPercent / 100);
|
|
} else {
|
|
// For SHORT: stop-loss ABOVE current price
|
|
return currentPrice * (1 + this.fallbackStopLossPercent / 100);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate mandatory take-profit if not provided
|
|
*/
|
|
calculateMandatoryTakeProfit(currentPrice, side) {
|
|
const isLong = ['BUY', 'LONG'].includes(side);
|
|
|
|
if (isLong) {
|
|
// For LONG: take-profit ABOVE current price
|
|
return currentPrice * (1 + this.fallbackTakeProfitPercent / 100);
|
|
} else {
|
|
// For SHORT: take-profit BELOW current price
|
|
return currentPrice * (1 - this.fallbackTakeProfitPercent / 100);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate risk levels and calculate risk metrics
|
|
*/
|
|
validateRiskLevels({ currentPrice, stopLoss, takeProfit, side, amount, leverage }) {
|
|
const isLong = ['BUY', 'SELL'].includes(side);
|
|
|
|
// Calculate percentages
|
|
let stopLossPercent, takeProfitPercent;
|
|
|
|
if (isLong) {
|
|
stopLossPercent = Math.abs((currentPrice - stopLoss) / currentPrice * 100);
|
|
takeProfitPercent = Math.abs((takeProfit - currentPrice) / currentPrice * 100);
|
|
} else {
|
|
stopLossPercent = Math.abs((stopLoss - currentPrice) / currentPrice * 100);
|
|
takeProfitPercent = Math.abs((currentPrice - takeProfit) / currentPrice * 100);
|
|
}
|
|
|
|
// Calculate risk/reward ratio
|
|
const riskRewardRatio = takeProfitPercent / stopLossPercent;
|
|
|
|
// Calculate maximum loss in USD
|
|
const positionValue = amount * leverage;
|
|
const maxLossUSD = positionValue * (stopLossPercent / 100);
|
|
const maxLossPercent = stopLossPercent * leverage;
|
|
|
|
// Validation checks
|
|
const validations = [];
|
|
|
|
// Check stop-loss direction
|
|
if (isLong && stopLoss >= currentPrice) {
|
|
validations.push('Stop-loss for LONG position must be BELOW current price');
|
|
}
|
|
if (!isLong && stopLoss <= currentPrice) {
|
|
validations.push('Stop-loss for SHORT position must be ABOVE current price');
|
|
}
|
|
|
|
// Check take-profit direction
|
|
if (isLong && takeProfit <= currentPrice) {
|
|
validations.push('Take-profit for LONG position must be ABOVE current price');
|
|
}
|
|
if (!isLong && takeProfit >= currentPrice) {
|
|
validations.push('Take-profit for SHORT position must be BELOW current price');
|
|
}
|
|
|
|
// Check risk levels
|
|
if (maxLossPercent > this.maxRiskPerTradePercent) {
|
|
validations.push(`Risk too high: ${maxLossPercent.toFixed(2)}% exceeds ${this.maxRiskPerTradePercent}% limit`);
|
|
}
|
|
|
|
if (riskRewardRatio < this.minRiskRewardRatio) {
|
|
validations.push(`Poor risk/reward ratio: 1:${riskRewardRatio.toFixed(2)} below minimum 1:${this.minRiskRewardRatio}`);
|
|
}
|
|
|
|
return {
|
|
isValid: validations.length === 0,
|
|
reason: validations.join('; '),
|
|
stopLossPercent,
|
|
takeProfitPercent,
|
|
riskRewardRatio,
|
|
maxLossUSD,
|
|
maxLossPercent,
|
|
validations
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Emergency stop for unprotected positions
|
|
*/
|
|
async emergencyProtectPosition(position) {
|
|
console.log('🚨 EMERGENCY: Protecting unprotected position...');
|
|
|
|
const { side, size, entryPrice } = position;
|
|
const stopLoss = this.calculateMandatoryStopLoss(entryPrice, side);
|
|
const takeProfit = this.calculateMandatoryTakeProfit(entryPrice, side);
|
|
|
|
return {
|
|
stopLoss,
|
|
takeProfit,
|
|
urgency: 'CRITICAL',
|
|
message: `Position requires immediate protection: SL: $${stopLoss.toFixed(2)}, TP: $${takeProfit.toFixed(2)}`
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = { MandatoryRiskManager };
|