实现全面的白名单管理系统,支持策略自动启动: - 添加 WhitelistManager 类用于持久化白名单配置存储 - 将白名单功能集成到 StrategyManager 核心模块 - 添加用于白名单 CRUD 操作的 REST API 端点 - 通过 start.py 创建用于白名单管理的 CLI 命令 - 更新前端 UI,添加白名单状态指示器和批量操作功能 - 实现每日 08:58 的自动启动调度 - 为白名单操作添加配置验证和日志记录 同时添加项目文档: - 代码格式规则(缩进、行长度、导入、命名) - 文件、变量、常量、函数、类的命名规范 - 受限制文件和目录的保护规则
15 KiB
15 KiB
策略管理优化方案
1. 需求概述
1.1 问题背景
- 策略启动后如果出现异常会停止进程
- 需要机制确保重要策略能够自动重启
1.2 优化目标
- 白名单机制: 本地文件保存希望自动启动的策略列表
- Web管理: 界面可以管理白名单策略
- 定时启动: 每个工作日 8:58 自动尝试启动白名单中未运行的策略
- 单日单次: 每天只尝试一次,避免重复尝试
- 手动控制: 手动停止后不自动重启,需要用户重新操作
- 双状态展示: 每个策略显示"是否在白名单"和"是否运行中"
2. 系统架构
2.1 新增/修改文件
| 文件 | 操作 | 说明 |
|---|---|---|
config/whitelist.json |
新增 | 白名单配置文件 |
core/whitelist_manager.py |
新增 | 白名单管理器 |
core/manager.py |
修改 | 集成白名单功能 |
web_backend.py |
修改 | 新增白名单管理 API |
frontend/ |
修改 | 前端界面添加白名单管理 |
2.2 核心数据结构
白名单配置 (config/whitelist.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"
}
}
}
策略状态结构扩展
# 在 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)
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
新增功能
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 端点
# ============ 白名单管理 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
修改定时任务
@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 命令
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 前端界面修改
状态表格新增列
| 列名 | 说明 | 示例值 |
|---|---|---|
| 白名单 | 是否在白名单中 | ✅ / ❌ |
| 白名单状态 | 白名单中是否启用 | 启用 / 禁用 |
| 自动启动 | 今天是否已尝试自动启动 | 是 / 否 |
| 自动启动结果 | 上次自动启动是否成功 | 成功 / 失败 / - |
新增管理操作
- 添加到白名单: 勾选策略后点击"添加到白名单"
- 从白名单移除: 勾选策略后点击"从白名单移除"
- 启用/禁用: 在白名单中启用或禁用某个策略
- 手动触发: 按钮"立即执行白名单启动"
4. 工作流程
4.1 自动启动流程
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 手动管理流程
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. 实施计划
阶段一:后端实现
- 创建
config/whitelist.json模板 - 实现
core/whitelist_manager.py - 修改
core/manager.py集成白名单功能 - 修改
web_backend.py添加 API - 修改
start.py添加 CLI 命令
阶段二:前端实现
- 修改状态表格,添加白名单列
- 添加白名单管理操作按钮
- 添加手动触发按钮
- 美化界面交互
阶段三:测试
- 测试白名单添加/移除
- 测试自动启动功能
- 测试手动停止不自动重启
- 测试一天只启动一次
- 测试重启后状态恢复
7. 文件修改清单
| 文件路径 | 操作 | 说明 |
|---|---|---|
config/whitelist.json |
新增 | 白名单配置文件 |
core/whitelist_manager.py |
新增 | 白名单管理器类 |
core/manager.py |
修改 | 集成白名单功能,扩展状态结构 |
web_backend.py |
修改 | 添加白名单管理 API,修改定时任务 |
start.py |
修改 | 添加白名单 CLI 命令 |
frontend/ |
修改 | 前端界面添加白名单管理功能 |