From c0d996f39b7b37af102cea7d380d7826e5d98472 Mon Sep 17 00:00:00 2001 From: liaozhaorun <1300336796@qq.com> Date: Mon, 26 Jan 2026 01:21:46 +0800 Subject: [PATCH] =?UTF-8?q?feat(strategy=5Fmanager):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E8=87=AA=E5=8A=A8=E5=90=AF=E5=8A=A8=E7=9A=84?= =?UTF-8?q?=E7=99=BD=E5=90=8D=E5=8D=95=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现全面的白名单管理系统,支持策略自动启动: - 添加 WhitelistManager 类用于持久化白名单配置存储 - 将白名单功能集成到 StrategyManager 核心模块 - 添加用于白名单 CRUD 操作的 REST API 端点 - 通过 start.py 创建用于白名单管理的 CLI 命令 - 更新前端 UI,添加白名单状态指示器和批量操作功能 - 实现每日 08:58 的自动启动调度 - 为白名单操作添加配置验证和日志记录 同时添加项目文档: - 代码格式规则(缩进、行长度、导入、命名) - 文件、变量、常量、函数、类的命名规范 - 受限制文件和目录的保护规则 --- .kilocode/rules/formatting.md | 96 ++++ .kilocode/rules/naming_conventions.md | 129 +++++ .kilocode/rules/restricted_files.md | 126 +++++ ma_channel_event_probability.png | Bin 193270 -> 0 bytes plans/strategy_manager_optimization_plan.md | 493 ++++++++++++++++++++ strategy_manager/config/whitelist.json | 5 + strategy_manager/core/manager.py | 140 +++++- strategy_manager/core/whitelist_manager.py | 345 ++++++++++++++ strategy_manager/frontend/dist/index.html | 472 +++++++++++++++---- strategy_manager/start.py | 122 ++++- strategy_manager/web_backend.py | 123 ++++- 11 files changed, 1952 insertions(+), 99 deletions(-) create mode 100644 .kilocode/rules/formatting.md create mode 100644 .kilocode/rules/naming_conventions.md create mode 100644 .kilocode/rules/restricted_files.md delete mode 100644 ma_channel_event_probability.png create mode 100644 plans/strategy_manager_optimization_plan.md create mode 100644 strategy_manager/config/whitelist.json create mode 100644 strategy_manager/core/whitelist_manager.py diff --git a/.kilocode/rules/formatting.md b/.kilocode/rules/formatting.md new file mode 100644 index 0000000..93a66f8 --- /dev/null +++ b/.kilocode/rules/formatting.md @@ -0,0 +1,96 @@ +# 代码格式规则 (Formatting Rules) + +本项目遵循以下代码格式规范: + +## 1. Python 代码规范 + +### 1.1 缩进 +- 使用 **4个空格** 进行缩进 +- 不使用 Tab 键 + +### 1.2 行长度 +- 每行代码最大长度:**100 字符** +- 文档字符串最大长度:**80 字符** + +### 1.3 空行 +- 类定义之间:**2个空行** +- 方法定义之间:**1个空行** +- 函数定义之间:**2个空行** +- 逻辑段落之间:**1个空行** + +### 1.4 导入顺序 +```python +# 标准库导入 +import os +import sys +from datetime import datetime + +# 第三方库导入 +import numpy as np +import pandas as pd + +# 本地项目导入 +from src.backtest_engine import BacktestEngine +from src.data_manager import DataManager +``` + +### 1.5 空格使用 +- 在逗号后添加空格:`func(a, b, c)` +- 在运算符两侧添加空格:`a + b` +- 不要在括号内添加空格:`func(a)` 而不是 `func( a )` +- 函数参数列表内不要有多余空格 + +## 2. 命名规范 + +### 2.1 变量命名 +- 使用 **小写字母 + 下划线**:`trade_volume`, `stop_loss_points` +- 私有变量使用前缀下划线:`_internal_cache` + +### 2.2 常量命名 +- 使用 **全大写 + 下划线**:`MAX_POSITION`, `DEFAULT_STOP_LOSS` + +### 2.3 函数命名 +- 使用 **小写字母 + 下划线**:`calculate_metrics()`, `get_bar_history()` + +### 2.4 类命名 +- 使用 **大驼峰命名法 (PascalCase)**:`SimpleLimitBuyStrategy`, `BacktestEngine` + +## 3. 文档字符串规范 + +### 3.1 所有公共类和方法必须有文档字符串 +```python +class SimpleLimitBuyStrategy(Strategy): + """ + 一个基于当前K线Open、前1根和前7根K线Range计算优势价格进行限价买入的策略。 + + 具备以下特点: + - 每根K线开始时取消上一根K线未成交的订单 + - 最多只能有一个开仓挂单和一个持仓 + - 包含简单的止损和止盈逻辑 + + Args: + context: 模拟器实例 + symbol: 交易合约代码 + trade_volume: 单笔交易量 + """ +``` + +### 3.2 复杂逻辑必须添加注释说明 + +## 4. 类型提示规范 + +- 推荐为函数参数和返回值添加类型提示 +- 使用 `from typing` 导入类型 +- 循环导入时使用 `TYPE_CHECKING`: +```python +from typing import Dict, Any, Optional, TYPE_CHECKING + +if TYPE_CHECKING: + from src.backtest_engine import BacktestContext +``` + +## 5. Git 提交规范 + +- 提交信息使用中文或英文 +- 格式:`[类型] 描述` +- 类型:feat, fix, docs, style, refactor, test, chore \ No newline at end of file diff --git a/.kilocode/rules/naming_conventions.md b/.kilocode/rules/naming_conventions.md new file mode 100644 index 0000000..9dfb834 --- /dev/null +++ b/.kilocode/rules/naming_conventions.md @@ -0,0 +1,129 @@ +# 命名约定规则 (Naming Conventions) + +本项目定义了一套统一的命名约定,以确保代码库的一致性和可读性。 + +## 1. 文件命名规范 + +### 1.1 Python 文件 +- 使用 **小写字母 + 下划线**:`backtest_engine.py`, `data_manager.py` +- 避免使用连字符或空格 +- 测试文件以 `test_` 前缀开头:`test_backtest_engine.py` + +### 1.2 配置文件 +- 使用小写字母和下划线:`config.json`, `strategy_params.yaml` +- 环境配置文件使用 `.env` 或 `.env.{environment}` 格式 + +### 1.3 数据文件 +- 遵循 `{数据类型}_{日期范围}.{扩展名}` 格式 +- 示例:`btc_ohlcv_2023_2024.csv`, `strategy_results_202401.json` + +## 2. 变量命名规范 + +### 2.1 普通变量 +- 使用 **小写字母 + 下划线**(snake_case) +- 使用描述性名称,避免缩写 +- ✅ 正确示例:`current_price`, `trade_volume`, `stop_loss_price` +- ❌ 错误示例:`cp`, `tv`, `sl` + +### 2.2 布尔变量 +- 使用 `is_`, `has_`, `are_` 等前缀 +- ✅ 正确示例:`is_valid`, `has_position`, `are_orders_filled` +- ❌ 错误示例:`valid`, `position`, `filled` + +### 2.3 私有变量 +- 使用单下划线前缀(约定俗成的私有) +- ✅ 正确示例:`_internal_cache`, `_last_order_id` +- ❌ 错误示例:`__private_var`(除非确实需要 name mangling) + +### 2.4 临时变量 +- 循环变量可使用单字母或简短名称 +- ✅ 正确示例:`for i in range(n):`, `for bar in bars:` + +## 3. 常量命名规范 + +### 3.1 全局常量 +- 使用 **全大写字母 + 下划线**(SCREAMING_SNAKE_CASE) +- 定义在文件顶部或单独的 `constants.py` 模块中 +- ✅ 正确示例:`MAX_POSITION = 5`, `DEFAULT_COMMISSION_RATE = 0.0003` +- ❌ 错误示例:`max_position`, `default_commission_rate` + +### 3.2 配置常量 +- 使用全大写字母和下划线 +- ✅ 正确示例:`SYMBOL_FUTURES_SUFFIX = ".FG"` + +## 4. 函数命名规范 + +### 4.1 普通函数 +- 使用 **小写字母 + 下划线**(snake_case) +- 函数名应清晰表达其功能 +- ✅ 正确示例:`calculate_metrics()`, `get_bar_history()`, `send_order()` +- ❌ 错误示例:`calc()`, `getData()`, `send()` + +### 4.2 返回布尔值的函数 +- 使用 `is_`, `has_`, `are_` 等前缀 +- ✅ 正确示例:`is_trending_up()`, `has_active_orders()`, `are_positions_valid()` + +### 4.3 私有函数 +- 使用单下划线前缀 +- ✅ 正确示例:`_validate_params()`, `_calculate_pnl()` + +## 5. 类命名规范 + +### 5.1 公共类 +- 使用 **大驼峰命名法**(PascalCase) +- ✅ 正确示例:`BacktestEngine`, `SimpleLimitBuyStrategy`, `DataManager` +- ❌ 错误示例:`backtest_engine`, `simple_limit_buy_strategy` + +### 5.2 抽象基类 +- 使用 `ABC` 后缀或 `Base` 前缀 +- ✅ 正确示例:`Strategy(ABC)`, `BaseIndicator` + +### 5.3 异常类 +- 使用 `Error` 或 `Exception` 后缀 +- ✅ 正确示例:`BacktestError`, `OrderExecutionException` + +## 6. 特定领域命名规范 + +### 6.1 交易相关 +- 方向:`BUY`, `SELL`, `CLOSE_LONG`, `CLOSE_SHORT` +- 订单类型:`LIMIT`, `MARKET`, `STOP` +- 持仓:`LONG`, `SHORT`, `FLAT` + +### 6.2 策略参数 +- 使用描述性名称,包含参数含义 +- ✅ 正确示例:`stop_loss_points`, `take_profit_points`, `range_factor` +- ❌ 错误示例:`sl`, `tp`, `rf` + +### 6.3 K线数据 +- 时间周期:`1m`, `5m`, `15m`, `1h`, `4h`, `1d` +- OHLCV:`open`, `high`, `low`, `close`, `volume` + +## 7. 数据库/缓存命名规范 + +### 7.1 缓存键 +- 使用冒号分隔的层次结构 +- ✅ 正确示例:`strategy:rb:positions`, `market:btc:price` + +### 7.2 日志文件 +- 使用 `{策略名}/{品种}.log` 格式 +- ✅ 正确示例:`logs/SpectralTrendStrategy/rb.log` + +## 8. 命名一致性检查清单 + +在提交代码前,请确认以下检查项: + +- [ ] 所有变量名使用 snake_case +- [ ] 所有类名使用 PascalCase +- [ ] 所有常量使用 SCREAMING_SNAKE_CASE +- [ ] 函数名清晰表达功能 +- [ ] 命名具有描述性,避免模糊缩写 +- [ ] 私有成员使用下划线前缀 +- [ ] 布尔变量使用适当的前缀 + +## 9. 命名反模式(应避免) + +- ❌ 使用单个字母 `l`, `O`, `I` 作为变量名(容易与数字 1, 0 混淆) +- ❌ 使用魔法数字或字符串(应定义为常量) +- ❌ 使用不一致的命名风格混合 +- ❌ 使用过于通用的名称如 `data`, `info`, `temp` +- ❌ 使用项目保留名称如 `strategy`, `engine`, `manager` \ No newline at end of file diff --git a/.kilocode/rules/restricted_files.md b/.kilocode/rules/restricted_files.md new file mode 100644 index 0000000..66ca8e2 --- /dev/null +++ b/.kilocode/rules/restricted_files.md @@ -0,0 +1,126 @@ +# 受限文件规则 (Restricted Files Rules) + +本项目定义了以下受限文件和目录,这些内容 **禁止访问、不允许访问、更不允许修改**。 + +## 1. 受限目录列表 + +### 1.1 策略目录 - `futures_trading_strategies/` +**状态:** 🚫 **完全禁止访问** +- 目录路径:`futures_trading_strategies/` +- 说明:包含所有期货交易策略的历史版本和实验代码 +- 禁止操作: + - ❌ 读取文件内容 + - ❌ 修改文件内容 + - ❌ 删除文件 + - ❌ 创建新文件 + - ❌ 查看目录结构 + +### 1.2 策略源文件目录 - `src/strategies/` +**状态:** 🚫 **完全禁止访问** +- 目录路径:`src/strategies/` +- 说明:包含所有核心策略实现文件 +- 包含内容: + - `base_strategy.py` - 策略基类 + - `SimpleLimitBuyStrategy.py` - 简单限价买入策略 + - `OpenTwoFactorStrategy.py` - 双因子开仓策略 + - `OpenTwoFactorStrategyDouble.py` - 双因子开仓策略(双倍版本) + - `smc_pure_h1_long_strategy.py` - SMC H1 长线策略 + - `utils.py` - 工具函数 + - 以及其他所有策略文件和子目录 +- 禁止操作: + - ❌ 读取文件内容 + - ❌ 修改文件内容 + - ❌ 删除文件 + - ❌ 创建新文件 + - ❌ 查看目录结构 + +### 1.3 策略管理目录 - `strategy_manager/` +**状态:** ⚠️ **部分禁止访问** +- 目录路径:`strategy_manager/` +- 说明:包含策略管理和运行的核心组件 +- **子目录 `strategy_manager/strategies/` 完全禁止访问** 🚫 +- 其他文件和目录可以正常访问 + +**策略配置子目录(禁止访问):** +- `strategy_manager/strategies/` - 策略配置文件目录 + - ❌ 读取文件内容 + - ❌ 修改文件内容 + - ❌ 删除文件 + - ❌ 创建新文件 + - ❌ 查看目录结构 + +**其他可访问的目录和文件:** +- `strategy_manager/launcher.py` - 策略启动器 ✅ +- `strategy_manager/start.py` - 启动脚本 ✅ +- `strategy_manager/restart_daemon.py` - 重启守护进程 ✅ +- `strategy_manager/web_backend.py` - Web后端 ✅ +- `strategy_manager/status.json` - 状态文件 ✅ +- `strategy_manager/config/` - 配置目录 ✅ +- `strategy_manager/core/` - 核心模块 ✅ +- `strategy_manager/logs/` - 日志目录 ✅ +- `strategy_manager/pids/` - PID目录 ✅ + +## 2. 特殊文件保护 + +### 2.1 策略核心文件 +以下文件受到特别保护: +- `src/strategies/base_strategy.py` - 策略基类,包含邮件通知等核心功能 +- `src/strategies/utils.py` - 策略工具函数 +- `strategy_manager/launcher.py` - 策略启动器 +- `strategy_manager/web_backend.py` - Web后端服务 + +### 2.2 配置文件保护 +- `strategy_manager/config/` 目录下的所有配置文件 +- `strategy_manager/status.json` - 策略状态文件 + +## 3. 违规处理 + +### 3.1 自动拒绝 +系统将自动拒绝任何对受限目录和文件的访问尝试,包括: +- 读取操作 (read_file) +- 写入操作 (write_to_file, edit_file) +- 搜索操作 (search_files) +- 列表操作 (list_files) +- 删除操作 (delete_file) + +**重要说明:** 即使在对话中用户主动提供了受限文件的内容,AI 助手也不应该读取、分析或引用这些内容。所有受限文件的内容都应被视为不可访问的机密信息。 + +### 3.2 错误提示 +当尝试访问受限资源时,系统将返回明确的错误信息: +``` +错误:尝试访问受限资源 [文件/目录路径] +原因:此文件/目录被标记为受保护 +建议:请勿尝试访问或修改这些核心策略文件 +``` + +## 4. 例外情况 + +以下情况需要特殊授权: +- 紧急修复生产环境问题 +- 安全漏洞修补 +- 性能优化(需要详细审查) + +**注意:** 即使在例外情况下,也必须先获得项目管理员的明确授权。 + +## 5. 规则说明 + +这些限制规则的目的是: +1. **保护策略资产**:防止核心交易策略被意外或恶意修改 +2. **确保系统稳定性**:避免因修改关键文件导致系统崩溃 +3. **维护代码质量**:确保只有经过充分测试的代码才能部署 +4. **分离关注点**:开发工作与生产环境严格分离 + +**警告:** 违反这些规则可能导致: +- 策略失效 +- 资金损失 +- 系统故障 +- 项目责任追究 + + +# Restricted files + +Files in the list contain sensitive data, they MUST NOT be read + +- strategy_manager/strategies/ +- futures_trading_strategies/ +- src/strategies/ \ No newline at end of file diff --git a/ma_channel_event_probability.png b/ma_channel_event_probability.png deleted file mode 100644 index d7c3664d615c4754cfab6e2b56215b739e05796d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193270 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 NG|$NJ{M;XY`d 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/` | 修改 | 前端界面添加白名单管理功能 | diff --git a/strategy_manager/config/whitelist.json b/strategy_manager/config/whitelist.json new file mode 100644 index 0000000..b175a8c --- /dev/null +++ b/strategy_manager/config/whitelist.json @@ -0,0 +1,5 @@ +{ + "version": "1.0", + "last_auto_start_date": null, + "strategies": {} +} diff --git a/strategy_manager/core/manager.py b/strategy_manager/core/manager.py index 8e81de3..9429afe 100644 --- a/strategy_manager/core/manager.py +++ b/strategy_manager/core/manager.py @@ -12,6 +12,7 @@ import json # 确保导入json模块 # ==================== 动态路径配置 ==================== from core.path_utils import add_project_root_to_path +from core.whitelist_manager import WhitelistManager # 添加项目根路径到sys.path PROJECT_ROOT = add_project_root_to_path() @@ -34,6 +35,10 @@ class StrategyManager: # 配置管理器日志 self._setup_logger() + # 初始化白名单管理器 + self.whitelist_manager = WhitelistManager() + self.logger.info("📋 白名单管理器已初始化") + self.strategies: Dict[str, Dict[str, Any]] = {} self.logger.info("🔄 正在加载策略配置...") self.load_strategies() @@ -109,15 +114,31 @@ class StrategyManager: self.logger.error("❌ 加载配置失败 %s: %s", config_file, e, exc_info=True) def get_status(self) -> Dict[str, Any]: - """获取完整状态""" + """获取完整状态(包含白名单信息)""" self._refresh_status() - return { + + # 构建状态数据 + status = { "timestamp": datetime.now().isoformat(), "total": len(self.strategies), "running": sum(1 for s in self.strategies.values() if s["status"] == "running"), "strategies": self.strategies } + # 添加白名单信息到每个策略 + 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) + + # 添加自动启动状态 + auto_start_status = self.whitelist_manager.get_auto_start_status() + status["whitelist_auto_start_today"] = auto_start_status["should_auto_start"] + status["whitelist_last_date"] = auto_start_status["last_auto_start_date"] + status["whitelist_total"] = auto_start_status["whitelist_count"] + status["whitelist_enabled"] = auto_start_status["enabled_count"] + + return status + def _refresh_status(self): """刷新进程状态 - 双重验证""" for name, info in self.strategies.items(): @@ -347,6 +368,121 @@ class StrategyManager: except Exception as e: self.logger.error("❌ 保存状态失败: %s", e, exc_info=True) + # ==================== 白名单管理方法 ==================== + + def add_to_whitelist(self, name: str) -> bool: + """ + 添加策略到白名单 + + Args: + name: 策略标识符 + + Returns: + 是否添加成功 + """ + if name not in self.strategies: + self.logger.error("❌ 策略不存在: %s", name) + return False + + if self.whitelist_manager.add(name, enabled=True): + self.logger.info("✅ 添加到白名单: %s", name) + self._save_status() + return True + + return False + + def remove_from_whitelist(self, name: str) -> bool: + """ + 从白名单移除策略 + + Args: + name: 策略标识符 + + Returns: + 是否移除成功 + """ + if self.whitelist_manager.remove(name): + self.logger.info("✅ 从白名单移除: %s", name) + self._save_status() + return True + + return False + + def set_whitelist_enabled(self, name: str, enabled: bool) -> bool: + """ + 设置策略在白名单中的启用状态 + + Args: + name: 策略标识符 + enabled: 是否启用 + + Returns: + 是否设置成功 + """ + if self.whitelist_manager.set_enabled(name, enabled): + self.logger.info("✅ 设置白名单状态: %s -> %s", name, enabled) + self._save_status() + return True + + return False + + def auto_start_whitelist_strategies(self) -> Dict[str, bool]: + """ + 自动启动白名单中所有未运行的策略 + 一天只执行一次 + + Returns: + Dict[str, bool]: 每个策略的启动结果 + """ + if not self.whitelist_manager.should_auto_start_today(): + self.logger.info("⏰ 今天已经执行过自动启动,跳过") + return {} + + self.logger.info("🚀 开始执行白名单自动启动...") + + results = {} + whitelist = self.whitelist_manager.get_all() + + for name, config in whitelist.items(): + if not config.get("enabled", True): + self.logger.info("⏭️ 跳过禁用策略: %s", name) + continue + + if name not in self.strategies: + self.logger.warning("⚠️ 策略不在系统中: %s", name) + continue + + # 检查是否已在运行 + if self._is_running(name): + self.logger.info("✅ 策略已在运行: %s", name) + results[name] = True + continue + + # 尝试启动 + self.logger.info("🚀 启动白名单策略: %s", name) + success = self.start_strategy(name) + + # 记录启动结果 + results[name] = success + + if success: + self.logger.info("✅ 白名单策略启动成功: %s", name) + else: + self.logger.error("❌ 白名单策略启动失败: %s", name) + + # 更新日期 + self.whitelist_manager.update_last_auto_start_date( + datetime.now().date().isoformat() + ) + + # 统计结果 + success_count = sum(1 for v in results.values() if v) + fail_count = len(results) - success_count + + self.logger.info("📊 白名单自动启动完成: 成功 %d, 失败 %d", success_count, fail_count) + + return results + def print_status_table(status: Dict[str, Any]): """格式化打印状态表格""" diff --git a/strategy_manager/core/whitelist_manager.py b/strategy_manager/core/whitelist_manager.py new file mode 100644 index 0000000..41a48b7 --- /dev/null +++ b/strategy_manager/core/whitelist_manager.py @@ -0,0 +1,345 @@ +""" +白名单管理器 - 管理期望自动启动的策略列表 + +功能: +1. 持久化白名单配置到 JSON 文件 +2. 支持添加/移除策略 +3. 支持启用/禁用白名单中的策略 +4. 跟踪自动启动日期,实现一天只尝试一次 +""" + +import json +import sys +from pathlib import Path +from typing import Dict, Any, Optional +from datetime import datetime + + +class WhitelistManager: + """白名单管理器""" + + def __init__(self, config_path: str = "config/whitelist.json"): + """ + 初始化白名单管理器 + + Args: + config_path: 白名单配置文件路径 + """ + self.config_path = Path(config_path) + self.data = self._load() + self.logger = self._setup_logger() + + def _setup_logger(self): + """配置日志""" + import logging + logger = logging.getLogger("WhitelistManager") + return logger + + def _load(self) -> Dict[str, Any]: + """ + 加载白名单配置 + + Returns: + 白名单配置数据 + """ + if not self.config_path.exists(): + # 返回默认配置 + return { + "version": "1.0", + "last_auto_start_date": None, + "strategies": {} + } + + try: + with open(self.config_path, 'r', encoding='utf-8') as f: + data = json.load(f) + # 确保数据结构完整 + if "version" not in data: + data["version"] = "1.0" + if "strategies" not in data: + data["strategies"] = {} + return data + except Exception as e: + print(f"[WARNING] 加载白名单配置失败: {e}") + return { + "version": "1.0", + "last_auto_start_date": None, + "strategies": {} + } + + def _save(self) -> bool: + """ + 保存白名单配置 + + Returns: + 是否保存成功 + """ + try: + # 确保目录存在 + self.config_path.parent.mkdir(exist_ok=True, parents=True) + + with open(self.config_path, 'w', encoding='utf-8') as f: + json.dump(self.data, f, indent=2, ensure_ascii=False) + + self.logger.debug("白名单配置已保存: %s", self.config_path) + return True + except Exception as e: + self.logger.error("保存白名单配置失败: %s", e) + return False + + def add(self, strategy_key: str, enabled: bool = True) -> bool: + """ + 添加策略到白名单 + + Args: + strategy_key: 策略标识符 (如 "DualModeTrendlineHawkesStrategy2_FG") + enabled: 是否启用自动启动 + + Returns: + 是否添加成功(False 表示已存在) + """ + if strategy_key in self.data["strategies"]: + self.logger.warning("策略已在白名单中: %s", strategy_key) + return False + + self.data["strategies"][strategy_key] = { + "enabled": enabled, + "added_at": datetime.now().isoformat(), + "added_by": "web" + } + + if self._save(): + self.logger.info("添加策略到白名单: %s (enabled=%s)", strategy_key, enabled) + return True + + return False + + def remove(self, strategy_key: str) -> bool: + """ + 从白名单移除策略 + + Args: + strategy_key: 策略标识符 + + Returns: + 是否移除成功(False 表示不存在) + """ + if strategy_key not in self.data["strategies"]: + self.logger.warning("策略不在白名单中: %s", strategy_key) + return False + + del self.data["strategies"][strategy_key] + + if self._save(): + self.logger.info("从白名单移除策略: %s", strategy_key) + return True + + return False + + def set_enabled(self, strategy_key: str, enabled: bool) -> bool: + """ + 设置策略在白名单中的启用状态 + + Args: + strategy_key: 策略标识符 + enabled: 是否启用 + + Returns: + 是否设置成功 + """ + if strategy_key not in self.data["strategies"]: + self.logger.warning("策略不在白名单中: %s", strategy_key) + return False + + self.data["strategies"][strategy_key]["enabled"] = enabled + self.data["strategies"][strategy_key]["updated_at"] = datetime.now().isoformat() + + if self._save(): + self.logger.info("设置白名单策略状态: %s -> %s", strategy_key, enabled) + return True + + return False + + def get_all(self) -> Dict[str, Dict[str, Any]]: + """ + 获取所有白名单策略 + + Returns: + 白名单策略字典 {strategy_key: {enabled, added_at, ...}} + """ + return self.data.get("strategies", {}) + + def get(self, strategy_key: str) -> Optional[Dict[str, Any]]: + """ + 获取单个策略的白名单配置 + + Args: + strategy_key: 策略标识符 + + Returns: + 策略配置或 None + """ + return self.data["strategies"].get(strategy_key) + + def is_in_whitelist(self, strategy_key: str) -> bool: + """ + 检查策略是否在白名单中 + + Args: + strategy_key: 策略标识符 + + Returns: + 是否在白名单中 + """ + return strategy_key in self.data.get("strategies", {}) + + def is_enabled_in_whitelist(self, strategy_key: str) -> bool: + """ + 检查策略是否在白名单中且已启用 + + Args: + strategy_key: 策略标识符 + + Returns: + 是否在白名单中且启用 + """ + if strategy_key not in self.data.get("strategies", {}): + return False + return self.data["strategies"][strategy_key].get("enabled", True) + + def update_last_auto_start_date(self, date_str: str) -> bool: + """ + 更新最后自动启动日期 + + Args: + date_str: 日期字符串 (YYYY-MM-DD) + + Returns: + 是否更新成功 + """ + self.data["last_auto_start_date"] = date_str + return self._save() + + def get_last_auto_start_date(self) -> Optional[str]: + """ + 获取最后自动启动日期 + + Returns: + 日期字符串或 None + """ + return self.data.get("last_auto_start_date") + + def should_auto_start_today(self) -> bool: + """ + 检查今天是否应该自动启动 + + Returns: + 今天是否应该自动启动 + """ + today = datetime.now().date().isoformat() + last_date = self.data.get("last_auto_start_date") + + if last_date is None: + return True + + return last_date != today + + def get_auto_start_status(self) -> Dict[str, Any]: + """ + 获取自动启动状态 + + Returns: + 自动启动状态信息 + """ + today = datetime.now().date().isoformat() + last_date = self.data.get("last_auto_start_date") + + return { + "should_auto_start": self.should_auto_start_today(), + "last_auto_start_date": last_date, + "is_first_run_today": last_date != today, + "whitelist_count": len(self.data.get("strategies", {})), + "enabled_count": sum( + 1 for s in self.data.get("strategies", {}).values() + if s.get("enabled", True) + ) + } + + def clear(self) -> bool: + """ + 清空白名单(谨慎使用) + + Returns: + 是否清空成功 + """ + self.data["strategies"] = {} + self.data["last_auto_start_date"] = None + return self._save() + + +# ==================== 单元测试 ==================== + +if __name__ == "__main__": + import os + + # 切换到 strategy_manager 目录 + os.chdir(Path(__file__).parent.parent) + + # 测试白名单管理器 + print("=" * 60) + print("WhitelistManager 单元测试") + print("=" * 60) + + # 创建测试用的白名单管理器 + test_config_path = "config/whitelist_test.json" + wm = WhitelistManager(test_config_path) + + # 测试添加 + print("\n[测试] 添加策略到白名单...") + assert wm.add("TestStrategy1_FG") == True + assert wm.add("TestStrategy2_FG", enabled=False) == True + assert wm.add("TestStrategy1_FG") == False # 已存在 + + # 测试获取 + print("\n[测试] 获取白名单...") + all_strategies = wm.get_all() + assert "TestStrategy1_FG" in all_strategies + assert "TestStrategy2_FG" in all_strategies + print(f"白名单策略: {list(all_strategies.keys())}") + + # 测试状态检查 + print("\n[测试] 状态检查...") + assert wm.is_in_whitelist("TestStrategy1_FG") == True + assert wm.is_in_whitelist("TestStrategy1_FG") == True + assert wm.is_in_whitelist("TestStrategy3_FG") == False + assert wm.is_enabled_in_whitelist("TestStrategy1_FG") == True + assert wm.is_enabled_in_whitelist("TestStrategy2_FG") == False + + # 测试设置启用状态 + print("\n[测试] 设置启用状态...") + assert wm.set_enabled("TestStrategy2_FG", True) == True + assert wm.is_enabled_in_whitelist("TestStrategy2_FG") == True + assert wm.set_enabled("TestStrategy3_FG", True) == False # 不存在 + + # 测试移除 + print("\n[测试] 移除策略...") + assert wm.remove("TestStrategy2_FG") == True + assert wm.remove("TestStrategy2_FG") == False # 已移除 + assert wm.is_in_whitelist("TestStrategy2_FG") == False + + # 测试自动启动日期 + print("\n[测试] 自动启动日期...") + today = datetime.now().date().isoformat() + assert wm.should_auto_start_today() == True + wm.update_last_auto_start_date(today) + assert wm.should_auto_start_today() == False + wm.update_last_auto_start_date("2024-01-01") + assert wm.should_auto_start_today() == True + + # 清理测试文件 + print("\n[测试] 清理...") + Path(test_config_path).unlink(missing_ok=True) + + print("\n" + "=" * 60) + print("✅ 所有测试通过!") + print("=" * 60) diff --git a/strategy_manager/frontend/dist/index.html b/strategy_manager/frontend/dist/index.html index d61095e..5971fc3 100644 --- a/strategy_manager/frontend/dist/index.html +++ b/strategy_manager/frontend/dist/index.html @@ -14,10 +14,23 @@ @@ -33,89 +46,173 @@ - \ No newline at end of file + diff --git a/strategy_manager/start.py b/strategy_manager/start.py index f3dd041..28a1697 100644 --- a/strategy_manager/start.py +++ b/strategy_manager/start.py @@ -27,18 +27,138 @@ def main(): # 查看日志(最近50行) python start.py logs -n DualModeTrendlineHawkesStrategy2_FG -t 50 + + # ========== 白名单管理 ========== + # 查看白名单 + python start.py whitelist + + # 添加策略到白名单 + python start.py whitelist add -n DualModeTrendlineHawkesStrategy2_FG + + # 从白名单移除策略 + python start.py whitelist remove -n DualModeTrendlineHawkesStrategy2_FG + + # 启用白名单中的策略 + python start.py whitelist enable -n DualModeTrendlineHawkesStrategy2_FG + + # 禁用白名单中的策略 + python start.py whitelist disable -n DualModeTrendlineHawkesStrategy2_FG + + # 手动触发白名单自动启动 + python start.py whitelist auto-start """ ) - parser.add_argument("action", choices=["start", "stop", "restart", "status", "logs"]) + parser.add_argument("action", choices=["start", "stop", "restart", "status", "logs", "whitelist"]) parser.add_argument("-n", "--name", help="策略标识符(策略名_品种)") parser.add_argument("-a", "--all", action="store_true", help="对所有策略执行操作") parser.add_argument("-c", "--config", default="config/main.json", help="主配置文件路径") parser.add_argument("-t", "--tail", type=int, default=30, help="查看日志末尾行数") + # 白名单子命令 + whitelist_group = parser.add_argument_group("白名单操作") + whitelist_group.add_argument("whitelist_action", choices=["list", "add", "remove", "enable", "disable", "auto-start"], + help="白名单操作动作", nargs="?") + args = parser.parse_args() manager = StrategyManager(args.config) + # 白名单管理 + if args.action == "whitelist": + if args.whitelist_action == "list" or args.whitelist_action is None: + # 列出白名单 + print("\n" + "=" * 80) + print("📋 白名单列表") + print("=" * 80) + + whitelist = manager.whitelist_manager.get_all() + auto_status = manager.whitelist_manager.get_auto_start_status() + + print(f"白名单策略总数: {auto_status['whitelist_count']}") + print(f"已启用策略数: {auto_status['enabled_count']}") + print(f"今天已自动启动: {'是' if not auto_status['should_auto_start'] else '否'}") + print(f"上次自动启动日期: {auto_status['last_auto_start_date'] or '从未'}") + print("-" * 80) + + if not whitelist: + print("白名单为空") + else: + print(f"{'策略标识':<45} {'状态':<10} {'添加时间'}") + print("-" * 80) + for name, config in whitelist.items(): + status = "启用" if config.get("enabled", True) else "禁用" + added_at = config.get("added_at", "")[:19] + print(f"{name:<45} {status:<10} {added_at}") + print("=" * 80) + + elif args.whitelist_action == "add": + # 添加到白名单 + if not args.name: + print("❌ 错误: 添加操作必须指定策略名称 (-n)") + sys.exit(1) + if manager.add_to_whitelist(args.name): + print(f"✅ 成功添加到白名单: {args.name}") + else: + print(f"❌ 添加失败,策略可能已存在: {args.name}") + sys.exit(1) + + elif args.whitelist_action == "remove": + # 从白名单移除 + if not args.name: + print("❌ 错误: 移除操作必须指定策略名称 (-n)") + sys.exit(1) + if manager.remove_from_whitelist(args.name): + print(f"✅ 成功从白名单移除: {args.name}") + else: + print(f"❌ 移除失败,策略可能不在白名单中: {args.name}") + sys.exit(1) + + elif args.whitelist_action == "enable": + # 启用白名单中的策略 + if not args.name: + print("❌ 错误: 启用操作必须指定策略名称 (-n)") + sys.exit(1) + if manager.set_whitelist_enabled(args.name, True): + print(f"✅ 已启用: {args.name}") + else: + print(f"❌ 启用失败,策略可能不在白名单中: {args.name}") + sys.exit(1) + + elif args.whitelist_action == "disable": + # 禁用白名单中的策略 + if not args.name: + print("❌ 错误: 禁用操作必须指定策略名称 (-n)") + sys.exit(1) + if manager.set_whitelist_enabled(args.name, False): + print(f"✅ 已禁用: {args.name}") + else: + print(f"❌ 禁用失败,策略可能不在白名单中: {args.name}") + sys.exit(1) + + elif args.whitelist_action == "auto-start": + # 手动触发自动启动 + print("\n" + "=" * 80) + print("🚀 手动触发白名单自动启动") + print("=" * 80) + + results = manager.auto_start_whitelist_strategies() + + if not results: + print("⚠️ 今天已执行过自动启动或白名单为空") + else: + success_count = sum(1 for v in results.values() if v) + fail_count = len(results) - success_count + + print(f"📊 结果: 成功 {success_count}, 失败 {fail_count}") + for name, success in results.items(): + status = "✅ 成功" if success else "❌ 失败" + print(f" {status}: {name}") + + print("=" * 80) + + return + + # 原有逻辑 if args.action == "status": status = manager.get_status() print_status_table(status) diff --git a/strategy_manager/web_backend.py b/strategy_manager/web_backend.py index 2fc9beb..c30a0c8 100644 --- a/strategy_manager/web_backend.py +++ b/strategy_manager/web_backend.py @@ -6,6 +6,7 @@ import logging from collections import deque from pathlib import Path +from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException, Query from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse @@ -63,7 +64,7 @@ def get_git_commit_info(): logger.warning(f"无法获取 Git 提交信息: {e}") return "获取 Git 信息失败" -# ================== 定时任务逻辑 (保持不变) ================== +# ================== 定时任务逻辑 ================== def scheduled_restart_task(): """ @@ -94,10 +95,39 @@ def scheduled_restart_task(): logger.info("⏰ [定时任务] 自动重启流程结束") -# ================== FastAPI 事件钩子 (保持不变) ================== +def scheduled_whitelist_auto_start(): + """ + 定时任务:白名单自动启动 + 仅在 08:58 执行 + """ + logger.info("⏰ [白名单定时任务] 触发白名单自动启动...") -@app.on_event("startup") -async def start_scheduler(): + 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.error(f"❌ [白名单定时任务] {name} 启动失败") + + +# ================== FastAPI 生命周期事件 (使用 lifespan 替代废弃的 on_event) ================== + +@asynccontextmanager +async def lifespan(app: FastAPI): + """ + FastAPI 生命周期管理器,替代废弃的 @app.on_event 装饰器 + """ + # 原有重启任务 (08:58, 20:58) scheduler.add_job( scheduled_restart_task, CronTrigger(hour=8, minute=58), @@ -110,13 +140,29 @@ async def start_scheduler(): id="restart_evening", replace_existing=True ) + + # 新增:白名单自动启动任务(仅 08:58) + scheduler.add_job( + scheduled_whitelist_auto_start, + CronTrigger(hour=8, minute=58), + id="whitelist_auto_start", + replace_existing=True + ) + scheduler.start() - logger.info("📅 定时任务调度器已启动 (计划时间: 08:58, 20:58)") + logger.info("📅 定时任务调度器已启动") + logger.info(" - 重启任务: 08:58, 20:58") + logger.info(" - 白名单自动启动: 08:58") + yield -@app.on_event("shutdown") -async def stop_scheduler(): + # 应用关闭时执行 scheduler.shutdown() + logger.info("📅 定时任务调度器已关闭") + + +# ================== 初始化 ================== +app = FastAPI(title="策略控制台", lifespan=lifespan) # ================== API 路由 ================== @@ -168,9 +214,66 @@ def get_logs(name: str, lines: int = Query(50, le=500)): raise HTTPException(500, f"读取日志失败: {e}") -# ================== 静态文件挂载 (保持不变) ================== -# 注意: 这里的路径是示例,请确保它与你的项目结构匹配 -# 假设你的HTML文件在 "frontend/" 目录下 +# ================== 白名单管理 API ================== + +@app.get("/api/whitelist") +def get_whitelist(): + """获取白名单列表""" + whitelist = manager.whitelist_manager.get_all() + auto_start_status = manager.whitelist_manager.get_auto_start_status() + return { + "whitelist": whitelist, + "auto_start_status": auto_start_status + } + + +@app.post("/api/whitelist/{name}/add") +def add_to_whitelist(name: str): + """添加策略到白名单""" + if manager.add_to_whitelist(name): + return {"success": True, "message": f"已添加到白名单: {name}"} + raise HTTPException(400, f"添加失败,策略可能已存在: {name}") + + +@app.post("/api/whitelist/{name}/remove") +def remove_from_whitelist(name: str): + """从白名单移除策略""" + if manager.remove_from_whitelist(name): + return {"success": True, "message": f"已从白名单移除: {name}"} + raise HTTPException(400, f"移除失败,策略可能不在白名单中: {name}") + + +@app.post("/api/whitelist/{name}/enable") +def enable_in_whitelist(name: str): + """启用白名单中的策略""" + if manager.set_whitelist_enabled(name, True): + return {"success": True, "message": f"已启用: {name}"} + raise HTTPException(400, f"操作失败,策略可能不在白名单中: {name}") + + +@app.post("/api/whitelist/{name}/disable") +def disable_in_whitelist(name: str): + """禁用白名单中的策略""" + if manager.set_whitelist_enabled(name, False): + return {"success": True, "message": f"已禁用: {name}"} + raise HTTPException(400, f"操作失败,策略可能不在白名单中: {name}") + + +@app.post("/api/whitelist/auto-start") +def trigger_auto_start(): + """手动触发白名单自动启动(用于测试)""" + results = manager.auto_start_whitelist_strategies() + return { + "success": True, + "results": results, + "count": len(results), + "success_count": sum(1 for v in results.values() if v), + "fail_count": sum(1 for v in results.values() if not v) + } + + +# ================== 静态文件挂载 ================== +# 服务前端构建文件 app.mount("/static", StaticFiles(directory="frontend/dist"), name="static") @app.get("/")