fix: 限价单后撤单下市价单没有工作

This commit is contained in:
zhiyong 2025-05-14 11:00:41 +08:00
parent e79d622b2c
commit 9736919a49
3 changed files with 76 additions and 56 deletions

View File

@ -4,6 +4,8 @@ from abc import ABC, abstractmethod
from logger_config import get_logger from logger_config import get_logger
from position_manager import PositionManager from position_manager import PositionManager
from typing import Dict from typing import Dict
from config import Config
import os
# 获取日志记录器 # 获取日志记录器
@ -14,6 +16,7 @@ class BaseTrader(ABC):
"""初始化交易基类""" """初始化交易基类"""
self.position_managers: Dict[str, PositionManager] = {} self.position_managers: Dict[str, PositionManager] = {}
self.logger = logger self.logger = logger
self._load_all_position_managers_from_data_dir() # 新增:自动加载所有持仓管理器
pass pass
@abstractmethod @abstractmethod
@ -230,3 +233,18 @@ class BaseTrader(ABC):
self.position_managers[strategy_name].clear() self.position_managers[strategy_name].clear()
return True return True
return False return False
def _load_all_position_managers_from_data_dir(self):
"""从Config.DATA_DIR目录下的持仓文件自动加载所有PositionManager"""
data_dir = Config.DATA_DIR
if not os.path.exists(data_dir):
self.logger.info(f"持仓数据目录不存在: {data_dir}")
return
for fname in os.listdir(data_dir):
if fname.endswith('_positions.json'):
strategy_name = fname[:-len('_positions.json')]
try:
self.position_managers[strategy_name] = PositionManager(strategy_name)
self.logger.info(f"已自动加载策略持仓: {strategy_name}")
except Exception as e:
self.logger.error(f"加载策略持仓失败: {strategy_name}, 错误: {e}")

View File

