/** * 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 = 6; // Maximum 6% risk per trade (slightly more realistic for leveraged trades) 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', 'LONG'].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 };