diff --git a/src/config.py b/src/config.py index 058cac8..55e261c 100644 --- a/src/config.py +++ b/src/config.py @@ -58,5 +58,5 @@ class Config: RTM_USE_MARKET_ORDER = True # 是否使用市价单进行补单 # 计划任务运行时间 - STRATEGY_SAVE_TIME = "15:10" # 每天保存策略数据的时间 CLEAN_ORDERS_TIME = "15:05" # 每天清理超时委托的时间 + STRATEGY_SAVE_TIME = "15:08" # 每天保存策略数据的时间 diff --git a/src/local_order.py b/src/local_order.py index 508dbd2..4f2f804 100644 --- a/src/local_order.py +++ b/src/local_order.py @@ -2,15 +2,15 @@ from trade_constants import ORDER_STATUS_PENDING from datetime import datetime class LocalOrder: - def __init__(self, order_id, code, price, amount, direction, order_type='limit'): - self.order_id = order_id - self.code = code - self.price = price - self.amount = amount - self.filled = 0 - self.direction = direction - self.order_type = order_type - self.status = ORDER_STATUS_PENDING - self.created_time = datetime.now() + def __init__(self, order_id, code, price, amount, direction, order_type='limit', filled=0, status=ORDER_STATUS_PENDING, created_time=datetime.now()): + self.order_id: str = order_id + self.code: str = code + self.price: float = price + self.amount: int = amount + self.filled: int = filled + self.direction: str = direction + self.order_type: str = order_type + self.status: str = status + self.created_time: datetime = created_time diff --git a/src/local_position.py b/src/local_position.py index eea27e0..f90958d 100644 --- a/src/local_position.py +++ b/src/local_position.py @@ -1,5 +1,5 @@ class LocalPosition: def __init__(self, code, total_amount, closeable_amount): - self.code = code - self.total_amount = total_amount - self.closeable_amount = closeable_amount + self.code: str = code + self.total_amount: int = total_amount + self.closeable_amount: int = closeable_amount diff --git a/src/position_manager.py b/src/position_manager.py index 9198b80..50b139d 100644 --- a/src/position_manager.py +++ b/src/position_manager.py @@ -30,6 +30,9 @@ class PositionManager: self.positions: Dict[str, LocalPosition] = {} # {股票代码 -> LocalPosition} # 待处理订单信息 self.pending_orders = {} # {order_id -> LocalOrder} + # 所有订单 + self.all_orders = [] # [LocalOrder] + self.data_path = os.path.join(Config.DATA_DIR, self.strategy_name + "_positions.json") # 确保数据目录存在 os.makedirs(os.path.dirname(self.data_path), exist_ok=True) @@ -37,7 +40,8 @@ class PositionManager: if not os.path.exists(self.data_path): with open(self.data_path, 'w') as f: f.write('{}') - self.load_data() + else: + self.load_data() def update_position(self, code, direction, amount): # 如果股票代码在持仓字典中不存在,初始化它 @@ -74,6 +78,8 @@ class PositionManager: order = LocalOrder(order_id, code, price, amount, direction, order_type) self.pending_orders[order_id] = order + if (order_type == ORDER_TYPE_LIMIT): + self.all_orders.append(order) logger.info( f"添加订单 - ID: {order_id}, 策略: {self.strategy_name}, 代码: {code}, 方向: {direction}, " @@ -168,11 +174,28 @@ class PositionManager: ), } + all_orders_array = [] + for order in self.all_orders: + all_orders_array.append({ + "order_id": order.order_id, + "code": order.code, + "price": order.price, + "amount": order.amount, + "direction": order.direction, + "order_type": order.order_type, + "created_time": ( + order.created_time.isoformat() + if hasattr(order, "created_time") + else None + ), + }) + with open(self.data_path, "w") as f: json.dump( { "positions": positions_dict, "pending_orders": pending_orders_dict, + "all_orders": all_orders_array, }, f, ) @@ -195,8 +218,8 @@ class PositionManager: for code, pos_data in positions_dict.items(): self.positions[code] = LocalPosition( pos_data["code"], - pos_data["total_amount"], - pos_data["closeable_amount"], + int(pos_data["total_amount"]), + int(pos_data["closeable_amount"]), ) # 还原pending_orders对象 @@ -206,13 +229,13 @@ class PositionManager: order = LocalOrder( order_data["order_id"], order_data["code"], - order_data["price"], - order_data["amount"], + float(order_data["price"]), + int(order_data["amount"]), order_data["direction"], order_data["order_type"], + int(order_data["filled"]), + order_data["status"], ) - order.filled = order_data["filled"] - order.status = order_data["status"] if order_data.get("created_time"): try: order.created_time = datetime.fromisoformat( @@ -223,22 +246,42 @@ class PositionManager: self.pending_orders[order_id] = order + # 还原all_orders对象 + self.all_orders = [] + all_orders_array = data.get("all_orders", []) + for order_data in all_orders_array: + order = LocalOrder( + order_data["order_id"], + order_data["code"], + float(order_data["price"]), + int(order_data["amount"]), + order_data["direction"], + order_data["order_type"], + created_time=datetime.fromisoformat( + order_data["created_time"] + ) if order_data.get("created_time") else datetime.now() + ) + self.all_orders.append(order) + logger.info("已加载实盘策略数据") logger.info(f"策略数: {len(self.positions)}") else: logger.info(f"实盘策略数据文件不存在: {self.data_path}") self.positions = {} self.pending_orders = {} + self.all_orders = [] except Exception as e: logger.error(f"加载实盘策略数据失败: {str(e)}") # 初始化空数据结构 self.positions = {} self.pending_orders = {} + self.all_orders = [] def clear(self): """清除所有持仓管理数据""" self.positions = {} self.pending_orders = {} + self.all_orders = [] self.save_data() def update_closeable_amount(self): @@ -250,4 +293,7 @@ class PositionManager: def clear_pending_orders(self): """清除所有未完成订单""" self.pending_orders = {} - self.save_data() + + def get_all_orders(self): + """获取所有订单""" + return self.all_orders diff --git a/src/real/real_trader_manager.py b/src/real/real_trader_manager.py index 8a7b6ab..dedab7c 100644 --- a/src/real/real_trader_manager.py +++ b/src/real/real_trader_manager.py @@ -52,16 +52,28 @@ class RealTraderManager: def _start_scheduler(self): # 每日定时清理(增加配置校验) - if hasattr(Config, "STRATEGY_SAVE_TIME"): + if hasattr(Config, "CLEAN_ORDERS_TIME"): try: - schedule.every().day.at(Config.STRATEGY_SAVE_TIME).do( + schedule.every().day.at(Config.CLEAN_ORDERS_TIME).do( run_threaded(self.clean_expired_orders) ) - schedule.every().day.at(Config.STRATEGY_SAVE_TIME).do( + schedule.every().day.at(Config.CLEAN_ORDERS_TIME).do( run_threaded(self.update_closeable_amount) ) except Exception as e: logger.error(f"清理任务配置错误: {e}") + else: + logger.error("CLEAN_ORDERS_TIME 未配置") + + # 每日定时保存策略数据(增加配置校验) + if hasattr(Config, "STRATEGY_SAVE_TIME"): + try: + schedule.every().day.at(Config.STRATEGY_SAVE_TIME).do( + run_threaded(self.save_strategy_data) + ) + + except Exception as e: + logger.error(f"保存策略数据任务配置错误: {e}") else: logger.error("STRATEGY_SAVE_TIME 未配置") @@ -350,3 +362,21 @@ class RealTraderManager: except Exception as e: logger.error(f"更新可卖持仓时发生异常: {str(e)}") + + def save_strategy_data(self): + """保存策略数据""" + try: + logger.info("开始保存策略数据...") + + # 获取所有持仓管理器 + position_managers = self.trader.get_all_position_managers() + + # 遍历所有持仓管理器,保存策略数据 + for position_manager in position_managers.values(): + position_manager.save_data() + + logger.info("策略数据保存完毕") + except Exception as e: + logger.error(f"保存策略数据时发生异常: {str(e)}") + + diff --git a/src/simulation/simulation_trader.py b/src/simulation/simulation_trader.py index 5e0cfce..4d8a41f 100644 --- a/src/simulation/simulation_trader.py +++ b/src/simulation/simulation_trader.py @@ -67,6 +67,9 @@ class SimulationTrader(BaseTrader): # 更新总资产 self._update_total_assets() + # 保存策略数据 + position_manager.save_data() + return {"order_id": order_id, "message": message, "success": True} def sell(self, code, price, amount, strategy_name="default_strategy"): @@ -104,6 +107,9 @@ class SimulationTrader(BaseTrader): # 更新总资产 self._update_total_assets() + # 保存策略数据 + position_manager.save_data() + return {"order_id": order_id, "message": message, "success": True} def _update_total_assets(self):