From ab6de20a9196dab8a8373197b3b5cbb5f4bfb92e Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Thu, 27 Nov 2025 23:14:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9BGridManager=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=EF=BC=9A=E5=BC=95=E5=85=A5pointer=5Findex?= =?UTF-8?q?=E3=80=81=E5=88=9B=E5=BB=BA=E6=97=B6=E9=97=B4=E3=80=81hash=5Fid?= =?UTF-8?q?=EF=BC=8C=E4=B8=BA=E6=96=B0=E7=9A=84Grid/currentGridList/histor?= =?UTF-8?q?yGridList=E6=9E=B6=E6=9E=84=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user_data/strategies/grid_manager.py | 70 ++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/user_data/strategies/grid_manager.py b/user_data/strategies/grid_manager.py index b2a88a6..93008ac 100644 --- a/user_data/strategies/grid_manager.py +++ b/user_data/strategies/grid_manager.py @@ -24,6 +24,32 @@ class AdjustmentType(Enum): EXIT = "exit" # 全部平仓 +@dataclass +class Grid: + """ + 单个网格对象 - 代表网格中的一个位置 + + 可以是已成交的买单或未成交的卖单 + """ + hash_id: str # 随机唯一标识 + grid_index: int # 网格位置索引 (0-49) + direction: str # "buy" 或 "sell" + + # 对于已成交买单 + entry_price: Optional[float] = None # 被填充时的入场价格 + entry_time: Optional[int] = None # 被填充的时间(蜡烛线索引) + quantity: float = 0.0 # 持仓数量 + + # 对于未成交卖单 + bid_price: Optional[float] = None # 挂单价格 + bid_time: Optional[int] = None # 挂单时间 + + # 兑现信息 + filled_price: Optional[float] = None # 兑现价格 + filled_time: Optional[int] = None # 兑现时间 + profit: Optional[float] = None # 单个网格的盈亏 + + @dataclass class GridLevel: """单个网格点的状态""" @@ -122,18 +148,25 @@ class GridMonitor: class GridManager: """ - 网格交易管理器 - 核心思想:维护网格的填充/排空状态 + 网格交易管理器 - 维护完整的持仓生命周期 - 网格逻辑: - - 下沿到当前价格 → 所有网格必须被填满(已买入持仓) - - 当前价格到上沿 → 所有网格必须被排空(不持有 或 已卖出) + 架构: + - currentGridList: 长度固定=50的网格集合(已成交买单+未成交卖单) + - historyGridList: 所有已兑现的Grid信息(长度只增不减) + - pointer_index: 浮标指针(虚拟),分界线位置 - 决策规则: - 1. 如果下方有空白网格 → 加仓(填满它们) - 2. 如果上方有持仓网格 → 平仓(排空它们) - 3. 维护一个网格状态数组,每个位置记录 "filled" 或 "empty" + 规则: + - 价格下跌 → pointer_index左移 → 右侧卖单被兑现 + - 价格上涨 → pointer_index右移 → 左侧买单被兑现 + - 兑现后的Grid自动从currentGridList移除,新Grid补充 """ + # 常量定义:所有都可以修改 + TOTAL_GRIDS = 50 # 总网格数 + FILL_RATIO = 0.5 # 初始填充比例 + PRICE_AMPLITUDE_BTC = 0.20 # BTC波幅 20% + PRICE_AMPLITUDE_DEFAULT = 0.33 # 其他币种波幅 33% + def __init__(self, pair: str, lower_price: float, @@ -156,7 +189,23 @@ class GridManager: self.step = step self.stake_per_grid = stake_per_grid - # 计算总网格数 + # 创建时间和随机hash_id + self.created_time = int(datetime.now().timestamp()) + import uuid + self.hash_id = str(uuid.uuid4())[:8] # 8位随机值 + + # ✅ 新架构:浮标指针 + self.pointer_index = int(self.TOTAL_GRIDS * self.FILL_RATIO) # 初始位置 = 25 + + # currentGridList 和 historyGridList 将由 Redis 存储 + # 这里只保存引用key + self.current_grid_list_key = f"grids:current:{pair}:{self.hash_id}" + self.history_grid_list_key = f"grids:history:{pair}:{self.hash_id}" + + # GridManager 本身的 key(存储元数据) + self.gridmanager_key = f"gm:{pair}:{self.created_time}:{self.hash_id}" + + # ... existing code ... self.total_grid_levels = int((upper_price - lower_price) / step) + 1 # 生成所有网格点价格 @@ -213,6 +262,9 @@ class GridManager: self.completion_reason: Optional[str] = None # 完结原因 (take_profit / stop_loss) self.min_grids_for_exit = 5 # 至少加仓到5个网格才能触发止盈/止损 + # ✅ GridManager 不变量:沉求下来就不改了(除非网格范围更新) + # 便于 Redis 序列化保存 + def update_state(self, current_price: float, candle_index: int) -> None: """ 更新网格对象的当前状态