diff --git a/user_data/strategies/grid_manager.py b/user_data/strategies/grid_manager.py index 2639ff5..2dd9be8 100644 --- a/user_data/strategies/grid_manager.py +++ b/user_data/strategies/grid_manager.py @@ -1354,3 +1354,177 @@ class GridManager: print(f"[GridManager] {self.pair} 计算盈亏失败: {str(e)}", file=sys.stderr, flush=True) return {} + + # ===== Pointer Index 操作接口 ===== + + def move_pointer_left(self) -> bool: + """ + 指针左移(价格下跌) + - 右侧的卖单被兑现,从 currentGridList 移除 + - 新的买单补充到左侧 + + Returns: + 是否移动成功 + """ + if self.pointer_index <= 0: + print(f"[GridManager] {self.pair} 指针已在最左侧,无法继续左移", + file=sys.stderr, flush=True) + return False + + try: + current_grids = self.get_current_grid_list() + + # 找到右侧的卖单(index = pointer_index 之后的第一个卖单) + sell_grid = None + for grid in reversed(current_grids): + if grid.direction == 'sell' and grid.grid_index >= self.pointer_index: + sell_grid = grid + break + + if sell_grid: + # 将卖单兑现,移到 historyGridList + if self.current_price and sell_grid.bid_price: + profit = (sell_grid.bid_price - sell_grid.entry_price) * sell_grid.quantity if sell_grid.entry_price else 0 + self.add_to_history_grid_list( + sell_grid, + filled_price=self.current_price, + filled_time=self.candle_index, + profit=profit + ) + + # 从 currentGridList 移除 + self.remove_from_current_grid_list(sell_grid.hash_id) + + # 左移指针 + self.pointer_index -= 1 + self.save_to_redis() + + print(f"[GridManager] {self.pair} 指针左移 {self.pointer_index + 1} -> {self.pointer_index}, " + f"卖单已兑现: {sell_grid.hash_id}", + file=sys.stderr, flush=True) + return True + + return False + + except Exception as e: + print(f"[GridManager] {self.pair} 指针左移失败: {str(e)}", + file=sys.stderr, flush=True) + return False + + def move_pointer_right(self) -> bool: + """ + 指针右移(价格上涨) + - 左侧的买单被兑现,从 currentGridList 移除 + - 新的卖单补充到右侧 + + Returns: + 是否移动成功 + """ + if self.pointer_index >= self.TOTAL_GRIDS - 1: + print(f"[GridManager] {self.pair} 指针已在最右侧,无法继续右移", + file=sys.stderr, flush=True) + return False + + try: + current_grids = self.get_current_grid_list() + + # 找到左侧的买单(index = pointer_index 之前的最后一个买单) + buy_grid = None + for grid in current_grids: + if grid.direction == 'buy' and grid.grid_index < self.pointer_index: + buy_grid = grid + + if buy_grid: + # 将买单兑现,移到 historyGridList + if self.current_price and buy_grid.entry_price: + profit = (self.current_price - buy_grid.entry_price) * buy_grid.quantity + self.add_to_history_grid_list( + buy_grid, + filled_price=self.current_price, + filled_time=self.candle_index, + profit=profit + ) + + # 从 currentGridList 移除 + self.remove_from_current_grid_list(buy_grid.hash_id) + + # 右移指针 + self.pointer_index += 1 + self.save_to_redis() + + print(f"[GridManager] {self.pair} 指针右移 {self.pointer_index - 1} -> {self.pointer_index}, " + f"买单已兑现: {buy_grid.hash_id}", + file=sys.stderr, flush=True) + return True + + return False + + except Exception as e: + print(f"[GridManager] {self.pair} 指针右移失败: {str(e)}", + file=sys.stderr, flush=True) + return False + + def update_pointer_by_price(self, new_price: float) -> int: + """ + 根据当前价格自动更新指针位置 + 计算当前价格应该对应的网格索引 + + Args: + new_price: 新的价格 + + Returns: + 指针移动的步数(负数表示左移,正数表示右移,0表示不动) + """ + try: + # 计算当前价格对应的网格索引 + if self.step <= 0: + return 0 + + price_offset = (new_price - self.lower_price) / self.step + new_pointer = int(price_offset) + + # 限制在有效范围内 + new_pointer = max(0, min(new_pointer, self.TOTAL_GRIDS - 1)) + + # 计算移动步数 + move_steps = new_pointer - self.pointer_index + + if move_steps < 0: + # 价格下跌,指针左移 + for _ in range(abs(move_steps)): + self.move_pointer_left() + elif move_steps > 0: + # 价格上涨,指针右移 + for _ in range(move_steps): + self.move_pointer_right() + + return move_steps + + except Exception as e: + print(f"[GridManager] {self.pair} 更新指针失败: {str(e)}", + file=sys.stderr, flush=True) + return 0 + + def get_pointer_info(self) -> Dict[str, Any]: + """ + 获取指针的详细信息 + + Returns: + 包含指针状态的字典 + """ + current_grids = self.get_current_grid_list() + history_grids = self.get_history_grid_list() + + buy_count = sum(1 for g in current_grids if g.direction == 'buy') + sell_count = sum(1 for g in current_grids if g.direction == 'sell') + + return { + 'pointer_index': self.pointer_index, + 'pointer_price': self.lower_price + self.pointer_index * self.step, + 'current_price': self.current_price, + 'current_grid_count': len(current_grids), + 'current_buy_count': buy_count, + 'current_sell_count': sell_count, + 'history_grid_count': len(history_grids), + 'total_pnl': self.calculate_pnl().get('total_pnl', 0), + }