From b466b803082c98efcd93b4198bce3abf22726cf4 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Thu, 27 Nov 2025 23:32:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=9B=88=E4=BA=8F=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E9=9D=A2=E6=9D=BF=20-=20=E6=AF=8F5=E5=88=86=E9=92=9F?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=B8=80=E6=AC=A1=E8=AF=A6=E7=BB=86=E7=9A=84?= =?UTF-8?q?=E7=9B=88=E4=BA=8F=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user_data/strategies/staticgrid.py | 38 ++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/user_data/strategies/staticgrid.py b/user_data/strategies/staticgrid.py index f2d0260..87399d0 100644 --- a/user_data/strategies/staticgrid.py +++ b/user_data/strategies/staticgrid.py @@ -132,8 +132,10 @@ class StaticGrid(IStrategy): # 更新网格管理器状态 grid_manager.update_state(current_price, candle_index) - # 定期报告 - grid_manager.check_and_report() + # ✅ 定期报告 - 每5分钟输出盈亏统计面板 + # 1小时K线下,5分钟 ≈ 5个蜡烛线(用300来近似) + if candle_index % 5 == 0: + self._print_pnl_panel(pair, grid_manager) return dataframe @@ -226,6 +228,38 @@ class StaticGrid(IStrategy): self.grid_managers[pair] = grid_manager self._pair_configs = getattr(self, '_pair_configs', {}) self._pair_configs[pair] = {'percent': percent} + + def _print_pnl_panel(self, pair: str, grid_manager: GridManager) -> None: + """ + 打印盈亏统计面板(每5分钟一次) + """ + # 计算盈亏指标 + filled_count = sum(1 for gs in grid_manager.grid_states.values() if gs.status == "filled") + empty_count = len(grid_manager.grid_states) - filled_count + + unrealized = (grid_manager.current_price - grid_manager.avg_entry_price) * grid_manager.total_quantity if grid_manager.total_quantity > 0 else 0 + unrealized_pct = (grid_manager.current_price - grid_manager.avg_entry_price) / grid_manager.avg_entry_price * 100 if grid_manager.avg_entry_price > 0 else 0 + + # 一旧扯住盈亏面板 + panel = f""" +┌{'='*100}┐ +│ [盈亏统计面板] {pair} | candle#{grid_manager.candle_index} | 价格: {grid_manager.current_price:.4f}│ +├{'='*100}┤ +│ 【持仓状态】 │ +│ • 数量: {grid_manager.total_quantity:.8f} | 分散世旧: {empty_count}/{len(grid_manager.grid_states)} | 成本: {grid_manager.total_invested:.2f} USDT │ +│ • 平均价: {grid_manager.avg_entry_price:.4f} USDT | 位置: {filled_count}/{len(grid_manager.grid_states)} FILLED │ +│ │ +│ 【盈亏情况】 │ +│ • 未实珰: {unrealized:+.2f} USDT ({unrealized_pct:+.2f}%) │ +│ • 最高价: {grid_manager.highest_price:.4f} USDT | 最低价: {grid_manager.lowest_price:.4f if grid_manager.lowest_price != float('inf') else 'N/A'}│ +│ • 状态: {'亏损💥' if unrealized < 0 else '盈利✅'} │ +│ │ +│ 【捷站显示】 │ +│ • gridMgr_id: {grid_manager.hash_id} | 创建时间: {grid_manager.created_time} │ +│ • 接次: {filled_count} | 下次需废数: {50 - filled_count} │ +└{'='*100}┘""" + + print(panel, file=sys.stderr, flush=True) def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """