diff --git a/OPTIMIZATION_IMPLEMENTATION_SUMMARY.md b/OPTIMIZATION_IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..bf7cdae --- /dev/null +++ b/OPTIMIZATION_IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,234 @@ +# 交易策略优化实施总结 + +## ✅ 已完成的优化(高优先级) + +### 实施总结 + +已完成5项高优先级优化,显著提升系统风险控制和信号质量: + +1. ✅ **大盘共振(Beta Filter)** - 减少大盘暴跌时的多单损失 +2. ✅ **成交量验证** - 避免流动性差的币种,减少滑点损失 +3. ✅ **固定风险百分比仓位计算** - 每笔单子风险恒定(2%),避免30%大额亏损 +4. ✅ **信号强度分级** - 高质量信号(9-10分)获得更大收益,低质量信号(8分)降低风险 +5. ✅ **阶梯杠杆** - 小众币风险降低(最大杠杆5倍) + +--- + +### 1. ✅ 动态过滤:大盘共振(Beta Filter) + +**实现位置**: +- `trading_system/strategy.py` - `_check_beta_filter()`, `_get_symbol_change_period()` +- `trading_system/strategy.py` - `_analyze_trade_signal()` 中调用 + +**功能**: +- 检查BTC和ETH在15min/1h周期的涨跌幅 +- 如果BTC或ETH下跌超过-3%(可配置),自动屏蔽所有多单信号 +- 做空信号不受影响 + +**配置项**: +- `BETA_FILTER_ENABLED`: True(默认启用) +- `BETA_FILTER_THRESHOLD`: -0.03(-3%) + +### 2. ✅ 成交量验证(严格过滤) + +**实现位置**: +- `trading_system/market_scanner.py` - `scan_market()` + +**功能**: +- 24H Volume低于1000万美金(可配置)的交易对直接剔除 +- 使用更严格的成交量要求,避免流动性差的币种 + +**配置项**: +- `MIN_VOLUME_24H_STRICT`: 10000000(1000万美金) + +### 3. ✅ 固定风险百分比仓位计算(凯利公式) + +**实现位置**: +- `trading_system/risk_manager.py` - `calculate_position_size()` +- `trading_system/position_manager.py` - `open_position()` 中调用 + +**功能**: +- 根据止损距离反算仓位,确保每笔单子赔掉的钱占总资金的比例恒定(默认2%) +- 公式:`仓位大小 = (总资金 * 每笔单子承受的风险%) / (入场价 - 止损价)` +- 如果固定风险计算的仓位超过最大仓位限制,自动调整为最大仓位 + +**配置项**: +- `USE_FIXED_RISK_SIZING`: True(默认启用) +- `FIXED_RISK_PERCENT`: 0.02(2%) + +### 4. ✅ 信号强度分级 + +**实现位置**: +- `trading_system/risk_manager.py` - `calculate_position_size()` +- `trading_system/position_manager.py` - `open_position()` 中传递信号强度 + +**功能**: +- 9-10分信号:使用100%仓位(MAX_POSITION_PERCENT) +- 8分信号:使用50%仓位(MAX_POSITION_PERCENT * 0.5) +- 提高高质量信号的收益,降低低质量信号的风险 + +**配置项**: +- `SIGNAL_STRENGTH_POSITION_MULTIPLIER`: {8: 0.5, 9: 1.0, 10: 1.0} + +### 5. ✅ 阶梯杠杆(小众币限制) + +**实现位置**: +- `trading_system/risk_manager.py` - `calculate_dynamic_leverage()` +- `trading_system/strategy.py` - 调用时传递ATR和入场价格 + +**功能**: +- 如果ATR波动率 >= 5%(可配置),识别为小众币 +- 小众币最大杠杆限制为5倍(可配置) +- 降低高波动币种的风险 + +**配置项**: +- `MAX_LEVERAGE_SMALL_CAP`: 5 +- `ATR_LEVERAGE_REDUCTION_THRESHOLD`: 0.05(5%) + +--- + +## ⏳ 待实现的优化(中低优先级) + +### 6. ⏳ 波动率阈值 + +**目标**:避开ATR异常激增的时刻 + +**实现方案**: +- 在 `market_scanner.py` 中计算平均ATR +- 如果当前ATR / 平均ATR > 2.0,过滤掉该交易对 + +**配置项**: +- `ATR_SPIKE_THRESHOLD`: 2.0 + +### 7. ⏳ 追踪止损(Trailing Stop) + +**目标**:当价格达到1:1目标后,利用币安Trailing Stop Order或代码层面实现 + +**实现方案**: +- 检查币安是否支持 `TRAILING_STOP_MARKET` 订单类型 +- 在分步止盈后,挂币安Trailing Stop Order或代码层面实现 + +**配置项**: +- `USE_TRAILING_STOP_AFTER_PARTIAL_PROFIT`: True +- `TRAILING_STOP_ATR_MULTIPLIER`: 1.5 + +### 8. ⏳ ADX趋势强度判断 + +**目标**:如果ADX > 25且处于上升趋势,延迟第一止盈位触发或取消50%减仓 + +**实现方案**: +- 在 `indicators.py` 中计算ADX +- 在 `position_manager.py` 的止盈检查中,如果ADX > 25且趋势向上,跳过第一止盈 + +**配置项**: +- `ADX_STRONG_TREND_THRESHOLD`: 25 +- `ADX_SKIP_PARTIAL_PROFIT`: True + +### 9. ⏳ 心跳检测与兜底巡检 + +**目标**:WebSocket断线重连机制 + 每1-2分钟兜底巡检 + +**实现方案**: +- 在 `position_manager.py` 的WebSocket监控中增加心跳检测 +- 增加独立的定时巡检任务(每1-2分钟),作为兜底 + +**配置项**: +- `WEBSOCKET_HEARTBEAT_INTERVAL`: 30(30秒) +- `FALLBACK_CHECK_INTERVAL`: 120(2分钟) + +### 10. ⏳ 滑点保护 + +**目标**:使用MARK_PRICE触发,但执行时使用LIMIT单或带保护的MARKET单 + +**实现方案**: +- 在 `position_manager.py` 的平仓逻辑中 +- 使用MARK_PRICE判断是否触发止损/止盈 +- 执行时使用LIMIT单(当前价±滑点容差) + +**配置项**: +- `SLIPPAGE_TOLERANCE_PCT`: 0.002(0.2%) +- `USE_LIMIT_ON_CLOSE`: True + +### 11. ⏳ 资金费率避险 + +**目标**:在费率结算前(8:00, 16:00, 24:00),如果费率过高(>0.1%),提前止盈或暂缓入场 + +**实现方案**: +- 在 `binance_client.py` 中获取资金费率 +- 在 `strategy.py` 中检查是否接近结算时间 +- 如果费率 > 0.1%,提前止盈或暂缓入场 + +**配置项**: +- `FUNDING_RATE_THRESHOLD`: 0.001(0.1%) +- `FUNDING_RATE_EARLY_EXIT_HOURS`: 1(结算前1小时) + +--- + +## 📊 配置项汇总 + +所有新增配置项已添加到 `trading_system/config.py` 的 `_get_trading_config()` 函数中: + +```python +# 动态过滤 +'BETA_FILTER_ENABLED': True, +'BETA_FILTER_THRESHOLD': -0.03, # -3% +'MIN_VOLUME_24H_STRICT': 10000000, # 1000万美金 +'SIGNAL_STRENGTH_POSITION_MULTIPLIER': {8: 0.5, 9: 1.0, 10: 1.0}, + +# 仓位管理 +'USE_FIXED_RISK_SIZING': True, +'FIXED_RISK_PERCENT': 0.02, # 2% +'MAX_LEVERAGE_SMALL_CAP': 5, +'ATR_LEVERAGE_REDUCTION_THRESHOLD': 0.05, # 5% +``` + +--- + +## 🎯 预期效果 + +### 已实现优化的预期效果: + +1. **大盘共振过滤**: + - ✅ 减少在大盘暴跌时的多单损失 + - ✅ 提高整体胜率 + +2. **成交量验证**: + - ✅ 避免流动性差的币种 + - ✅ 减少滑点损失(2-3%) + +3. **固定风险百分比**: + - ✅ 每笔单子风险恒定(2%),避免30%的大额亏损 + - ✅ 根据止损距离自动调整仓位,更科学 + +4. **信号强度分级**: + - ✅ 高质量信号(9-10分)获得更大收益 + - ✅ 低质量信号(8分)降低风险 + +5. **阶梯杠杆**: + - ✅ 小众币风险降低(最大杠杆5倍) + - ✅ 减少因高杠杆导致的强平风险 + +--- + +## 📝 使用说明 + +### 管理员配置 + +所有优化配置项都可以在 `GlobalConfig` 页面中配置: +- 大盘共振过滤:`BETA_FILTER_ENABLED`, `BETA_FILTER_THRESHOLD` +- 成交量验证:`MIN_VOLUME_24H_STRICT` +- 固定风险百分比:`USE_FIXED_RISK_SIZING`, `FIXED_RISK_PERCENT` +- 信号强度分级:`SIGNAL_STRENGTH_POSITION_MULTIPLIER` +- 阶梯杠杆:`MAX_LEVERAGE_SMALL_CAP`, `ATR_LEVERAGE_REDUCTION_THRESHOLD` + +### 默认值 + +所有优化默认启用,使用推荐的参数值。管理员可以根据实际情况调整。 + +--- + +## 🔄 后续优化建议 + +1. **监控效果**:观察优化后的实际效果,根据数据调整参数 +2. **逐步实现**:剩余优化可以根据实际需求逐步实现 +3. **测试验证**:建议在测试环境或小资金账户先测试 diff --git a/STRATEGY_OPTIMIZATION_PLAN.md b/STRATEGY_OPTIMIZATION_PLAN.md new file mode 100644 index 0000000..cbd036e --- /dev/null +++ b/STRATEGY_OPTIMIZATION_PLAN.md @@ -0,0 +1,247 @@ +# 交易策略优化计划 + +## 📋 优化目标 + +根据专业建议,系统化提升: +1. **入场信号质量** (Win Rate Up) +2. **利润捕获能力** (Profit Up) +3. **风险控制** (Survival First) +4. **系统可靠性** (Reliability Up) +5. **小众币专项优化** + +--- + +## 1. 动态过滤:提升入场信号质量 (Win Rate Up) + +### 1.1 大盘共振(Beta Filter)✅ 优先实现 + +**目标**:当BTC或ETH在15min/1h周期剧烈下跌时,自动屏蔽所有多单信号 + +**实现方案**: +- 在 `strategy.py` 的 `_analyze_trade_signal` 中增加大盘检查 +- 获取BTCUSDT和ETHUSDT的15min和1h K线 +- 计算最近N根K线的涨跌幅 +- 如果BTC或ETH在15min/1h周期下跌超过阈值(如-3%),屏蔽所有多单 +- 配置项:`BETA_FILTER_ENABLED`, `BETA_FILTER_THRESHOLD` + +**代码位置**: +- `trading_system/strategy.py` - `_analyze_trade_signal()` +- `trading_system/market_scanner.py` - 增加大盘数据获取 + +### 1.2 波动率阈值 + +**目标**:避开成交量极低或ATR异常激增的时刻 + +**实现方案**: +- 在 `market_scanner.py` 中增加波动率检查 +- ATR异常激增:当前ATR / 平均ATR > 阈值(如2.0) +- 成交量极低:24H Volume < 配置阈值(如1000万美金) +- 配置项:`ATR_SPIKE_THRESHOLD`, `MIN_VOLUME_24H_STRICT` + +**代码位置**: +- `trading_system/market_scanner.py` - `_get_symbol_change()` +- `trading_system/indicators.py` - ATR计算 + +### 1.3 信号强度分级 + +**目标**:9-10分信号分配更高权重,8分信号仅作为轻仓试探 + +**实现方案**: +- 在 `risk_manager.py` 的 `calculate_position_size` 中根据信号强度调整仓位 +- 9-10分:使用100%仓位(MAX_POSITION_PERCENT) +- 8分:使用50%仓位(MAX_POSITION_PERCENT * 0.5) +- 配置项:`SIGNAL_STRENGTH_POSITION_MULTIPLIER` + +**代码位置**: +- `trading_system/risk_manager.py` - `calculate_position_size()` +- `trading_system/strategy.py` - 传递信号强度 + +--- + +## 2. 策略优化:从"固定止盈"到"动态追踪" (Profit Up) + +### 2.1 追踪止损(Trailing Stop) + +**目标**:当价格达到1:1目标后,利用币安Trailing Stop Order或代码层面根据ATR向上移动止损线 + +**实现方案**: +- 检查币安是否支持 `TRAILING_STOP_MARKET` 订单类型 +- 如果支持:在分步止盈后,挂币安Trailing Stop Order +- 如果不支持:代码层面实现,根据ATR动态调整止损价 +- 配置项:`USE_TRAILING_STOP_AFTER_PARTIAL_PROFIT`, `TRAILING_STOP_ATR_MULTIPLIER` + +**代码位置**: +- `trading_system/position_manager.py` - 分步止盈后逻辑 +- `trading_system/binance_client.py` - Trailing Stop Order支持 + +### 2.2 ADX趋势强度判断 + +**目标**:如果ADX > 25且处于上升趋势,延迟第一止盈位触发或取消50%减仓 + +**实现方案**: +- 在 `indicators.py` 中计算ADX +- 在 `position_manager.py` 的止盈检查中,如果ADX > 25且趋势向上,跳过第一止盈(50%减仓) +- 配置项:`ADX_STRONG_TREND_THRESHOLD`, `ADX_SKIP_PARTIAL_PROFIT` + +**代码位置**: +- `trading_system/indicators.py` - ADX计算 +- `trading_system/position_manager.py` - 止盈逻辑 + +--- + +## 3. 仓位管理:基于风险的头寸缩放 (Survival First) + +### 3.1 凯利公式/固定风险百分比 + +**目标**:根据止损距离反算仓位,确保每笔单子赔掉的钱占总资金的比例恒定(如2%) + +**实现方案**: +- 在 `risk_manager.py` 的 `calculate_position_size` 中实现 +- 公式:`仓位大小 = (总资金 * 每笔单子承受的风险%) / (入场价 - 止损价)` +- 配置项:`FIXED_RISK_PERCENT`, `USE_FIXED_RISK_SIZING` + +**代码位置**: +- `trading_system/risk_manager.py` - `calculate_position_size()` + +### 3.2 阶梯杠杆 + +**目标**:针对小众币,强制限制最高杠杆(如3-5倍) + +**实现方案**: +- 在 `risk_manager.py` 的 `calculate_dynamic_leverage` 中增加波动率检查 +- 如果ATR过高或成交量过低,限制最高杠杆 +- 配置项:`MAX_LEVERAGE_SMALL_CAP`, `ATR_LEVERAGE_REDUCTION_THRESHOLD` + +**代码位置**: +- `trading_system/risk_manager.py` - `calculate_dynamic_leverage()` + +--- + +## 4. 基础设施与风控 (Reliability Up) + +### 4.1 心跳检测与延迟监控 + +**目标**:WebSocket断线重连机制 + 每1-2分钟兜底巡检 + +**实现方案**: +- 在 `position_manager.py` 的WebSocket监控中增加心跳检测 +- 如果WebSocket断线,自动重连 +- 增加独立的定时巡检任务(每1-2分钟),作为兜底 +- 配置项:`WEBSOCKET_HEARTBEAT_INTERVAL`, `FALLBACK_CHECK_INTERVAL` + +**代码位置**: +- `trading_system/position_manager.py` - WebSocket监控逻辑 + +### 4.2 滑点保护 + +**目标**:使用MARK_PRICE触发,但执行时使用LIMIT单或带保护的MARKET单 + +**实现方案**: +- 在 `position_manager.py` 的平仓逻辑中 +- 使用MARK_PRICE判断是否触发止损/止盈 +- 执行时使用LIMIT单(当前价±滑点容差)或带保护的MARKET单 +- 配置项:`SLIPPAGE_TOLERANCE_PCT`, `USE_LIMIT_ON_CLOSE` + +**代码位置**: +- `trading_system/position_manager.py` - `close_position()` + +--- + +## 5. 针对小众币的专项优化 + +### 5.1 资金费率避险 + +**目标**:在费率结算前(8:00, 16:00, 24:00),如果费率过高(>0.1%),提前止盈或暂缓入场 + +**实现方案**: +- 在 `binance_client.py` 中获取资金费率 +- 在 `strategy.py` 中检查是否接近结算时间(8:00, 16:00, 24:00) +- 如果费率 > 0.1%,提前止盈或暂缓入场 +- 配置项:`FUNDING_RATE_THRESHOLD`, `FUNDING_RATE_EARLY_EXIT_HOURS` + +**代码位置**: +- `trading_system/binance_client.py` - 资金费率获取 +- `trading_system/strategy.py` - 入场检查 +- `trading_system/position_manager.py` - 止盈检查 + +### 5.2 成交量验证 + +**目标**:24H Volume低于1000万美金,直接剔除 + +**实现方案**: +- 在 `market_scanner.py` 中增加严格成交量过滤 +- 配置项:`MIN_VOLUME_24H_STRICT` (10000000) + +**代码位置**: +- `trading_system/market_scanner.py` - 扫描过滤 + +--- + +## 📊 实施优先级 + +### ✅ 高优先级(已完成) + +1. ✅ **大盘共振(Beta Filter)** - 当BTC/ETH下跌超过-3%时,屏蔽所有多单 +2. ✅ **成交量验证(1000万美金)** - 24H Volume低于1000万美金直接剔除 +3. ✅ **固定风险百分比仓位计算** - 根据止损距离反算仓位,每笔风险恒定2% +4. ✅ **信号强度分级** - 8分50%仓位,9-10分100%仓位 +5. ✅ **阶梯杠杆** - 小众币(ATR>=5%)限制最高杠杆5倍 + +**预期效果**: +- ✅ 减少大盘暴跌时的损失 +- ✅ 避免流动性差的币种,减少滑点损失(2-3%) +- ✅ 每笔单子风险恒定(2%),避免30%的大额亏损 +- ✅ 高质量信号获得更大收益,低质量信号降低风险 +- ✅ 小众币风险降低,减少强平风险 + +### ⏳ 中优先级(待实施) + +6. ⏳ 波动率阈值 - 避开ATR异常激增的时刻 +7. ⏳ 心跳检测与兜底巡检 - WebSocket断线重连和兜底巡检 +8. ⏳ 滑点保护 - 使用MARK_PRICE触发,LIMIT单执行 + +### 中优先级(本周实施) +5. 波动率阈值 +6. 信号强度分级 +7. 阶梯杠杆(小众币) +8. 滑点保护 + +### 低优先级(后续优化) +9. 追踪止损(Trailing Stop) +10. ADX趋势强度判断 +11. 资金费率避险 + +--- + +## 🔧 配置项汇总 + +```python +# 动态过滤 +'BETA_FILTER_ENABLED': True, +'BETA_FILTER_THRESHOLD': -0.03, # -3% +'ATR_SPIKE_THRESHOLD': 2.0, +'MIN_VOLUME_24H_STRICT': 10000000, # 1000万美金 +'SIGNAL_STRENGTH_POSITION_MULTIPLIER': {8: 0.5, 9: 1.0, 10: 1.0}, + +# 策略优化 +'USE_TRAILING_STOP_AFTER_PARTIAL_PROFIT': True, +'TRAILING_STOP_ATR_MULTIPLIER': 1.5, +'ADX_STRONG_TREND_THRESHOLD': 25, +'ADX_SKIP_PARTIAL_PROFIT': True, + +# 仓位管理 +'USE_FIXED_RISK_SIZING': True, +'FIXED_RISK_PERCENT': 0.02, # 2% +'MAX_LEVERAGE_SMALL_CAP': 5, +'ATR_LEVERAGE_REDUCTION_THRESHOLD': 0.05, # 5% + +# 基础设施 +'WEBSOCKET_HEARTBEAT_INTERVAL': 30, # 30秒 +'FALLBACK_CHECK_INTERVAL': 120, # 2分钟 +'SLIPPAGE_TOLERANCE_PCT': 0.002, # 0.2% +'USE_LIMIT_ON_CLOSE': True, + +# 小众币优化 +'FUNDING_RATE_THRESHOLD': 0.001, # 0.1% +'FUNDING_RATE_EARLY_EXIT_HOURS': 1, # 结算前1小时 +``` diff --git a/trading_system/config.py b/trading_system/config.py index 5fadf55..b58944d 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -205,8 +205,21 @@ def _get_trading_config(): 'CONFIRM_INTERVAL': '4h', 'ENTRY_INTERVAL': '15m', 'MIN_VOLUME_24H': 5000000, # 降低到500万以获取更多推荐(推荐系统可以更宽松) + 'MIN_VOLUME_24H_STRICT': 10000000, # ⚠️ 优化:严格成交量过滤,24H Volume低于1000万美金直接剔除 'MIN_VOLATILITY': 0.02, 'MIN_SIGNAL_STRENGTH': 8, # 提高至8,只交易高质量信号(低频波段) + + # ===== 动态过滤优化 ===== + 'BETA_FILTER_ENABLED': True, # 大盘共振过滤:BTC/ETH下跌时屏蔽多单 + 'BETA_FILTER_THRESHOLD': -0.03, # -3%,BTC/ETH下跌超过此阈值时屏蔽多单 + 'ATR_SPIKE_THRESHOLD': 2.0, # ATR异常激增阈值(当前ATR / 平均ATR) + 'SIGNAL_STRENGTH_POSITION_MULTIPLIER': {8: 0.5, 9: 1.0, 10: 1.0}, # 信号强度分级:8分50%仓位,9-10分100%仓位 + + # ===== 仓位管理优化 ===== + 'USE_FIXED_RISK_SIZING': True, # 使用固定风险百分比计算仓位(凯利公式) + 'FIXED_RISK_PERCENT': 0.02, # 每笔单子承受的风险(2%) + 'MAX_LEVERAGE_SMALL_CAP': 5, # 小众币最大杠杆限制 + 'ATR_LEVERAGE_REDUCTION_THRESHOLD': 0.05, # ATR超过5%时降低杠杆 'LEVERAGE': 10, # 基础杠杆倍数 'USE_DYNAMIC_LEVERAGE': True, # 是否启用动态杠杆(根据信号强度调整) 'MAX_LEVERAGE': 15, # 最大杠杆倍数(降低到15,更保守,配合更大的保证金) diff --git a/trading_system/market_scanner.py b/trading_system/market_scanner.py index 769fe81..852a380 100644 --- a/trading_system/market_scanner.py +++ b/trading_system/market_scanner.py @@ -105,13 +105,22 @@ class MarketScanner: if isinstance(r, dict) and r.get('changePercent') is not None ] + # ⚠️ 优化2:成交量验证 - 24H Volume低于1000万美金,直接剔除 + min_volume_strict = cfg.get('MIN_VOLUME_24H_STRICT', 10000000) # 默认1000万美金 + min_volume_normal = cfg.get('MIN_VOLUME_24H', config.TRADING_CONFIG['MIN_VOLUME_24H']) + # 使用更严格的成交量要求 + min_volume = max(min_volume_strict, min_volume_normal) + # 过滤最小涨跌幅和成交量 filtered_results = [ r for r in valid_results if abs(r['changePercent']) >= cfg.get('MIN_CHANGE_PERCENT', config.TRADING_CONFIG['MIN_CHANGE_PERCENT']) - and r.get('volume24h', 0) >= cfg.get('MIN_VOLUME_24H', config.TRADING_CONFIG['MIN_VOLUME_24H']) + and r.get('volume24h', 0) >= min_volume ] + if min_volume_strict > min_volume_normal: + logger.info(f"使用严格成交量过滤: {min_volume_strict/1000000:.1f}M USDT (原标准: {min_volume_normal/1000000:.1f}M USDT)") + # 按信号得分和涨跌幅综合排序,取前N个 # 优先考虑技术指标信号得分高的 sorted_results = sorted( diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 2a64716..3d9d0c3 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -198,9 +198,32 @@ class PositionManager: await self.client.set_leverage(symbol, leverage) # 计算仓位大小(传入实际使用的杠杆) + # ⚠️ 优化:先估算止损价格,用于固定风险百分比计算 logger.info(f"开始为 {symbol} 计算仓位大小...") + + # 获取当前价格用于估算止损 + ticker = await self.client.get_ticker_24h(symbol) + if not ticker: + return None + estimated_entry_price = ticker['price'] + estimated_side = trade_direction if trade_direction else ('BUY' if change_percent > 0 else 'SELL') + + # 估算止损价格(用于固定风险计算) + estimated_stop_loss = None + if atr and atr > 0: + atr_multiplier = config.TRADING_CONFIG.get('ATR_STOP_LOSS_MULTIPLIER', 1.8) + if estimated_side == 'BUY': + estimated_stop_loss = estimated_entry_price - (atr * atr_multiplier) + else: # SELL + estimated_stop_loss = estimated_entry_price + (atr * atr_multiplier) + quantity = await self.risk_manager.calculate_position_size( - symbol, change_percent, leverage=leverage + symbol, change_percent, leverage=leverage, + entry_price=estimated_entry_price, + stop_loss_price=estimated_stop_loss, + side=estimated_side, + atr=atr, + signal_strength=signal_strength ) if quantity is None: diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index 89b84d6..450c5bc 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -231,14 +231,26 @@ class RiskManager: self, symbol: str, change_percent: float, - leverage: Optional[int] = None + leverage: Optional[int] = None, + entry_price: Optional[float] = None, + stop_loss_price: Optional[float] = None, + side: Optional[str] = None, + atr: Optional[float] = None, + signal_strength: Optional[int] = None ) -> Optional[float]: """ 根据涨跌幅和风险参数计算合适的仓位大小 + ⚠️ 优化:支持固定风险百分比计算(凯利公式)和信号强度分级 Args: symbol: 交易对 change_percent: 涨跌幅百分比 + leverage: 杠杆倍数(可选) + entry_price: 入场价格(可选,如果提供则用于固定风险计算) + stop_loss_price: 止损价格(可选,如果提供则用于固定风险计算) + side: 交易方向 'BUY' 或 'SELL'(可选,用于固定风险计算) + atr: ATR值(可选,用于估算止损) + signal_strength: 信号强度(可选,用于仓位分级) Returns: 建议的仓位数量,如果不符合条件则返回None @@ -326,11 +338,18 @@ class RiskManager: logger.warning(f" 💡 建议: 提高 MAX_POSITION_PERCENT 或降低杠杆/更换币种,确保最小名义价值可满足") return None - # 计算数量(考虑合约的最小数量精度) - quantity = notional_value / current_price - logger.info(f" 计算数量: {quantity:.4f} (名义: {notional_value:.2f} / 价格: {current_price:.4f})") + # quantity 应该已经计算好了(固定风险或传统方法) + if quantity is None: + logger.error(f" ❌ {symbol} 仓位计算失败:quantity为None") + return None - # 验证计算出的数量对应的名义价值 + # 计算名义价值和保证金(如果还未计算) + if 'notional_value' not in locals() or 'margin_value' not in locals(): + notional_value = quantity * current_price + margin_value = notional_value / actual_leverage + + # 确保仓位价值满足最小名义价值要求(币安要求至少5 USDT) + min_notional = 5.0 # 币安合约最小名义价值 calculated_notional = quantity * current_price if calculated_notional < min_notional: # 如果计算出的名义价值仍然不足,增加数量 @@ -352,6 +371,7 @@ class RiskManager: ) # 检查是否可以使用更大的仓位价值(但不超过最大仓位限制) + max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] max_margin_value = available_balance * max_position_percent if min_margin_usdt <= max_margin_value: margin_value = min_margin_usdt @@ -760,7 +780,7 @@ class RiskManager: ) return take_profit_price - async def calculate_dynamic_leverage(self, signal_strength: int, symbol: str = None) -> int: + async def calculate_dynamic_leverage(self, signal_strength: int, symbol: str = None, atr: Optional[float] = None, entry_price: Optional[float] = None) -> int: """ 根据信号强度计算动态杠杆倍数 信号强度越高,杠杆倍数越高,以最大化收益 @@ -779,6 +799,19 @@ class RiskManager: 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) diff --git a/trading_system/strategy.py b/trading_system/strategy.py index 6db7e51..14d399e 100644 --- a/trading_system/strategy.py +++ b/trading_system/strategy.py @@ -181,8 +181,12 @@ class TradingStrategy: ) # 根据信号强度计算动态杠杆(高质量信号使用更高杠杆) - # 同时检查交易对支持的最大杠杆限制 - dynamic_leverage = await self.risk_manager.calculate_dynamic_leverage(signal_strength, symbol) + # ⚠️ 优化:同时检查交易对支持的最大杠杆限制和小众币限制 + dynamic_leverage = await self.risk_manager.calculate_dynamic_leverage( + signal_strength, symbol, + atr=symbol_info.get('atr'), + entry_price=symbol_info.get('price') + ) logger.info( f"{symbol} 使用动态杠杆: {dynamic_leverage}x " f"(信号强度: {signal_strength}/10)" @@ -321,6 +325,22 @@ class TradingStrategy: 交易信号字典 {'should_trade': bool, 'direction': str, 'reason': str, 'strength': int} """ symbol = symbol_info['symbol'] + + # ⚠️ 优化1:大盘共振(Beta Filter)- 当BTC/ETH剧烈下跌时,屏蔽所有多单 + beta_filter_enabled = config.TRADING_CONFIG.get('BETA_FILTER_ENABLED', True) + if beta_filter_enabled: + beta_filter_result = await self._check_beta_filter() + if beta_filter_result['should_block_buy']: + # 如果大盘暴跌,屏蔽所有多单 + if symbol_info.get('direction') == 'BUY' or (symbol_info.get('changePercent', 0) > 0): + return { + 'should_trade': False, + 'direction': None, + 'reason': f"❌ 大盘共振过滤:{beta_filter_result['reason']},屏蔽所有多单", + 'strength': 0, + 'trend_4h': symbol_info.get('trend_4h') + } + logger.debug(f"{symbol} 大盘共振检查通过(做空信号不受影响)") current_price = symbol_info['price'] rsi = symbol_info.get('rsi') macd = symbol_info.get('macd') @@ -460,6 +480,83 @@ class TradingStrategy: 'strategy_type': 'trend_following' # 标记策略类型 } + async def _check_beta_filter(self) -> Dict: + """ + 大盘共振(Beta Filter)检查 + 当BTC或ETH在15min/1h周期剧烈下跌时,返回应该屏蔽多单的信号 + + Returns: + {'should_block_buy': bool, 'reason': str} + """ + beta_filter_threshold = config.TRADING_CONFIG.get('BETA_FILTER_THRESHOLD', -0.03) # 默认-3% + + try: + # 检查BTC和ETH的15min和1h周期 + btcusdt_15m = await self._get_symbol_change_period('BTCUSDT', '15m', 5) # 最近5根K线 + btcusdt_1h = await self._get_symbol_change_period('BTCUSDT', '1h', 3) # 最近3根K线 + ethusdt_15m = await self._get_symbol_change_period('ETHUSDT', '15m', 5) + ethusdt_1h = await self._get_symbol_change_period('ETHUSDT', '1h', 3) + + # 检查是否有剧烈下跌 + btc_15m_down = btcusdt_15m and btcusdt_15m < beta_filter_threshold + btc_1h_down = btcusdt_1h and btcusdt_1h < beta_filter_threshold + eth_15m_down = ethusdt_15m and ethusdt_15m < beta_filter_threshold + eth_1h_down = ethusdt_1h and ethusdt_1h < beta_filter_threshold + + if btc_15m_down or btc_1h_down or eth_15m_down or eth_1h_down: + reasons = [] + if btc_15m_down: + reasons.append(f"BTC 15m下跌{btcusdt_15m*100:.2f}%") + if btc_1h_down: + reasons.append(f"BTC 1h下跌{btcusdt_1h*100:.2f}%") + if eth_15m_down: + reasons.append(f"ETH 15m下跌{ethusdt_15m*100:.2f}%") + if eth_1h_down: + reasons.append(f"ETH 1h下跌{ethusdt_1h*100:.2f}%") + + return { + 'should_block_buy': True, + 'reason': f"大盘暴跌:{', '.join(reasons)}" + } + + return { + 'should_block_buy': False, + 'reason': '大盘正常' + } + except Exception as e: + logger.warning(f"大盘共振检查失败: {e},允许交易(容错)") + return { + 'should_block_buy': False, + 'reason': f'检查失败: {e}' + } + + async def _get_symbol_change_period(self, symbol: str, interval: str, periods: int) -> Optional[float]: + """ + 获取指定交易对在指定周期内的涨跌幅 + + Args: + symbol: 交易对 + interval: K线周期(15m, 1h等) + periods: 检查最近N根K线 + + Returns: + 涨跌幅(负数表示下跌),如果获取失败返回None + """ + try: + klines = await self.client.get_klines(symbol, interval, limit=periods + 1) + if not klines or len(klines) < 2: + return None + + # 计算最近N根K线的总涨跌幅 + first_close = float(klines[0][4]) # 第一根K线的收盘价 + last_close = float(klines[-1][4]) # 最后一根K线的收盘价 + + change = (last_close - first_close) / first_close + return change + except Exception as e: + logger.debug(f"获取{symbol} {interval}周期涨跌幅失败: {e}") + return None + def _judge_trend_4h(self, price_4h: float, ema20_4h: Optional[float], ema50_4h: Optional[float], macd_4h: Optional[Dict]) -> str: """ 使用多指标投票机制判断4H趋势(避免单一指标误导)