# 策略管理优化方案 ## 1. 需求概述 ### 1.1 问题背景 - 策略启动后如果出现异常会停止进程 - 需要机制确保重要策略能够自动重启 ### 1.2 优化目标 1. **白名单机制**: 本地文件保存希望自动启动的策略列表 2. **Web管理**: 界面可以管理白名单策略 3. **定时启动**: 每个工作日 8:58 自动尝试启动白名单中未运行的策略 4. **单日单次**: 每天只尝试一次,避免重复尝试 5. **手动控制**: 手动停止后不自动重启,需要用户重新操作 6. **双状态展示**: 每个策略显示"是否在白名单"和"是否运行中" --- ## 2. 系统架构 ### 2.1 新增/修改文件 | 文件 | 操作 | 说明 | |------|------|------| | `config/whitelist.json` | 新增 | 白名单配置文件 | | `core/whitelist_manager.py` | 新增 | 白名单管理器 | | `core/manager.py` | 修改 | 集成白名单功能 | | `web_backend.py` | 修改 | 新增白名单管理 API | | `frontend/` | 修改 | 前端界面添加白名单管理 | ### 2.2 核心数据结构 #### 白名单配置 (`config/whitelist.json`) ```json { "version": "1.0", "last_auto_start_date": "2024-01-25", "strategies": { "DualModeTrendlineHawkesStrategy2_FG": { "enabled": true, "added_at": "2024-01-25T10:00:00", "added_by": "web" }, "SpectralTrendStrategy_rb": { "enabled": true, "added_at": "2024-01-25T10:00:00", "added_by": "web" } } } ``` #### 策略状态结构扩展 ```python # 在 StrategyManager.strategies 字典中新增字段 { "strategy_key": { # ... 现有字段 ... "in_whitelist": True, # 是否在白名单中 "whitelist_enabled": True, # 白名单中是否启用 "last_auto_start_attempt": "2024-01-25T08:58:00", # 上次自动启动尝试 "auto_start_success": False # 上次自动启动是否成功 } } ``` --- ## 3. 详细设计 ### 3.1 白名单管理器 (`core/whitelist_manager.py`) ```python class WhitelistManager: """白名单管理器""" def __init__(self, config_path: str = "config/whitelist.json"): self.config_path = Path(config_path) self.data = self._load() def _load(self) -> Dict: """加载白名单配置""" if not self.config_path.exists(): return {"version": "1.0", "strategies": {}} with open(self.config_path, 'r') as f: return json.load(f) def _save(self): """保存白名单配置""" self.config_path.parent.mkdir(exist_ok=True) with open(self.config_path, 'w') as f: json.dump(self.data, f, indent=2, ensure_ascii=False) def add(self, strategy_key: str, enabled: bool = True) -> bool: """添加策略到白名单""" if strategy_key in self.data["strategies"]: return False # 已存在 self.data["strategies"][strategy_key] = { "enabled": enabled, "added_at": datetime.now().isoformat(), "added_by": "web" } self._save() return True def remove(self, strategy_key: str) -> bool: """从白名单移除策略""" if strategy_key not in self.data["strategies"]: return False del self.data["strategies"][strategy_key] self._save() return True def set_enabled(self, strategy_key: str, enabled: bool) -> bool: """设置策略在白名单中的启用状态""" if strategy_key not in self.data["strategies"]: return False self.data["strategies"][strategy_key]["enabled"] = enabled self._save() return True def get_all(self) -> Dict[str, Dict]: """获取所有白名单策略""" return self.data.get("strategies", {}) def is_in_whitelist(self, strategy_key: str) -> bool: """检查策略是否在白名单中""" return strategy_key in self.data.get("strategies", {}) def is_enabled_in_whitelist(self, strategy_key: str) -> bool: """检查策略是否在白名单中且已启用""" if strategy_key not in self.data.get("strategies", {}): return False return self.data["strategies"][strategy_key].get("enabled", False) def update_last_auto_start_date(self, date_str: str): """更新最后自动启动日期""" self.data["last_auto_start_date"] = date_str self._save() def should_auto_start_today(self) -> bool: """检查今天是否应该自动启动""" today = datetime.now().date().isoformat() return self.data.get("last_auto_start_date") != today ``` ### 3.2 修改 `core/manager.py` #### 新增功能 ```python class StrategyManager: def __init__(self, config_path: str = "config/main.json"): # ... 现有代码 ... self.whitelist_manager = WhitelistManager() def get_status(self) -> Dict[str, Any]: """获取完整状态(扩展白名单信息)""" status = super().get_status() # 添加白名单信息 for name, info in status["strategies"].items(): info["in_whitelist"] = self.whitelist_manager.is_in_whitelist(name) info["whitelist_enabled"] = self.whitelist_manager.is_enabled_in_whitelist(name) status["whitelist_auto_start_today"] = self.whitelist_manager.should_auto_start_today() return status def add_to_whitelist(self, name: str) -> bool: """添加策略到白名单""" return self.whitelist_manager.add(name, enabled=True) def remove_from_whitelist(self, name: str) -> bool: """从白名单移除策略""" return self.whitelist_manager.remove(name) def set_whitelist_enabled(self, name: str, enabled: bool) -> bool: """设置白名单中策略的启用状态""" return self.whitelist_manager.set_enabled(name, enabled) def start_strategy(self, name: str, auto_start: bool = False) -> bool: """ 启动策略 Args: name: 策略标识符 auto_start: 是否为自动启动(自动启动不会更新最后尝试日期) """ # ... 现有启动逻辑 ... # 如果是手动启动,清除自动启动相关的标记 if not auto_start: if name in self.strategies: self.strategies[name]["last_auto_start_attempt"] = None self.strategies[name]["auto_start_success"] = None return success def auto_start_whitelist_strategies(self) -> Dict[str, bool]: """ 自动启动白名单中所有未运行的策略 一天只执行一次 Returns: Dict[str, bool]: 每个策略的启动结果 """ if not self.whitelist_manager.should_auto_start_today(): return {} results = {} whitelist = self.whitelist_manager.get_all() for name, config in whitelist.items(): if not config.get("enabled", True): continue if name not in self.strategies: continue # 检查是否已在运行 if self._is_running(name): results[name] = True continue # 尝试启动 success = self.start_strategy(name, auto_start=True) results[name] = success # 更新策略状态 if name in self.strategies: self.strategies[name]["last_auto_start_attempt"] = datetime.now().isoformat() self.strategies[name]["auto_start_success"] = success # 更新日期 self.whitelist_manager.update_last_auto_start_date( datetime.now().date().isoformat() ) return results ``` ### 3.3 修改 `web_backend.py` #### 新增 API 端点 ```python # ============ 白名单管理 API ============ @app.get("/api/whitelist") def get_whitelist(): """获取白名单列表""" whitelist = manager.whitelist_manager.get_all() return { "whitelist": whitelist, "auto_start_today": manager.whitelist_manager.should_auto_start_today() } @app.post("/api/whitelist/{name}/add") def add_to_whitelist(name: str): """添加策略到白名单""" if manager.add_to_whitelist(name): return {"success": True} raise HTTPException(400, "添加失败,策略可能已存在") @app.post("/api/whitelist/{name}/remove") def remove_from_whitelist(name: str): """从白名单移除策略""" if manager.remove_from_whitelist(name): return {"success": True} raise HTTPException(400, "移除失败,策略可能不在白名单中") @app.post("/api/whitelist/{name}/enable") def enable_in_whitelist(name: str): """启用白名单中的策略""" if manager.set_whitelist_enabled(name, True): return {"success": True} raise HTTPException(400, "操作失败") @app.post("/api/whitelist/{name}/disable") def disable_in_whitelist(name: str): """禁用白名单中的策略""" if manager.set_whitelist_enabled(name, False): return {"success": True} raise HTTPException(400, "操作失败") @app.post("/api/whitelist/auto-start") def trigger_auto_start(): """手动触发白名单自动启动(用于测试)""" results = manager.auto_start_whitelist_strategies() return { "success": True, "results": results, "count": len(results) } # ============ 修改现有的状态 API ============ @app.get("/api/status") def get_status(): """获取策略状态(包含白名单信息)""" status_data = manager.get_status() status_data['git_info'] = get_git_commit_info() return status_data ``` #### 修改定时任务 ```python @app.on_event("startup") async def start_scheduler(): # ... 现有的 08:58, 20:58 重启任务 ... # 新增:白名单自动启动任务(仅 08:58) scheduler.add_job( auto_start_whitelist_task, CronTrigger(hour=8, minute=58), id="whitelist_auto_start", replace_existing=True ) logger.info("📅 白名单自动启动任务已添加 (计划时间: 08:58)") def auto_start_whitelist_task(): """ 白名单自动启动任务 """ logger.info("⏰ [白名单任务] 触发自动启动...") results = manager.auto_start_whitelist_strategies() if not results: logger.info("⏰ [白名单任务] 今天已执行过或无需启动") return success_count = sum(1 for v in results.values() if v) fail_count = len(results) - success_count logger.info(f"⏰ [白名单任务] 完成: 成功 {success_count}, 失败 {fail_count}") for name, success in results.items(): if success: logger.info(f"✅ [白名单任务] {name} 启动成功") else: logger.warning(f"❌ [白名单任务] {name} 启动失败") ``` ### 3.4 修改 `start.py` #### 新增 CLI 命令 ```python def main(): # ... 现有的参数解析 ... parser.add_argument("--whitelist", action="store_true", help="白名单操作模式") # 白名单子命令 whitelist_parser = subparsers.add_parser("whitelist", help="白名单管理") whitelist_parser.add_argument("action", choices=["add", "remove", "list", "enable", "disable"]) whitelist_parser.add_argument("-n", "--name", help="策略标识符") ``` ### 3.5 前端界面修改 #### 状态表格新增列 | 列名 | 说明 | 示例值 | |------|------|--------| | 白名单 | 是否在白名单中 | ✅ / ❌ | | 白名单状态 | 白名单中是否启用 | 启用 / 禁用 | | 自动启动 | 今天是否已尝试自动启动 | 是 / 否 | | 自动启动结果 | 上次自动启动是否成功 | 成功 / 失败 / - | #### 新增管理操作 1. **添加到白名单**: 勾选策略后点击"添加到白名单" 2. **从白名单移除**: 勾选策略后点击"从白名单移除" 3. **启用/禁用**: 在白名单中启用或禁用某个策略 4. **手动触发**: 按钮"立即执行白名单启动" --- ## 4. 工作流程 ### 4.1 自动启动流程 ```mermaid sequenceDiagram participant T as 定时任务 (08:58) participant W as Web Backend participant M as StrategyManager participant WM as WhitelistManager participant S as Strategy Process T->>W: 触发定时任务 W->>M: auto_start_whitelist_strategies() M->>WM: should_auto_start_today()? alt 今天未执行过 WM-->>M: True M->>WM: get_all() 获取白名单 loop 遍历白名单策略 M->>M: 检查策略是否运行 alt 未运行 M->>S: 启动策略进程 (auto_start=True) M->>M: 记录启动结果 else 已在运行 M->>M: 标记为成功 end end M->>WM: update_last_auto_start_date(今天) M-->>W: 返回启动结果 W->>T: 记录日志 else 今天已执行过 WM-->>M: False M-->>W: 返回空结果 W->>T: 跳过(今天已执行) end ``` ### 4.2 手动管理流程 ```mermaid sequenceDiagram participant U as 用户 participant W as Web界面 participant API as Web Backend API participant M as StrategyManager participant WM as WhitelistManager participant F as 白名单配置文件 U->>W: 点击"添加到白名单" W->>API: POST /api/whitelist/{name}/add API->>M: add_to_whitelist(name) M->>WM: add(name) WM->>F: 写入配置 F-->>WM: 保存成功 WM-->>M: True M-->>API: True API-->>W: {"success": True} W->>U: 显示成功提示 W->>API: GET /api/status API->>M: get_status() M->>WM: 获取白名单状态 M-->>API: 状态数据 API-->>W: 状态数据 W->>U: 更新表格(显示白名单状态) ``` --- ## 5. 兼容性设计 ### 5.1 向后兼容 - 现有 `start.py status` 命令保持不变 - 现有 API `/api/status` 保持兼容(新增字段不影响现有功能) - 现有日志查看功能保持不变 ### 5.2 数据迁移 - 首次启动时自动创建 `config/whitelist.json` - 无需手动迁移现有配置 --- ## 6. 实施计划 ### 阶段一:后端实现 1. 创建 `config/whitelist.json` 模板 2. 实现 `core/whitelist_manager.py` 3. 修改 `core/manager.py` 集成白名单功能 4. 修改 `web_backend.py` 添加 API 5. 修改 `start.py` 添加 CLI 命令 ### 阶段二:前端实现 1. 修改状态表格,添加白名单列 2. 添加白名单管理操作按钮 3. 添加手动触发按钮 4. 美化界面交互 ### 阶段三:测试 1. 测试白名单添加/移除 2. 测试自动启动功能 3. 测试手动停止不自动重启 4. 测试一天只启动一次 5. 测试重启后状态恢复 --- ## 7. 文件修改清单 | 文件路径 | 操作 | 说明 | |----------|------|------| | `config/whitelist.json` | 新增 | 白名单配置文件 | | `core/whitelist_manager.py` | 新增 | 白名单管理器类 | | `core/manager.py` | 修改 | 集成白名单功能,扩展状态结构 | | `web_backend.py` | 修改 | 添加白名单管理 API,修改定时任务 | | `start.py` | 修改 | 添加白名单 CLI 命令 | | `frontend/` | 修改 | 前端界面添加白名单管理功能 |