diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index b347390..14fbe5e 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -289,75 +289,84 @@ class RiskManager: # 公式:仓位大小 = (总资金 * 每笔单子承受的风险%) / (入场价 - 止损价) use_fixed_risk = config.TRADING_CONFIG.get('USE_FIXED_RISK_SIZING', True) fixed_risk_percent = config.TRADING_CONFIG.get('FIXED_RISK_PERCENT', 0.02) # 默认2% - quantity = None + quantity = None # 初始化为None,确保变量存在 if use_fixed_risk and entry_price and side: - # 如果未提供止损价格,先估算 - if stop_loss_price is None: - # 尝试使用ATR估算止损距离 - if atr and atr > 0: - atr_multiplier = config.TRADING_CONFIG.get('ATR_STOP_LOSS_MULTIPLIER', 1.8) + try: + # 如果未提供止损价格,先估算 + if stop_loss_price is None: + # 尝试使用ATR估算止损距离 + if atr and atr > 0: + atr_multiplier = config.TRADING_CONFIG.get('ATR_STOP_LOSS_MULTIPLIER', 1.8) + if side == 'BUY': + estimated_stop_loss = entry_price - (atr * atr_multiplier) + else: # SELL + estimated_stop_loss = entry_price + (atr * atr_multiplier) + stop_loss_price = estimated_stop_loss + else: + # 使用固定百分比估算(基于保证金) + stop_loss_pct = config.TRADING_CONFIG.get('STOP_LOSS_PERCENT', 0.10) + # 先估算一个临时仓位来计算止损距离 + temp_margin = total_balance * 0.05 # 临时使用5%保证金 + temp_notional = temp_margin * actual_leverage + temp_quantity = temp_notional / entry_price if entry_price > 0 else 0 + if temp_quantity > 0: + stop_loss_amount = temp_margin * stop_loss_pct + if side == 'BUY': + estimated_stop_loss = entry_price - (stop_loss_amount / temp_quantity) + else: # SELL + estimated_stop_loss = entry_price + (stop_loss_amount / temp_quantity) + stop_loss_price = estimated_stop_loss + else: + stop_loss_price = None + + # 计算止损距离 + if stop_loss_price is not None and stop_loss_price > 0: if side == 'BUY': - estimated_stop_loss = entry_price - (atr * atr_multiplier) + stop_distance = entry_price - stop_loss_price else: # SELL - estimated_stop_loss = entry_price + (atr * atr_multiplier) - stop_loss_price = estimated_stop_loss + stop_distance = stop_loss_price - entry_price + + if stop_distance > 0: + # 固定风险金额 + risk_amount = total_balance * fixed_risk_percent + + # 根据止损距离反算仓位 + # 风险金额 = (入场价 - 止损价) × 数量 + # 所以:数量 = 风险金额 / (入场价 - 止损价) + quantity = risk_amount / stop_distance + + # 计算对应的保证金和名义价值 + notional_value = quantity * entry_price + margin_value = notional_value / actual_leverage + + logger.info(f" ⚠️ 使用固定风险百分比计算仓位:") + logger.info(f" 固定风险: {fixed_risk_percent*100:.2f}% = {risk_amount:.4f} USDT") + logger.info(f" 止损距离: {stop_distance:.4f} USDT ({stop_distance/entry_price*100:.2f}%)") + logger.info(f" 计算数量: {quantity:.4f}") + logger.info(f" 名义价值: {notional_value:.2f} USDT") + logger.info(f" 保证金: {margin_value:.4f} USDT ({margin_value/total_balance*100:.2f}%)") + + # 检查是否超过最大仓位限制 + max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] + max_margin_value = available_balance * max_position_percent + + if margin_value > max_margin_value: + # 如果超过最大仓位,使用最大仓位 + logger.warning(f" ⚠️ 固定风险计算的保证金 {margin_value:.4f} USDT > 最大限制 {max_margin_value:.2f} USDT") + logger.info(f" ✓ 调整为最大仓位限制: {max_margin_value:.2f} USDT") + margin_value = max_margin_value + notional_value = margin_value * actual_leverage + quantity = notional_value / entry_price if entry_price > 0 else None + else: + logger.warning(f" ⚠️ 止损距离无效 (stop_distance={stop_distance:.4f}),将使用传统方法计算仓位") else: - # 使用固定百分比估算(基于保证金) - stop_loss_pct = config.TRADING_CONFIG.get('STOP_LOSS_PERCENT', 0.10) - # 先估算一个临时仓位来计算止损距离 - temp_margin = total_balance * 0.05 # 临时使用5%保证金 - temp_notional = temp_margin * actual_leverage - temp_quantity = temp_notional / entry_price - stop_loss_amount = temp_margin * stop_loss_pct - if side == 'BUY': - estimated_stop_loss = entry_price - (stop_loss_amount / temp_quantity) - else: # SELL - estimated_stop_loss = entry_price + (stop_loss_amount / temp_quantity) - stop_loss_price = estimated_stop_loss - - # 计算止损距离 - if side == 'BUY': - stop_distance = entry_price - stop_loss_price - else: # SELL - stop_distance = stop_loss_price - entry_price - - if stop_distance > 0: - # 固定风险金额 - risk_amount = total_balance * fixed_risk_percent - - # 根据止损距离反算仓位 - # 风险金额 = (入场价 - 止损价) × 数量 - # 所以:数量 = 风险金额 / (入场价 - 止损价) - quantity = risk_amount / stop_distance - - # 计算对应的保证金和名义价值 - notional_value = quantity * entry_price - margin_value = notional_value / actual_leverage - - logger.info(f" ⚠️ 使用固定风险百分比计算仓位:") - logger.info(f" 固定风险: {fixed_risk_percent*100:.2f}% = {risk_amount:.4f} USDT") - logger.info(f" 止损距离: {stop_distance:.4f} USDT ({stop_distance/entry_price*100:.2f}%)") - logger.info(f" 计算数量: {quantity:.4f}") - logger.info(f" 名义价值: {notional_value:.2f} USDT") - logger.info(f" 保证金: {margin_value:.4f} USDT ({margin_value/total_balance*100:.2f}%)") - - # 检查是否超过最大仓位限制 - max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] - max_margin_value = available_balance * max_position_percent - - if margin_value > max_margin_value: - # 如果超过最大仓位,使用最大仓位 - logger.warning(f" ⚠️ 固定风险计算的保证金 {margin_value:.4f} USDT > 最大限制 {max_margin_value:.2f} USDT") - logger.info(f" ✓ 调整为最大仓位限制: {max_margin_value:.2f} USDT") - margin_value = max_margin_value - notional_value = margin_value * actual_leverage - quantity = notional_value / entry_price - else: - # 使用固定风险计算的仓位 - pass # quantity已经计算好了 + logger.warning(f" ⚠️ 无法估算止损价格,将使用传统方法计算仓位") + except Exception as e: + logger.warning(f" ⚠️ 固定风险百分比计算失败: {e},将使用传统方法计算仓位") + quantity = None # 确保quantity为None,使用传统方法 - # 如果未使用固定风险计算,使用原来的方法 + # 如果未使用固定风险计算或计算失败,使用原来的方法 if quantity is None: # ⚠️ 优化3:信号强度分级 - 9-10分高权重,8分轻仓 signal_multiplier = 1.0