diff --git a/docs/止损止盈计算说明.md b/docs/止损止盈计算说明.md index 2235d36..fb5dd37 100644 --- a/docs/止损止盈计算说明.md +++ b/docs/止损止盈计算说明.md @@ -47,3 +47,5 @@ **已实现**:在 `risk_manager.get_take_profit_price` 中增加了 **USE_MARGIN_CAP_FOR_TP**(默认 **True**):当使用盈亏比算出 TP2 时,若该价格比「TAKE_PROFIT_PERCENT 对应的保证金止盈价」更远,则**改用保证金止盈价**作为 TP2,这样止盈不会远到难以触及。 - **⚠️ 不要关闭**:普遍出现的「止盈特别远(如 +238% 保证金)、亏损扛单」是因为**没有封顶**时用了「止损距离×3」的止盈。**关掉 USE_MARGIN_CAP_FOR_TP 会恢复那种过远止盈,加重扛单**。应保持 **True**,并确保交易进程已重启/配置已生效,新开仓才会用封顶后的止盈。 + +**止损封顶(USE_MARGIN_CAP_FOR_SL)**:若仅封顶止盈、不封顶止损,会出现「止盈 55%、止损 -58%~-78%」——止损仍过宽、易扛单。因此增加了 **USE_MARGIN_CAP_FOR_SL**(默认 True):当 ATR(或技术)止损对应的**保证金亏损**超过配置的 STOP_LOSS_PERCENT(如 10%)时,**改用保证金止损**,使止损不再超过 10% 保证金。与 USE_MARGIN_CAP_FOR_TP 一起使用,新开仓的 SL/TP 都会在「保证金比例」范围内,避免极端远距。 diff --git a/trading_system/config.py b/trading_system/config.py index a5a6f26..80c5edd 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -207,6 +207,7 @@ DEFAULT_TRADING_CONFIG = { 'ATR_TAKE_PROFIT_MULTIPLIER': 6.0, # ATR止盈倍数6.0(追求更高盈亏比) 'RISK_REWARD_RATIO': 3.0, # 盈亏比3:1 'USE_MARGIN_CAP_FOR_TP': True, # 止盈按保证金上限封顶,避免 TP 过远难以触及、亏损扛单。勿关。 + 'USE_MARGIN_CAP_FOR_SL': True, # 止损按保证金上限封顶,避免 ATR 过宽导致 -60%~-80% 保证金扛单。勿关。 'ATR_PERIOD': 14, # ATR计算周期14 'USE_DYNAMIC_ATR_MULTIPLIER': False, # 不使用动态ATR 'ATR_MULTIPLIER_MIN': 0.5, # 动态ATR倍数最小值 diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index e9e7bc0..0bd6423 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -1135,21 +1135,32 @@ class RiskManager: f"已采用保证金止损以与策略一致" ) - # 如果最终止损价对应的保证金百分比超过配置值,且不是ATR/技术止损,则强制使用保证金止损 - if final_stop_loss_pct_margin > (stop_loss_percent * 100) and not is_atr_or_tech: - logger.warning( - f"⚠️ 最终止损价({final_stop_loss:.4f}, 使用{selected_method})对应的保证金百分比({final_stop_loss_pct_margin:.2f}%) " - f"超过配置值({stop_loss_percent*100:.1f}%),强制使用保证金止损({stop_loss_price_margin:.4f})" - ) - final_stop_loss = stop_loss_price_margin - selected_method = '保证金(强制)' - final_stop_loss_pct_margin = stop_loss_percent * 100 - elif final_stop_loss_pct_margin > (stop_loss_percent * 100) and is_atr_or_tech: - logger.info( - f"ℹ️ {selected_method}止损 ({final_stop_loss:.4f}) 超过保证金配置值 " - f"({final_stop_loss_pct_margin:.2f}% > {stop_loss_percent*100:.1f}%)," - f"但予以保留(风险已通过仓位控制)" - ) + # 如果最终止损价对应的保证金百分比超过配置值,强制使用保证金止损(含 ATR/技术止损) + # 避免 ATR 过宽导致止损 -58%~-78% 保证金、长期扛单;与 USE_MARGIN_CAP_FOR_TP 一致 + use_margin_cap_sl = bool(config.TRADING_CONFIG.get('USE_MARGIN_CAP_FOR_SL', True)) + if final_stop_loss_pct_margin > (stop_loss_percent * 100): + if not is_atr_or_tech: + logger.warning( + f"⚠️ 最终止损价({final_stop_loss:.4f}, 使用{selected_method})对应的保证金百分比({final_stop_loss_pct_margin:.2f}%) " + f"超过配置值({stop_loss_percent*100:.1f}%),强制使用保证金止损({stop_loss_price_margin:.4f})" + ) + final_stop_loss = stop_loss_price_margin + selected_method = '保证金(强制)' + final_stop_loss_pct_margin = stop_loss_percent * 100 + elif use_margin_cap_sl: + logger.info( + f"止损已按保证金上限封顶: {selected_method}止损({final_stop_loss_pct_margin:.1f}% 保证金) " + f"超过 STOP_LOSS_PERCENT({stop_loss_percent*100:.1f}%),采用保证金止损({stop_loss_price_margin:.4f})" + ) + final_stop_loss = stop_loss_price_margin + selected_method = '保证金(止损上限)' + final_stop_loss_pct_margin = stop_loss_percent * 100 + else: + logger.info( + f"ℹ️ {selected_method}止损 ({final_stop_loss:.4f}) 超过保证金配置值 " + f"({final_stop_loss_pct_margin:.2f}% > {stop_loss_percent*100:.1f}%)," + f"但予以保留(USE_MARGIN_CAP_FOR_SL=False)" + ) # ⚠️ 最终强制检查:最小止损距离(防止 -2021 Order would immediately trigger) # 此检查必须在最后执行,覆盖之前的逻辑,因为这是交易所/系统的硬性约束 diff --git a/持仓记录_2026-02-14T16-45-51.json b/持仓记录_2026-02-14T16-45-51.json new file mode 100644 index 0000000..8aae1d3 --- /dev/null +++ b/持仓记录_2026-02-14T16-45-51.json @@ -0,0 +1,452 @@ +[ + { + "id": 4640, + "symbol": "PIPPINUSDT", + "side": "SELL", + "quantity": 13, + "entry_price": 0.70165, + "entry_value_usdt": 9.12145, + "notional_usdt": 9.060078690000001, + "margin_usdt": 4.5300393450000005, + "original_notional_usdt": 9.12145, + "original_margin_usdt": 4.560725, + "mark_price": 0.69692913, + "pnl": 0.06137131, + "pnl_percent": 1.3547632884853011, + "leverage": 2, + "entry_time": 1771087159, + "stop_loss_price": 0.90642143, + "take_profit_price": 0.50869625, + "take_profit_1": 0.39449286, + "take_profit_2": 0.50869625, + "atr": 0.06825714, + "entry_order_id": 4503065801, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449763200, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.5087, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449763193, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.90642, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 0.90642 (NEW)", + "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.5087 (NEW)", + "binance_open_orders_raw": [ + { + "orderId": 2000000449763200, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.5087, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449763193, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.90642, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4643, + "symbol": "ZECUSDT", + "side": "SELL", + "quantity": 0.084, + "entry_price": 283.79, + "entry_value_usdt": 23.83836, + "notional_usdt": 23.828280000000003, + "margin_usdt": 4.765656000000001, + "original_notional_usdt": 23.83836, + "original_margin_usdt": 4.767672, + "mark_price": 283.67, + "pnl": 0.01008, + "pnl_percent": 0.21151337822117247, + "leverage": 5, + "entry_time": 1771087205, + "stop_loss_price": 327.98, + "take_profit_price": 252.5731, + "take_profit_1": 217.505, + "take_profit_2": 252.5731, + "atr": 14.73, + "entry_order_id": 797657761399, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449766575, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 252.58, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449766566, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 327.98, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 327.98 (NEW)", + "active_tp_orders": "TAKE_PROFIT_MARKET @ 252.58 (NEW)", + "binance_open_orders_raw": [ + { + "orderId": 2000000449766575, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 252.58, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449766566, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 327.98, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4641, + "symbol": "TAOUSDT", + "side": "SELL", + "quantity": 0.104, + "entry_price": 191.45, + "entry_value_usdt": 19.9108, + "notional_usdt": 19.9984220904, + "margin_usdt": 4.9996055226, + "original_notional_usdt": 19.9108, + "original_margin_usdt": 4.9777, + "mark_price": 192.2925201, + "pnl": -0.08762209, + "pnl_percent": -1.7525800706459123, + "leverage": 4, + "entry_time": 1771087174, + "stop_loss_price": 223.29714286, + "take_profit_price": 165.125625, + "take_profit_1": 143.67928571, + "take_profit_2": 165.125625, + "atr": 10.61571429, + "entry_order_id": 9523399174, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449764167, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 165.13, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449764159, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 223.29, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 223.29 (NEW)", + "active_tp_orders": "TAKE_PROFIT_MARKET @ 165.13 (NEW)", + "binance_open_orders_raw": [ + { + "orderId": 2000000449764167, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 165.13, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449764159, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 223.29, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4642, + "symbol": "COAIUSDT", + "side": "SELL", + "quantity": 22, + "entry_price": 0.4395, + "entry_value_usdt": 9.669, + "notional_usdt": 9.4624585, + "margin_usdt": 4.73122925, + "original_notional_usdt": 9.669, + "original_margin_usdt": 4.8345, + "mark_price": 0.43011175, + "pnl": 0.2065415, + "pnl_percent": 4.365493386311813, + "leverage": 2, + "entry_time": 1771087179, + "stop_loss_price": 0.57938571, + "take_profit_price": 0.3186375, + "take_profit_1": 0.22967143, + "take_profit_2": 0.3186375, + "atr": 0.04662857, + "entry_order_id": 2086471512, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449764560, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.3187, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449764551, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.5793, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 0.5793 (NEW)", + "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.3187 (NEW)", + "binance_open_orders_raw": [ + { + "orderId": 2000000449764560, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.3187, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449764551, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.5793, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4647, + "symbol": "PYTHUSDT", + "side": "SELL", + "quantity": 377, + "entry_price": 0.0610065251989, + "entry_value_usdt": 22.9994599999853, + "notional_usdt": 23.053546230000002, + "margin_usdt": 4.610709246000001, + "original_notional_usdt": 22.9994505, + "original_margin_usdt": 4.5998901, + "mark_price": 0.06114999, + "pnl": -0.05408819, + "pnl_percent": -1.173099128879661, + "leverage": 5, + "entry_time": 1771087459, + "stop_loss_price": 0.06959507, + "take_profit_price": 0.05429579, + "take_profit_1": 0.04812364, + "take_profit_2": 0.05429579, + "atr": 0.00286286, + "entry_order_id": 5286793226, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449784169, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.0543, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449784150, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.06959, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 0.06959 (NEW)", + "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.0543 (NEW)", + "binance_open_orders_raw": [ + { + "orderId": 2000000449784169, + "type": "TAKE_PROFIT_MARKET", + "side": "BUY", + "stopPrice": 0.0543, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + }, + { + "orderId": 2000000449784150, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 0.06959, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4639, + "symbol": "VVVUSDT", + "side": "SELL", + "quantity": 3.64, + "entry_price": 2.792, + "entry_value_usdt": 10.16288, + "notional_usdt": 10.46136, + "margin_usdt": 5.23068, + "original_notional_usdt": 10.16288, + "original_margin_usdt": 5.08144, + "mark_price": 2.874, + "pnl": -0.29848, + "pnl_percent": -5.706332637439109, + "leverage": 2, + "entry_time": 1771081222, + "stop_loss_price": 3.776, + "take_profit_price": -0.16, + "take_profit_1": 1.316, + "take_profit_2": -0.16, + "atr": 0.328, + "entry_order_id": 824862620, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449333341, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 3.776, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 3.776 (NEW)", + "active_tp_orders": "", + "binance_open_orders_raw": [ + { + "orderId": 2000000449333341, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 3.776, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + }, + { + "id": 4637, + "symbol": "RIVERUSDT", + "side": "SELL", + "quantity": 0.7, + "entry_price": 13.874, + "entry_value_usdt": 9.7118, + "notional_usdt": 9.251199999999999, + "margin_usdt": 4.6255999999999995, + "original_notional_usdt": 9.7118, + "original_margin_usdt": 4.8559, + "mark_price": 13.216, + "pnl": 0.4606, + "pnl_percent": 9.95762711864407, + "leverage": 2, + "entry_time": 1771079231, + "stop_loss_price": 19.02242857, + "take_profit_price": -1.57128571, + "take_profit_1": 6.15135714, + "take_profit_2": -1.57128571, + "atr": 1.71614286, + "entry_order_id": 3923246641, + "entry_order_type": "LIMIT", + "open_orders": [ + { + "orderId": 2000000449191175, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 19.022, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ], + "active_sl_orders": "STOP_MARKET @ 19.022 (NEW)", + "active_tp_orders": "", + "binance_open_orders_raw": [ + { + "orderId": 2000000449191175, + "type": "STOP_MARKET", + "side": "BUY", + "stopPrice": 19.022, + "price": 0, + "origType": "CONDITIONAL", + "reduceOnly": true, + "status": "NEW" + } + ] + } +] \ No newline at end of file