From b779b7b9ec1589d9fe6cef96c6192174a36b6f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Sat, 14 Feb 2026 19:56:58 +0800 Subject: [PATCH] 1 --- trading_system/position_manager.py | 39 ++++++++++++++++++++++++++++++ trading_system/strategy.py | 7 +++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 1331593..847e3e2 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -2171,6 +2171,45 @@ class PositionManager: db_open_symbols = {t['symbol'] for t in db_open_trades} logger.debug(f"数据库open状态: {len(db_open_symbols)} 个 ({', '.join(db_open_symbols) if db_open_symbols else '无'})") + # 2.5 用「DB 有 open 且币安也有」的持仓填充 active_positions,确保这些持仓会被后续启动的监控覆盖 + in_both = db_open_symbols & binance_symbols + for symbol in in_both: + if symbol in self.active_positions: + continue + trade = next((t for t in db_open_trades if t.get('symbol') == symbol), None) + pos = next((p for p in binance_positions if p.get('symbol') == symbol), None) + if not trade or not pos or float(pos.get('positionAmt', 0)) == 0: + continue + try: + entry_price = float(trade.get('entry_price', 0) or pos.get('entryPrice', 0)) + quantity = abs(float(pos.get('positionAmt', 0))) + side = 'BUY' if float(pos.get('positionAmt', 0)) > 0 else 'SELL' + leverage = float(pos.get('leverage', 10) or trade.get('leverage', 10) or 10) + stop_loss_price = trade.get('stop_loss_price') + take_profit_price = trade.get('take_profit_price') or trade.get('take_profit_1') + if stop_loss_price is None or take_profit_price is None: + stop_loss_pct = config.TRADING_CONFIG.get('STOP_LOSS_PERCENT', 0.08) + if stop_loss_pct is not None and stop_loss_pct > 1: + stop_loss_pct = stop_loss_pct / 100.0 + take_profit_pct = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT', 0.15) + if take_profit_pct is not None and take_profit_pct > 1: + take_profit_pct = take_profit_pct / 100.0 + if not take_profit_pct: + take_profit_pct = (stop_loss_pct or 0.08) * 2.0 + stop_loss_price = self.risk_manager.get_stop_loss_price(entry_price, side, quantity, leverage, stop_loss_pct=stop_loss_pct) + take_profit_price = take_profit_price or self.risk_manager.get_take_profit_price(entry_price, side, quantity, leverage, take_profit_pct=take_profit_pct) + position_info = { + 'symbol': symbol, 'side': side, 'quantity': quantity, 'entryPrice': entry_price, + 'changePercent': 0, 'orderId': trade.get('entry_order_id'), 'tradeId': trade.get('id'), + 'stopLoss': stop_loss_price, 'takeProfit': take_profit_price, 'initialStopLoss': stop_loss_price, + 'leverage': leverage, 'entryReason': trade.get('entry_reason') or 'db_sync', 'atr': trade.get('atr'), + 'maxProfit': 0.0, 'trailingStopActivated': False, + } + self.active_positions[symbol] = position_info + logger.debug(f"{symbol} 已从 DB 载入到 active_positions,便于监控") + except Exception as e: + logger.debug(f"{symbol} 载入 active_positions 失败: {e}") + # 3. 找出在数据库中open但在币安已不存在的持仓 missing_in_binance = db_open_symbols - binance_symbols diff --git a/trading_system/strategy.py b/trading_system/strategy.py index bc2850d..d2fcbbc 100644 --- a/trading_system/strategy.py +++ b/trading_system/strategy.py @@ -59,8 +59,13 @@ class TradingStrategy: self.last_scan_trigger_ts = int(time.time()) # 初始化触发时间戳 logger.info("交易策略开始执行...") - # 启动所有现有持仓的WebSocket实时监控 + # 先同步持仓(补建「币安有、DB 无」的系统单),再启动监控,保证补建后的持仓会被监控 if not self._monitoring_started: + try: + await self.position_manager.sync_positions_with_binance() + logger.info("启动前持仓同步已完成,开始启动持仓监控...") + except Exception as e: + logger.warning(f"启动前持仓同步失败: {e},继续启动监控") try: await self.position_manager.start_all_position_monitoring() self._monitoring_started = True