diff --git a/user_data/strategies/grid_manager.py b/user_data/strategies/grid_manager.py index 93008ac..6999118 100644 --- a/user_data/strategies/grid_manager.py +++ b/user_data/strategies/grid_manager.py @@ -385,8 +385,8 @@ class GridManager: # 记录到历史 self.position_history.append(adjustment) - # ✅ 立即同步上次改变上 Redis - self.sync_grid_state_to_redis() + # ✅ 立即同步元数据到 Redis + self.save_to_redis() print(f"[GridManager] {self.pair} 网格状态已同步到 Redis", file=sys.stderr, flush=True) @@ -982,3 +982,155 @@ class GridManager: print(f"[GridManager] {self.pair} 网格管理器已销毁,可以释放该对象", file=sys.stderr, flush=True) + + def serialize_to_dict(self) -> Dict[str, Any]: + """ + 将 GridManager 的元数据序列化为字典 + 用于存储到 Redis + + Returns: + 包含所有元数据的字典 + """ + return { + 'pair': self.pair, + 'hash_id': self.hash_id, + 'created_time': self.created_time, + 'lower_price': self.lower_price, + 'upper_price': self.upper_price, + 'step': self.step, + 'stake_per_grid': self.stake_per_grid, + 'pointer_index': self.pointer_index, + 'total_grid_levels': self.total_grid_levels, + 'is_completed': self.is_completed, + 'completion_reason': self.completion_reason, + 'current_price': self.current_price, + 'total_quantity': self.total_quantity, + 'total_invested': self.total_invested, + 'avg_entry_price': self.avg_entry_price, + 'highest_price': self.highest_price, + 'lowest_price': self.lowest_price if self.lowest_price != float('inf') else -1, + 'candle_index': self.candle_index, + 'current_grid_list_key': self.current_grid_list_key, + 'history_grid_list_key': self.history_grid_list_key, + } + + @staticmethod + def deserialize_from_dict(data: Dict[str, Any]) -> 'GridManager': + """ + 从字典恢复 GridManager 对象 + + Args: + data: 包含元数据的字典 + + Returns: + 恢复后的 GridManager 对象 + """ + # 创建新的 GridManager + gm = GridManager( + pair=data['pair'], + lower_price=data['lower_price'], + upper_price=data['upper_price'], + step=data['step'], + stake_per_grid=data['stake_per_grid'] + ) + + # 恢复元数据 + gm.hash_id = data['hash_id'] + gm.created_time = data['created_time'] + gm.pointer_index = data['pointer_index'] + gm.is_completed = data['is_completed'] + gm.completion_reason = data['completion_reason'] + gm.current_price = data['current_price'] + gm.total_quantity = data['total_quantity'] + gm.total_invested = data['total_invested'] + gm.avg_entry_price = data['avg_entry_price'] + gm.highest_price = data['highest_price'] + lowest = data['lowest_price'] + gm.lowest_price = float('inf') if lowest == -1 else lowest + gm.candle_index = data['candle_index'] + gm.current_grid_list_key = data['current_grid_list_key'] + gm.history_grid_list_key = data['history_grid_list_key'] + gm.total_grid_levels = data['total_grid_levels'] + + print(f"[GridManager] {data['pair']} 从字典恢复成功 - hash_id: {gm.hash_id}", + file=sys.stderr, flush=True) + return gm + + def save_to_redis(self) -> bool: + """ + 将 GridManager 的元数据保存到 Redis + + Returns: + 是否保存成功 + """ + if not self.redis_client: + print(f"[GridManager] {self.pair} Redis 客户端未初始化", + file=sys.stderr, flush=True) + return False + + try: + data = self.serialize_to_dict() + self.redis_client.set( + self.gridmanager_key, + json.dumps(data) + ) + print(f"[GridManager] {self.pair} 元数据已保存到 Redis - key: {self.gridmanager_key}", + file=sys.stderr, flush=True) + return True + except Exception as e: + print(f"[GridManager] {self.pair} 保存到 Redis 失败: {str(e)}", + file=sys.stderr, flush=True) + return False + + @staticmethod + def load_from_redis(pair: str, redis_url: str, hash_id: str = None) -> Optional['GridManager']: + """ + 从 Redis 加载 GridManager + 如果 hash_id 为空,则加载最新的(按时间戳) + + Args: + pair: 币对 + redis_url: Redis 连接URL + hash_id: 可选,指定特定的 GridManager + + Returns: + 恢复的 GridManager 或 None + """ + try: + parsed_url = urlparse(redis_url) + redis_client = redis.Redis( + host=parsed_url.hostname or 'localhost', + port=parsed_url.port or 6379, + db=int(parsed_url.path.strip('/') or 0), + decode_responses=True + ) + + if hash_id: + # 加载指定的 GridManager + # 需要遍历查找(因为 key 包含 timestamp) + # 这里简化为直接用 hash_id 查找最新的 + pattern = f"gm:{pair}:*:{hash_id}" + keys = redis_client.keys(pattern) + if keys: + data = redis_client.get(keys[0]) + if data: + return GridManager.deserialize_from_dict(json.loads(data)) + else: + # 加载最新的 GridManager(按 key 中的时间戳排序) + pattern = f"gm:{pair}:*" + keys = redis_client.keys(pattern) + if keys: + # 按时间戳排序,取最新的 + keys_sorted = sorted(keys, reverse=True) + data = redis_client.get(keys_sorted[0]) + if data: + return GridManager.deserialize_from_dict(json.loads(data)) + + print(f"[GridManager] {pair} Redis 中未找到 GridManager", + file=sys.stderr, flush=True) + return None + + except Exception as e: + print(f"[GridManager] {pair} 从 Redis 加载失败: {str(e)}", + file=sys.stderr, flush=True) + return None