This commit is contained in:
薇薇安 2026-02-12 21:07:11 +08:00
parent 2c81d47b2b
commit 7550b707f4

View File

@ -230,16 +230,22 @@ class RiskManager:
async def calculate_dynamic_leverage(
self,
symbol: str,
entry_price: float,
*args,
symbol: Optional[str] = None,
entry_price: Optional[float] = None,
stop_loss_price: Optional[float] = None,
atr: Optional[float] = None,
side: Optional[str] = None,
signal_strength: Optional[int] = None
signal_strength: Optional[int] = None,
**kwargs
) -> int:
"""
计算动态杠杆 - 综合考虑信号强度和风险控制
兼容两种调用方式
1. 新版本calculate_dynamic_leverage(symbol=..., entry_price=..., stop_loss_price=..., ...)
2. 旧版本calculate_dynamic_leverage(signal_strength, symbol, atr=..., entry_price=...)
Args:
symbol: 交易对
entry_price: 入场价格
@ -251,6 +257,28 @@ class RiskManager:
Returns:
建议杠杆倍数
"""
# 兼容旧调用方式:第一个位置参数可能是 signal_strength
if args and len(args) > 0:
first_arg = args[0]
if isinstance(first_arg, int) and 0 <= first_arg <= 10:
signal_strength = first_arg
elif isinstance(first_arg, str):
symbol = first_arg
if len(args) > 1 and isinstance(args[1], str) and symbol is None:
symbol = args[1]
if len(args) > 2 and isinstance(args[2], (int, float)) and entry_price is None:
entry_price = args[2]
# 从 kwargs 中提取(兼容旧调用)
if 'signal_strength' in kwargs and signal_strength is None:
signal_strength = kwargs.get('signal_strength')
if 'symbol' in kwargs and symbol is None:
symbol = kwargs.get('symbol')
if 'entry_price' in kwargs and entry_price is None:
entry_price = kwargs.get('entry_price')
if 'atr' in kwargs and atr is None:
atr = kwargs.get('atr')
# 默认使用配置杠杆
default_leverage = config.TRADING_CONFIG.get('LEVERAGE', 10)
@ -273,7 +301,7 @@ class RiskManager:
signal_leverage = base_leverage + leverage_increase
signal_leverage = min(signal_leverage, max_leverage)
logger.info(f" 📊 信号强度杠杆 ({symbol}): 信号={signal_strength} -> {int(signal_leverage)}x")
logger.info(f" 📊 信号强度杠杆 ({symbol or 'N/A'}): 信号={signal_strength} -> {int(signal_leverage)}x")
# 2. 基于ATR波动率的限制 (小众币保护)
atr_limit_leverage = 100 # 初始设为很高
@ -311,7 +339,7 @@ class RiskManager:
theoretical_leverage = max_loss_pct / stop_loss_width
risk_safe_leverage = int(theoretical_leverage)
logger.info(f" 🛡️ 风险安全杠杆 ({symbol}):")
logger.info(f" 🛡️ 风险安全杠杆 ({symbol or 'N/A'}):")
logger.info(f" 止损宽度: {stop_loss_width*100:.2f}%")
logger.info(f" 最大单笔亏损限制: {max_loss_pct*100:.1f}%")
logger.info(f" -> 理论最大杠杆: {theoretical_leverage:.2f}x")
@ -1236,82 +1264,3 @@ class RiskManager:
+ f"止盈金额={take_profit_amount:.4f} USDT ({take_profit_percent*100:.1f}% of margin)"
)
return take_profit_price
async def calculate_dynamic_leverage(self, signal_strength: int, symbol: str = None, atr: Optional[float] = None, entry_price: Optional[float] = None) -> int:
"""
根据信号强度计算动态杠杆倍数
信号强度越高杠杆倍数越高以最大化收益
同时检查交易对支持的最大杠杆限制
Args:
signal_strength: 信号强度 (0-10)
symbol: 交易对符号可选用于检查交易对的最大杠杆限制
Returns:
杠杆倍数
"""
# 获取配置参数
use_dynamic_leverage = config.TRADING_CONFIG.get('USE_DYNAMIC_LEVERAGE', True)
base_leverage = config.TRADING_CONFIG.get('LEVERAGE', 10)
max_leverage = config.TRADING_CONFIG.get('MAX_LEVERAGE', 20)
min_signal_strength = config.TRADING_CONFIG.get('MIN_SIGNAL_STRENGTH', 7)
# ⚠️ 优化7阶梯杠杆 - 小众币限制最高杠杆
max_leverage_small_cap = config.TRADING_CONFIG.get('MAX_LEVERAGE_SMALL_CAP', 5)
atr_leverage_reduction_threshold = config.TRADING_CONFIG.get('ATR_LEVERAGE_REDUCTION_THRESHOLD', 0.05) # 5%
# 检查是否为小众币(高波动率)
is_small_cap = False
if atr and entry_price and entry_price > 0:
atr_percent = atr / entry_price
if atr_percent >= atr_leverage_reduction_threshold:
is_small_cap = True
logger.info(f" ⚠️ {symbol} ATR波动率 {atr_percent*100:.2f}% >= {atr_leverage_reduction_threshold*100:.0f}%,识别为小众币,限制最大杠杆为{max_leverage_small_cap}x")
max_leverage = min(max_leverage, max_leverage_small_cap)
# 如果未启用动态杠杆,返回基础杠杆
if not use_dynamic_leverage:
final_leverage = int(base_leverage)
else:
# 如果信号强度低于最小要求,使用基础杠杆
if signal_strength < min_signal_strength:
final_leverage = int(base_leverage)
else:
# 计算动态杠杆:信号强度越高,杠杆越高
# 公式:杠杆 = 基础杠杆 + (信号强度 - 最小信号强度) * (最大杠杆 - 基础杠杆) / (10 - 最小信号强度)
signal_range = 10 - min_signal_strength # 信号强度范围
leverage_range = max_leverage - base_leverage # 杠杆范围
if signal_range > 0:
# 计算信号强度超出最小值的比例
strength_above_min = signal_strength - min_signal_strength
leverage_increase = (strength_above_min / signal_range) * leverage_range
dynamic_leverage = base_leverage + leverage_increase
else:
dynamic_leverage = base_leverage
# 确保杠杆在合理范围内(不超过配置的最大杠杆)
final_leverage = max(int(base_leverage), min(int(dynamic_leverage), int(max_leverage)))
# 如果提供了交易对符号,检查交易对支持的最大杠杆限制
if symbol:
try:
symbol_info = await self.client.get_symbol_info(symbol)
if symbol_info and 'maxLeverage' in symbol_info:
symbol_max_leverage = symbol_info['maxLeverage']
if final_leverage > symbol_max_leverage:
logger.warning(
f"{symbol} 交易对最大杠杆限制为 {symbol_max_leverage}x, "
f"计算杠杆 {final_leverage}x 超过限制,调整为 {symbol_max_leverage}x"
)
final_leverage = symbol_max_leverage
except Exception as e:
logger.warning(f"获取 {symbol} 交易对杠杆限制失败: {e},使用计算值 {final_leverage}x")
logger.info(
f"动态杠杆计算: 信号强度={signal_strength}/10, "
f"基础杠杆={base_leverage}x, 计算杠杆={final_leverage}x"
+ (f", 交易对={symbol}" if symbol else "")
)
return final_leverage