diff --git a/trading_system/config.py b/trading_system/config.py index 405edd5..d781cf1 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -198,7 +198,7 @@ DEFAULT_TRADING_CONFIG = { 'EXCLUDE_MAJOR_COINS': True, # 排除主流币 'STOP_LOSS_PERCENT': 0.05, # 基础止损5%(配合ATR动态止损,作为保底) 'TAKE_PROFIT_PERCENT': 0.25, # 第二目标止盈25%(略拉近止盈以提高触达率) - 'TAKE_PROFIT_1_PERCENT': 0.15, # 第一目标止盈15%(更容易先锁定部分利润) + 'TAKE_PROFIT_1_PERCENT': 0.12, # 第一目标止盈12%(山寨币不必久拿,早点落袋为安,降低反转风险) 'MIN_RR_FOR_TP1': 1.2, # 第一目标止盈的最小盈亏比(相对于止损距离),略放宽以提高触发率 'MIN_STOP_LOSS_PRICE_PCT': 0.03, # 最小止损价格变动3%(适当放宽止损,减少正常波动被扫) 'MIN_TAKE_PROFIT_PRICE_PCT': 0.02, # 最小止盈价格变动2% @@ -253,6 +253,10 @@ DEFAULT_TRADING_CONFIG = { 'TIME_STOP_MAX_HOLD_HOURS': 8, # 持仓超过 N 小时且未达最小盈利则考虑平仓(低波动期更适用) 'TIME_STOP_MIN_PNL_PCT_TO_HOLD': 0.0, # 持仓超过时间阈值时,若 pnl% 低于此值则平仓(0=允许小亏即走) 'TIME_STOP_ENABLED': True, # 是否启用时间/无盈利止损(可与 regime 结合:仅低波动期或始终启用) + # 山寨币早止盈:盈利达标且持仓满 N 小时则市价止盈,不等挂单 TP,避免反转回吐 + 'EARLY_TAKE_PROFIT_ENABLED': True, # 是否启用「盈利达标+持仓时长」早止盈 + 'EARLY_TAKE_PROFIT_MIN_PNL_PCT': 10.0, # 盈利达到此比例(% of margin)即符合条件,默认 10% + 'EARLY_TAKE_PROFIT_MIN_HOLD_HOURS': 2.0, # 且持仓至少 N 小时才触发(避免刚开仓就平) # 开仓前流动性检查(价差/深度):低量期可减少滑点与冲击成本 'LIQUIDITY_CHECK_BEFORE_ENTRY': False, # 默认关闭;开启后开仓前检查盘口价差与深度,不通过则跳过 'LIQUIDITY_MAX_SPREAD_PCT': 0.005, # 买一卖一价差超过此比例(0.5%)则跳过 diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 3b26ce6..b0ecf70 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -1985,6 +1985,32 @@ class PositionManager: except Exception as e: logger.debug(f"从Redis重新加载配置失败: {e}") + # 山寨币早止盈:盈利达标且持仓满 N 小时则市价止盈,不必等挂单 TP,避免反转回吐 + early_tp_enabled = config.TRADING_CONFIG.get('EARLY_TAKE_PROFIT_ENABLED', True) + if early_tp_enabled and pnl_percent_margin > 0: + min_pnl_pct = float(config.TRADING_CONFIG.get('EARLY_TAKE_PROFIT_MIN_PNL_PCT', 10) or 10) + min_hold_hours = float(config.TRADING_CONFIG.get('EARLY_TAKE_PROFIT_MIN_HOLD_HOURS', 2) or 2) + hold_hours = 0.0 + entry_time = position_info.get('entryTime') + if entry_time is not None: + try: + if isinstance(entry_time, datetime): + hold_hours = (get_beijing_time() - entry_time).total_seconds() / 3600.0 + elif isinstance(entry_time, str) and len(entry_time) >= 19: + entry_dt = datetime.strptime(entry_time[:19], '%Y-%m-%d %H:%M:%S') + hold_hours = (get_beijing_time() - entry_dt).total_seconds() / 3600.0 + else: + hold_hours = (time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0)) / 3600.0 + except Exception: + pass + if pnl_percent_margin >= min_pnl_pct and hold_hours >= min_hold_hours: + logger.info( + f"{symbol} [早止盈] 盈利{pnl_percent_margin:.2f}%≥{min_pnl_pct}% 且持仓{hold_hours:.1f}h≥{min_hold_hours}h,市价止盈离场(山寨币不必久拿)" + ) + if await self.close_position(symbol, reason='early_take_profit'): + closed_positions.append(symbol) + continue + # 检查是否启用移动止损(默认False,需要显式启用) use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', False) if use_trailing: diff --git a/持仓记录_2026-02-19T09-39-29.json b/持仓记录_2026-02-19T09-39-29.json deleted file mode 100644 index b6f3541..0000000 --- a/持仓记录_2026-02-19T09-39-29.json +++ /dev/null @@ -1,702 +0,0 @@ -[ - { - "id": null, - "symbol": "ZECUSDT", - "side": "SELL", - "quantity": 0.112, - "entry_price": 265.8, - "entry_value_usdt": 29.7696, - "notional_usdt": 29.12784, - "margin_usdt": 7.28196, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 260.07, - "pnl": 0.64176, - "pnl_percent": 8.813011881416543, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000479271333, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 239.04, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479271328, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 273.77, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 273.77 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 239.04 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000479271333, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 239.04, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479271328, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 273.77, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "HYPEUSDT", - "side": "SELL", - "quantity": 0.96, - "entry_price": 28.503, - "entry_value_usdt": 27.36288, - "notional_usdt": 27.712493712, - "margin_usdt": 6.928123428, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 28.86718095, - "pnl": -0.34961371, - "pnl_percent": -5.046297365128294, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000479340803, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 26.636, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479340801, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 29.358, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 29.358 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 26.636 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000479340803, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 26.636, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479340801, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 29.358, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "TAOUSDT", - "side": "SELL", - "quantity": 0.211, - "entry_price": 185.4614691943, - "entry_value_usdt": 39.1323699999973, - "notional_usdt": 38.51799427279, - "margin_usdt": 9.6294985681975, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 182.54973589, - "pnl": 0.61437572, - "pnl_percent": 6.38014238902371, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480794655, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 170.49, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480794649, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 189.07, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 189.07 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 170.49 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480794655, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 170.49, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480794649, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 189.07, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "FILUSDT", - "side": "SELL", - "quantity": 60, - "entry_price": 0.933, - "entry_value_usdt": 55.980000000000004, - "notional_usdt": 55.552446, - "margin_usdt": 13.8881115, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 0.9258741, - "pnl": 0.427554, - "pnl_percent": 3.078561113222629, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000479413824, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.875, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479413817, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.96, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 0.96 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.875 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000479413824, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.875, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479413817, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.96, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "TRUMPUSDT", - "side": "SELL", - "quantity": 7.2, - "entry_price": 3.436, - "entry_value_usdt": 24.7392, - "notional_usdt": 24.624, - "margin_usdt": 6.156, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 3.42, - "pnl": 0.1152, - "pnl_percent": 1.8713450292397662, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000479508471, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 3.19, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479508466, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 3.539, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 3.539 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 3.19 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000479508471, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 3.19, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000479508466, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 3.539, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "PUMPUSDT", - "side": "SELL", - "quantity": 9729, - "entry_price": 0.002039, - "entry_value_usdt": 19.837431, - "notional_usdt": 19.934721, - "margin_usdt": 4.98368025, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 0.002049, - "pnl": -0.09729, - "pnl_percent": -1.9521717911176184, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480154344, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.001851, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480154340, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.0021, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 0.0021 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.001851 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480154344, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.001851, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480154340, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.0021, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "NAORISUSDT", - "side": "BUY", - "quantity": 335, - "entry_price": 0.0376422985075, - "entry_value_usdt": 12.610170000012499, - "notional_usdt": 13.52641225, - "margin_usdt": 13.52641225, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 0.04037735, - "pnl": 0.9162451, - "pnl_percent": 6.773748153358257, - "leverage": 1, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480529814, - "type": "TAKE_PROFIT_MARKET", - "side": "SELL", - "stopPrice": 0.06148, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480529809, - "type": "STOP_MARKET", - "side": "SELL", - "stopPrice": 0.03643, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 0.03643 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.06148 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480529814, - "type": "TAKE_PROFIT_MARKET", - "side": "SELL", - "stopPrice": 0.06148, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480529809, - "type": "STOP_MARKET", - "side": "SELL", - "stopPrice": 0.03643, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "KITEUSDT", - "side": "BUY", - "quantity": 617, - "entry_price": 0.2258499027553, - "entry_value_usdt": 139.3493900000201, - "notional_usdt": 141.32854537, - "margin_usdt": 35.3321363425, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 0.22905761, - "pnl": 1.97915707, - "pnl_percent": 5.601577699164852, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480845123, - "type": "TAKE_PROFIT_MARKET", - "side": "SELL", - "stopPrice": 0.26007, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480845117, - "type": "STOP_MARKET", - "side": "SELL", - "stopPrice": 0.22204, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 0.22204 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.26007 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480845123, - "type": "TAKE_PROFIT_MARKET", - "side": "SELL", - "stopPrice": 0.26007, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480845117, - "type": "STOP_MARKET", - "side": "SELL", - "stopPrice": 0.22204, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "AAVEUSDT", - "side": "SELL", - "quantity": 0.5, - "entry_price": 123.936, - "entry_value_usdt": 61.968, - "notional_usdt": 61.495, - "margin_usdt": 15.37375, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 122.99, - "pnl": 0.473, - "pnl_percent": 3.0766729002357915, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480581320, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 115.95, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480581308, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 127.69, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 127.69 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 115.95 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480581320, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 115.95, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480581308, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 127.69, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - }, - { - "id": null, - "symbol": "ASTERUSDT", - "side": "SELL", - "quantity": 84, - "entry_price": 0.69645, - "entry_value_usdt": 58.5018, - "notional_usdt": 58.576746480000004, - "margin_usdt": 14.644186620000001, - "original_notional_usdt": null, - "original_margin_usdt": null, - "mark_price": 0.69734222, - "pnl": -0.07494648, - "pnl_percent": -0.5117831528972961, - "leverage": 4, - "entry_time": null, - "stop_loss_price": null, - "take_profit_price": null, - "take_profit_1": null, - "take_profit_2": null, - "atr": null, - "entry_order_id": null, - "entry_order_type": null, - "open_orders": [ - { - "orderId": 2000000480743935, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.6525, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480743932, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.7168, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ], - "active_sl_orders": "STOP_MARKET @ 0.7168 (NEW)", - "active_tp_orders": "TAKE_PROFIT_MARKET @ 0.6525 (NEW)", - "binance_open_orders_raw": [ - { - "orderId": 2000000480743935, - "type": "TAKE_PROFIT_MARKET", - "side": "BUY", - "stopPrice": 0.6525, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - }, - { - "orderId": 2000000480743932, - "type": "STOP_MARKET", - "side": "BUY", - "stopPrice": 0.7168, - "price": 0, - "origType": "CONDITIONAL", - "reduceOnly": true, - "status": "NEW" - } - ] - } -] \ No newline at end of file