@ -1,7 +1,6 @@
import time import time
import threading import threading
import schedule import schedule
import weakref
from xtquant import xtconstant from xtquant import xtconstant
from logger_config import get_logger from logger_config import get_logger
from config import Config from config import Config
@ -43,7 +42,7 @@ class RealTraderManager:
position_manager: StrategyPositionManager实例 position_manager: StrategyPositionManager实例
""" """
# 使用传入的trader实例使用弱引用避免循环引用 # 使用传入的trader实例使用弱引用避免循环引用
self.trader = weakref.proxy(trader) self.trader = trader
# 启动调度器 # 启动调度器
self._start_scheduler() self._start_scheduler()
@ -159,12 +158,7 @@ class RealTraderManager:
f"已提交订单: ID={order_id}, 策略={strategy_name}, 代码={code}, 方向={direction}, 数量={amount}, 价格={price}, 类型={order_type}" f"已提交订单: ID={order_id}, 策略={strategy_name}, 代码={code}, 方向={direction}, 数量={amount}, 价格={price}, 类型={order_type}"
) )
# 设置60秒后检查订单状态 threading.Timer(60, self.check_and_retry, args=(order_id, strategy_name)).start()
threading.Timer(
60,
self.check_and_retry,
args=(order_id, strategy_name)
).start()
return {"success": True, "order_id": order_id} return {"success": True, "order_id": order_id}
@ -205,56 +199,62 @@ class RealTraderManager:
order_id: 订单ID order_id: 订单ID
strategy_name: 策略名称 strategy_name: 策略名称
""" """
position_manager = self.trader.get_position_manager(strategy_name) try:
order_info = position_manager.get_pending_order(order_id) logger.info(f"开始检查订单状态: ID={order_id}, 策略={strategy_name}")
if not order_info: position_manager = self.trader.get_position_manager(strategy_name)
logger.warning(f"订单信息不存在, 可能全部完成或者撤单: ID={order_id}") order_info = position_manager.get_pending_order(order_id)
return if not order_info:
logger.warning(f"订单信息不存在, 可能全部完成或者撤单: ID={order_id}")
return
order_type = order_info.order_type order_type = order_info.order_type
# 使用trader的handle_order_update方法更新订单状态 # 使用trader的handle_order_update方法更新订单状态
status = self.trader.handle_order_update(order_id, strategy_name) status = self.trader.handle_order_update(order_id, strategy_name)
# 如果状态为None说明处理失败则直接返回 # 如果状态为None说明处理失败则直接返回
if status is None: if status is None:
logger.warning(f"订单状态更新失败: ID={order_id}") logger.warning(f"订单状态更新失败: ID={order_id}")
return return
# 重新获取订单信息,因为可能已经被更新 # 重新获取订单信息,因为可能已经被更新
order_info = position_manager.get_pending_order(order_id) order_info = position_manager.get_pending_order(order_id)
if not order_info: if not order_info:
logger.info(f"订单已完成: ID={order_id}") logger.info(f"订单已完成: ID={order_id}")
return return
if order_type == ORDER_TYPE_MARKET: if order_type == ORDER_TYPE_MARKET:
# 市价单,如果未完成则继续检查 # 市价单,如果未完成则继续检查
if status in [ORDER_STATUS_PENDING, ORDER_STATUS_PARTIAL]: if status in [ORDER_STATUS_PENDING, ORDER_STATUS_PARTIAL]:
logger.info(f"市价单未完成60秒后继续检查: ID={order_id}, 状态={status}") logger.info(f"市价单未完成60秒后继续检查: ID={order_id}, 状态={status}")
threading.Timer(60, self.check_and_retry, args=(order_id, strategy_name)).start() schedule.every(60).seconds.do(
run_threaded(self.check_and_retry), order_id, strategy_name
).tag(f"order_{order_id}")
else:
logger.info(f"市价单已完成: ID={order_id}, 状态={status}")
elif order_type == ORDER_TYPE_LIMIT:
filled = order_info.filled
target_amount = order_info.amount
left_amount = target_amount - filled
# 限价单这是60秒后的检查如果未完成则撤单补市价单
if status in [ORDER_STATUS_PENDING, ORDER_STATUS_PARTIAL]:
# 尝试撤单
try:
logger.info(f"限价单60秒后仍未完成尝试撤单: ID={order_id}, 状态={status}")
self.trader.cancel(order_id)
position_manager.update_order_status(order_id, filled, ORDER_STATUS_CANCELLED)
except Exception as e:
logger.error(f"撤单失败: order_id={order_id}, error={str(e)}")
# 计算剩余数量, 如果剩余数量大于0, 则补单
self._place_market_order_for_remainder(strategy_name, order_info.code, order_info.direction, left_amount)
else:
logger.info(f"限价单已完成: ID={order_id}, 状态={status}")
else: else:
logger.info(f"市价单已完成: ID={order_id}, 状态={status}") logger.warning(f"未知订单类型: ID={order_id}, type={order_type}")
elif order_type == ORDER_TYPE_LIMIT: except Exception as e:
filled = order_info.filled logger.error(f"检查订单状态时发生异常: ID={order_id}, error={str(e)}", exc_info=True)
target_amount = order_info.amount
left_amount = target_amount - filled
# 限价单这是60秒后的检查如果未完成则撤单补市价单
if status in [ORDER_STATUS_PENDING, ORDER_STATUS_PARTIAL]:
# 尝试撤单
try:
logger.info(f"限价单60秒后仍未完成尝试撤单: ID={order_id}, 状态={status}")
self.trader.cancel(order_id)
position_manager.update_order_status(order_id, filled, ORDER_STATUS_CANCELLED)
except Exception as e:
logger.error(f"撤单失败: order_id={order_id}, error={str(e)}")
# 计算剩余数量, 如果剩余数量大于0, 则补单
self._place_market_order_for_remainder(strategy_name, order_info.code, order_info.direction, left_amount)
else:
logger.info(f"限价单已完成: ID={order_id}, 状态={status}")
else:
logger.warning(f"未知订单类型: ID={order_id}, type={order_type}")

View File

@ -72,6 +72,8 @@ class MyXtQuantTraderCallback:
# 使用trader的方法来处理订单状态更新避免直接调用real_trader_manager # 使用trader的方法来处理订单状态更新避免直接调用real_trader_manager
self.trader_instance.handle_order_update(order_id, strategy_name) self.trader_instance.handle_order_update(order_id, strategy_name)
logger.info(f"成交回报触发订单状态更新: ID={order_id}, 策略={strategy_name}") logger.info(f"成交回报触发订单状态更新: ID={order_id}, 策略={strategy_name}")
else:
logger.warning(f"成交回报触发订单状态更新失败: 根据order id未找到策略名 ID={order_id}, 策略={strategy_name}")
except Exception as e: except Exception as e:
logger.error(f"成交回报处理异常: {str(e)}", exc_info=True) logger.error(f"成交回报处理异常: {str(e)}", exc_info=True)
def on_stock_position(self, position): def on_stock_position(self, position):