Files
NewQuant/plans/strategy_manager_optimization_plan.md
liaozhaorun c0d996f39b feat(strategy_manager): 添加策略自动启动的白名单管理
实现全面的白名单管理系统,支持策略自动启动:

- 添加 WhitelistManager 类用于持久化白名单配置存储
- 将白名单功能集成到 StrategyManager 核心模块
- 添加用于白名单 CRUD 操作的 REST API 端点
- 通过 start.py 创建用于白名单管理的 CLI 命令
- 更新前端 UI,添加白名单状态指示器和批量操作功能
- 实现每日 08:58 的自动启动调度
- 为白名单操作添加配置验证和日志记录

同时添加项目文档:
- 代码格式规则(缩进、行长度、导入、命名)
- 文件、变量、常量、函数、类的命名规范
- 受限制文件和目录的保护规则
2026-01-26 01:21:46 +08:00

494 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 策略管理优化方案
## 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/` | 修改 | 前端界面添加白名单管理功能 |