From 7ae3d16a5e4d07356f17e4155a365abe571b7ad2 Mon Sep 17 00:00:00 2001 From: liaozhaorun <1300336796@qq.com> Date: Wed, 28 Jan 2026 00:22:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20start=E8=84=9A=E6=9C=AC=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20conda=20activate=20stock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kilocode/rules/interaction_rules.md | 82 ++++++ .kilocode/rules/requirement_review.md | 183 +++++++++++++ .kilocode/rules/rules_index.md | 23 +- qmt/qmt_config.md | 379 -------------------------- qmt/qmt_functionality.md | 331 ++++++++++++++++++++++ qmt/start.bat | 20 +- 6 files changed, 637 insertions(+), 381 deletions(-) create mode 100644 .kilocode/rules/interaction_rules.md create mode 100644 .kilocode/rules/requirement_review.md delete mode 100644 qmt/qmt_config.md create mode 100644 qmt/qmt_functionality.md diff --git a/.kilocode/rules/interaction_rules.md b/.kilocode/rules/interaction_rules.md new file mode 100644 index 0000000..4f957b1 --- /dev/null +++ b/.kilocode/rules/interaction_rules.md @@ -0,0 +1,82 @@ +# 交互限制规则 + +本规则定义了与用户交互时的行为限制。 + +## 代码编写限制 + +### 规则描述 +在编写任何代码之前,必须先向用户询问并获得明确许可。 + +### 具体规则 + +- **禁止直接编写代码**:任何代码修改、新增文件、代码重构都必须先询问用户 +- **询问内容**:明确说明将要编写/修改的代码内容、目的和位置 +- **获得许可**:等待用户确认后才能执行代码编写 +- **代码审查**:编写完成后应展示代码内容供用户审查 + +### 询问示例 + +``` +我计划在 `main/utils/data_process.py` 文件中添加一个新的数据处理函数 `normalize_data()`,用于对因子数据进行标准化处理。 + +具体改动: +1. 在文件末尾添加新的函数 +2. 函数接收 DataFrame 和列名作为参数 +3. 返回标准化后的 DataFrame + +是否允许我编写这段代码? +``` + +### 允许的操作(无需询问) + +- 创建空的模板文件 +- 创建空的类或函数框架(不含实现) +- 读取现有文件内容 + +## 命令执行限制 + +### 规则描述 +禁止直接执行任何命令,所有命令执行都必须先询问用户。 + +### 具体规则 + +- **禁止直接执行命令**:任何 CLI 命令、脚本执行都必须先询问用户 +- **命令说明**:明确说明命令的内容、目的和预期影响 +- **获得许可**:等待用户确认后才能执行命令 +- **结果展示**:命令执行后应展示结果供用户确认 + +### 询问示例 + +``` +我需要执行以下命令来更新项目的依赖: + +```bash +pip install --upgrade pandas numpy +``` + +这将更新 pandas 和 numpy 包到最新版本。是否允许执行? +``` + +### 允许的操作(无需询问) + +- 查看文件列表(`list_files`) +- 读取文件内容(`read_file`) +- 查看帮助信息 + +## 违反规则的处理 + +### 轻微违反 +- 立即停止当前操作 +- 向用户说明违反了哪条规则 +- 重新按照规则流程执行 + +### 严重违反 +- 暂停当前会话 +- 向用户报告违规行为 +- 等待用户重新确认是否继续 + +## 相关规则文件 + +- [rules_index.md](rules_index.md) - 规则索引 +- [restricted_files.md](restricted_files.md) - 限制文件规则 +- [restricted_reads.md](restricted_reads.md) - 读取限制规则 diff --git a/.kilocode/rules/requirement_review.md b/.kilocode/rules/requirement_review.md new file mode 100644 index 0000000..16e4eeb --- /dev/null +++ b/.kilocode/rules/requirement_review.md @@ -0,0 +1,183 @@ +# 代码修改需求审查规则 + +本规则定义了代码修改前的需求审查流程,确保修改工作符合项目需求,避免引入不必要的变更。 + +## 规则目的 + +- 规范代码修改流程,确保修改符合需求 +- 避免在修改过程中引入与任务无关的功能变更 +- 提高代码修改的可控性和可追溯性 + +## 修改前检查 + +### 需求文件检查 + +在修改任何代码文件前,必须执行以下检查: + +1. **检查需求md文件**: + - 检查目标模块目录下是否存在需求md文件 + - 匹配模式:`*.md` 或 `requirement*.md` + - 常见命名:`requirement.md`、`requirement_xxx.md`、`模块名_requirement.md` + +2. **阅读并理解需求**: + - 如果存在需求md文件,必须先阅读并理解其内容 + - 明确任务目标和修改范围 + - 记录关键需求点 + +3. **不存在需求文件**: + - 如果不存在需求md文件,继续正常修改流程 + - 仍需与用户确认修改范围和目标 + +### 检查示例 + +```python +import os + +def check_requirement_file(module_path): + """检查模块目录下是否存在需求md文件""" + md_files = [f for f in os.listdir(module_path) + if f.endswith('.md') or f.lower().startswith('requirement')] + + if md_files: + print(f"发现需求文件: {md_files}") + return True + return False + +# 推荐做法 +def before_modify_code(module_path): + """修改代码前的检查流程""" + if check_requirement_file(module_path): + print("请先阅读需求md文件并理解需求内容") + # 读取并分析需求文件 + # 确认修改范围和目标 + else: + print("未发现需求文件,继续正常流程") +``` + +## 修改范围控制 + +### 严格遵守需求范围 + +- **只修改任务要求的功能相关代码** +- **禁止修改与任务要求无关的功能代码** +- **禁止在修改过程中引入意外的功能变更** + +### 范围控制原则 + +| 场景 | 正确做法 | 错误做法 | +|------|----------|----------| +| 修改函数A | 只修改函数A相关的代码 | 同时修改函数B、C | +| 添加新功能 | 在指定位置添加 | 在其他地方添加辅助功能 | +| 修复bug | 只修复目标bug | 顺便优化其他代码 | +| 重构代码 | 只重构必要部分 | 大规模重构无关模块 | + +### 示例说明 + +```python +# 任务要求:修复 get_factor 函数中的除零错误 + +# 正确做法:只修复除零问题,不修改其他内容 +def get_factor(df, window=5): + epsilon = 1e-8 # 防止除零 + result = df["close"] / (df["high"] - df["low"] + epsilon) + return result + +# 错误做法:在修复过程中引入了不必要的变更 +def get_factor(df, window=5): + # 不应该添加日志功能(除非需求要求) + logger.info(f"Calculating factor with window={window}") + + epsilon = 1e-8 + result = df["close"] / (df["high"] - df["low"] + epsilon) + + # 不应该修改返回值类型(除非需求要求) + return {"factor": result, "window": window} +``` + +### 变更影响评估 + +在修改过程中,如果发现可能影响其他功能的改动: + +1. **暂停当前修改** +2. **评估影响范围** +3. **与用户确认**:说明影响和变更原因 +4. **获得许可**:确认是否继续修改 + +```python +# 发现可能影响其他功能的示例 +def modify_function(): + """修改函数时发现可能影响其他功能""" + potential_impact = True + + if potential_impact: + # 暂停修改,与用户确认 + print("发现可能影响其他功能的变更,请确认是否继续") + # 等待用户确认后再执行修改 +``` + +## 例外情况 + +以下情况可以进行小幅调整,但需在提交前说明: + +### 1. 语法错误和拼写问题 + +```python +# 允许的修复 +def caculate_factor(): # 拼写错误 + return "calculated" # 修正为 calculate + +# 允许 +def calculate_factor(): + return "calculated" +``` + +### 2. 代码格式化调整 + +```python +# 为了代码格式化一致性可以进行格式调整 + +# 之前 +def example_function(df,parameter1,parameter2): + result=df["col"]/(df["high"]-df["low"]+epsilon) + return result + +# 之后(格式调整) +def example_function(df, parameter1, parameter2): + result = df["col"] / (df["high"] - df["low"] + epsilon) + return result +``` + +### 3. 明显的性能优化 + +```python +# 明显的性能优化可以进行 + +# 优化前 +def slow_calculation(df): + result = [] + for i in range(len(df)): + result.append(df["close"].iloc[i] * 2) + return result + +# 优化后 +def fast_calculation(df): + result = df["close"] * 2 + return result +``` + +## 提交前检查清单 + +在提交代码修改前,确认以下事项: + +- [ ] 修改内容符合需求文件要求(如果存在) +- [ ] 没有引入与任务无关的功能变更 +- [ ] 没有破坏现有功能 +- [ ] 格式调整已说明 +- [ ] 性能优化已说明 +- [ ] 语法错误已修复 + +## 相关规则文件 + +- [rules_index.md](rules_index.md) - 规则索引 +- [interaction_rules.md](interaction_rules.md) - 交互限制规则 +- [formatting.md](formatting.md) - 代码格式化规则 diff --git a/.kilocode/rules/rules_index.md b/.kilocode/rules/rules_index.md index c132e33..a8b57fb 100644 --- a/.kilocode/rules/rules_index.md +++ b/.kilocode/rules/rules_index.md @@ -10,6 +10,8 @@ | [naming_conventions.md](naming_conventions.md) | 命名约定规范 | 高 | | [restricted_files.md](restricted_files.md) | 限制文件修改规则 | 高 | | [restricted_reads.md](restricted_reads.md) | 限制文件读取规则 | 高 | +| [interaction_rules.md](interaction_rules.md) | 交互限制规则 | 高 | +| [requirement_review.md](requirement_review.md) | 代码修改需求审查规则 | 高 | | [rule_formatting_guide.md](rule_formatting_guide.md) | 规则编写指南 | 中 | ## 规则说明 @@ -64,6 +66,23 @@ - **列表枚举**:使用 `-`, `*` 枚举具体规则 - **代码示例**:使用 ``` 包含代码示例 +### 6. 交互限制规则 [interaction_rules.md](interaction_rules.md) + +定义与用户交互时的行为限制: + +- **代码编写**:必须先询问用户,获得许可后才能编写代码 +- **命令执行**:必须先询问用户,获得许可后才能执行命令 +- **询问内容**:明确说明将要执行的操作、目的和影响 + +### 7. 代码修改需求审查规则 [requirement_review.md](requirement_review.md) + +规范代码修改前的需求审查流程: + +- **修改前检查**:检查模块目录下是否存在需求md文件 +- **修改范围控制**:只修改任务要求的功能相关代码 +- **变更影响评估**:发现可能影响其他功能的改动时先与用户确认 +- **例外情况**:语法错误、代码格式化、性能优化可小幅调整 + ## 项目结构 ``` @@ -71,9 +90,11 @@ NewStock/ ├── .kilocode/ │ └── rules/ │ ├── formatting.md # 代码格式化规则 -│ ├── naming_conventions.md # 命名约定规则 +│ ├── naming_conventions.md # 命名约定规范 │ ├── restricted_files.md # 限制文件修改规则 │ ├── restricted_reads.md # 限制文件读取规则 +│ ├── interaction_rules.md # 交互限制规则 +│ ├── requirement_review.md # 代码修改需求审查规则 │ └── rule_formatting_guide.md # 规则编写指南 ├── main/ │ ├── factor/ # 因子计算模块 diff --git a/qmt/qmt_config.md b/qmt/qmt_config.md deleted file mode 100644 index 194e490..0000000 --- a/qmt/qmt_config.md +++ /dev/null @@ -1,379 +0,0 @@ -# QMT 模块配置说明 - -本文档详细介绍 NewStock 量化交易系统中 QMT 模块的配置文件格式和所有配置项的含义。 - -## 配置文件概述 - -QMT 模块使用 JSON 格式的配置文件来管理 MiniQMT 终端连接、多个交易策略的执行配置。配置文件通常命名为 `config.json`,位于项目根目录或 `qmt/` 目录下。 - -## 完整配置示例 - -```json -{ - "redis": { - "host": "localhost", - "port": 123, - "password": "123", - "db": 0 - }, - "qmt_terminals": [ - { - "qmt_id": "gj", - "alias": "国金证券", - "path": "D:\\QMT\\国金证券QMT交易端\\userdata_mini", - "account_id": "123", - "account_type": "STOCK" - } - ], - "strategies": { - "ST_Strategy": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - }, - "XSZ_Strategy": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - } - } -} -``` - -## 配置项详解 - -### 1. Redis 配置(redis) - -Redis 用于存储交易状态、缓存策略信号和实时行情数据。 - -| 配置项 | 类型 | 必选 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `host` | 字符串 | 是 | - | Redis 服务器地址,支持 IP 地址或域名 | -| `port` | 整数 | 是 | - | Redis 服务端口,默认为 6379 | -| `password` | 字符串 | 否 | `null` | Redis 访问密码,如无密码则设为空字符串或 `null` | -| `db` | 整数 | 否 | 0 | Redis 数据库编号,范围 0-15 | - -#### 详细说明 - -- **`host`**:配置 Redis 服务器的网络地址。本地开发环境通常使用 `localhost` 或 `127.0.0.1`;生产环境应使用服务器的实际 IP 地址或域名。 -- **`port`**:Redis 服务监听端口,标准端口为 6379。如果您的 Redis 使用非标准端口,请在此处修改。 -- **`password`**:Redis 认证密码。如果 Redis 服务器未启用密码认证,此项可设为空字符串 `""` 或 `null`。生产环境建议启用密码认证以保证安全性。 -- **`db`**:Redis 数据库编号。不同的应用可以使用不同的数据库来隔离数据,避免键名冲突。 - -#### 完整示例 - -```json -"redis": { - "host": "192.168.1.100", - "port": 6379, - "password": "your_password_here", - "db": 0 -} -``` - -### 2. QMT 终端配置(qmt_terminals) - -`qmt_terminals` 是一个数组,用于配置一个或多个 MiniQMT 交易终端。每个终端代表一个券商账户。 - -| 配置项 | 类型 | 必选 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `qmt_id` | 字符串 | 是 | - | 终端唯一标识符,用于在策略中引用此终端 | -| `alias` | 字符串 | 否 | `qmt_id` | 终端别名,用于日志和界面显示 | -| `path` | 字符串 | 是 | - | MiniQMT 终端的 userdata_mini 目录路径 | -| `account_id` | 字符串 | 是 | - | 交易账户 ID,通常为券商账号 | -| `account_type` | 字符串 | 是 | - | 账户类型,详见下方的可选值 | - -#### account_type 可选值 - -| 账户类型 | 说明 | -|----------|------| -| `STOCK` | 股票账户(默认) | -| `FUTURES` | 期货账户 | -| `OPTIONS` | 期权账户 | -| `两融` | 融资融券账户 | -| `港股通` | 港股通账户 | - -#### 详细说明 - -- **`qmt_id`**:终端的唯一标识符,建议使用简短的英文标识,如 `gj`(国金证券)、`yh`(银河证券)。此 ID 用于在策略配置中关联到具体的终端。 -- **`alias`**:终端的友好名称,会在日志、仪表盘等界面中显示。建议使用中文券商名称,便于识别。 -- **`path`**:MiniQMT 终端的 `userdata_mini` 目录的绝对路径。此目录包含终端的配置文件和交易数据。注意:路径分隔符在 JSON 中需要使用双反斜杠 `\\` 或使用正斜杠 `/`。 -- **`account_id`**:您的券商交易账号。请确保此账号与 MiniQMT 终端登录的账号一致。 -- **`account_type`**:账户类型决定了可以交易的品种范围。请根据实际账户类型填写。 - -#### 多终端配置示例 - -```json -"qmt_terminals": [ - { - "qmt_id": "gj", - "alias": "国金证券", - "path": "D:\\QMT\\国金证券QMT交易端\\userdata_mini", - "account_id": "12345678", - "account_type": "STOCK" - }, - { - "qmt_id": "yh", - "alias": "银河证券", - "path": "D:\\QMT\\银河证券QMT交易端\\userdata_mini", - "account_id": "87654321", - "account_type": "两融" - } -] -``` - -### 3. 策略配置(strategies) - -`strategies` 是一个对象,用于定义一个或多个交易策略。每个策略有自己的执行参数和关联的 QMT 终端。 - -#### 策略顶级配置 - -| 配置项 | 类型 | 必选 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `qmt_id` | 字符串 | 是 | - | 策略绑定的 QMT 终端 ID,必须在 `qmt_terminals` 中定义 | -| `total_slots` | 整数 | 是 | - | 策略可用的交易仓位总数 | -| `weight` | 整数 | 否 | 1 | 策略权重,用于按权重分配下单金额 | -| `execution` | 对象 | 是 | - | 策略执行参数,详见下方说明 | - -#### execution 执行参数配置 - -| 配置项 | 类型 | 必选 | 默认值 | 说明 | -|--------|------|------|--------|------| -| `buy_drift_pct` | 浮点数 | 是 | - | 买入时价格漂移百分比,用于滑点控制 | -| `sell_drift_fixed` | 浮点数 | 是 | - | 卖出时固定漂移值,用于滑点控制 | -| `max_adjust_limit` | 浮点数 | 是 | - | 最大调仓限制,范围 0-1 表示仓位调整比例上限 | - -#### 详细说明 - -**策略顶级配置** - -- **`qmt_id`**:策略绑定的 QMT 终端标识符。一个策略只能绑定到一个终端,但多个策略可以绑定到同一个终端。 -- **`total_slots`**:策略可用的总仓位数量。例如设为 5 表示策略最多同时持有 5 只股票。此参数用于仓位管理和风险控制。 -- **`weight`**:策略权重,用于按权重分配下单金额。当不配置时,默认为 1,表示等权分配。可用于实现策略间的资金分配比例控制。 -- **`execution`**:包含策略的具体执行参数,这些参数控制订单的提交方式。 - -**执行参数详解** - -- **`buy_drift_pct`**:买入时允许的价格漂移百分比。例如设置为 `0.005`(0.5%)表示买入时允许以高于基准价 0.5% 的价格成交,用于应对行情快速上涨的情况。计算公式为:买入价 = 基准价 × (1 + buy_drift_pct)。 -- **`sell_drift_fixed`**:卖出时的固定漂移值。例如设置为 `-0.01`(-1%)表示卖出时允许以低于基准价 1% 的价格成交,用于应对行情快速下跌的情况。计算公式为:卖出价 = 基准价 × (1 + sell_drift_fixed)。 -- **`max_adjust_limit`**:单次调仓的最大比例限制。例如设置为 `0.05`(5%)表示每次调仓不超过总仓位的 5%。此参数用于控制换手率和交易成本。 - -#### 权重配置示例 - -通过 `weight` 字段可以控制策略间的资金分配比例。下单金额计算公式为: - -**下单金额 = 可用资金 × 策略权重 / Σ(各策略槽位数 × 权重)** - -##### 基础配置(无权重,等权分配) - -不配置 `weight` 时,所有策略默认为权重 1,实现等权分配: - -```json -"strategies": { - "strategy_a": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - }, - "strategy_b": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - } -} -``` - -**计算示例**:A(权重1×5) + B(权重1×5) = 10,可用资金 100 万时,A 和 B 各分配 50 万。 - -##### 加权配置(按权重分配) - -配置 `weight` 字段可以实现差异化的资金分配: - -```json -"strategies": { - "strategy_a": { - "qmt_id": "gj", - "total_slots": 5, - "weight": 1, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - }, - "strategy_b": { - "qmt_id": "gj", - "total_slots": 5, - "weight": 2, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - } -} -``` - -**计算示例**:A(权重1×5) + B(权重2×5) = 15,可用资金 100 万时,A 分配 100×1/15 ≈ 6.67 万,B 分配 100×2/15 ≈ 13.33 万。 - -##### 不同槽位数的加权配置 - -```json -"strategies": { - "conservative_strategy": { - "qmt_id": "gj", - "total_slots": 3, - "weight": 1, - "execution": { - "buy_drift_pct": 0.003, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.03 - } - }, - "aggressive_strategy": { - "qmt_id": "gj", - "total_slots": 8, - "weight": 3, - "execution": { - "buy_drift_pct": 0.008, - "sell_drift_fixed": -0.02, - "max_adjust_limit": 0.1 - } - } -} -``` - -**计算示例**:保守策略(权重1×3) + 激进策略(权重3×8) = 27,可用资金 100 万时,保守策略分配 100×1/27 ≈ 3.7 万,激进策略分配 100×3/27 ≈ 11.1 万。 - -```json -"strategies": { - "ST_Strategy": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.005, - "sell_drift_fixed": -0.01, - "max_adjust_limit": 0.05 - } - }, - "XSZ_Strategy": { - "qmt_id": "gj", - "total_slots": 5, - "execution": { - "buy_drift_pct": 0.003, - "sell_drift_fixed": -0.015, - "max_adjust_limit": 0.03 - } - }, - "FUTURES_Strategy": { - "qmt_id": "yh", - "total_slots": 3, - "execution": { - "buy_drift_pct": 0.002, - "sell_drift_fixed": -0.005, - "max_adjust_limit": 0.1 - } - } -} -``` - -## 配置验证清单 - -在启动 QMT 模块之前,请确保完成以下检查: - -### Redis 配置检查 - -- [ ] `host` 指向正确的 Redis 服务器地址 -- [ ] `port` 与 Redis 服务端口一致 -- [ ] 如果 Redis 启用了密码认证,`password` 已正确设置 -- [ ] 确保 Redis 服务器已启动且可访问 - -### QMT 终端配置检查 - -- [ ] 每个 `qmt_id` 在配置文件中唯一 -- [ ] `path` 指向正确的 `userdata_mini` 目录 -- [ ] `account_id` 与 MiniQMT 终端登录账号一致 -- [ ] `account_type` 与实际账户类型匹配 -- [ ] 确保 MiniQMT 终端已启动并登录成功 - -### 策略配置检查 - -- [ ] 每个策略的 `qmt_id` 已在 `qmt_terminals` 中定义 -- [ ] `total_slots` 设置合理,建议根据资金规模和风险管理需求设置 -- [ ] `buy_drift_pct` 设置合理,通常 0.3%-1% 之间 -- [ ] `sell_drift_fixed` 设置合理,通常 -0.5% 到 -2% 之间 -- [ ] `max_adjust_limit` 设置合理,通常 3%-10% 之间 - -## 常见问题 - -### Q:如何添加新的券商终端? - -A:按照以下步骤操作: -1. 在 MiniQMT 终端中登录您的账户 -2. 复制终端的 `userdata_mini` 目录路径 -3. 在配置文件的 `qmt_terminals` 数组中添加新的终端配置 -4. 保存配置文件后重启 QMT 模块 - -### Q:如何为一个策略绑定多个终端? - -A:当前设计不支持一个策略直接绑定多个终端。如果需要跨券商交易,建议创建多个策略分别绑定不同的终端。 - -### Q:执行参数如何影响交易? - -A: -- `buy_drift_pct` 越大,买入时允许的价格溢价越高,利于快速成交但可能增加滑点成本 -- `sell_drift_fixed` 越负(绝对值越大),卖出时允许的价格折价越高,利于快速成交但可能减少收益 -- `max_adjust_limit` 越小,换手率越低,交易成本降低但灵活性也降低 - -### Q:Redis 连接失败怎么办? - -A:请检查以下几点: -1. Redis 服务是否已启动 -2. `host` 和 `port` 配置是否正确 -3. 防火墙是否允许 Redis 端口访问 -4. 如果设置了密码,`password` 是否正确 - -### Q:如何配置策略的资金分配权重? - -A:通过 `weight` 字段可以配置策略的资金分配权重: -- `weight` 是可选字段,不配置时默认为 1 -- 下单金额计算公式:可用资金 × 策略权重 / Σ(各策略槽位数 × 权重) -- 示例:两个策略,A 的 weight=1、total_slots=5,B 的 weight=2、total_slots=5,则 A 分配 1/(1×5+2×5)=1/15,B 分配 2/(1×5+2×5)=2/15 -- 现有配置无需修改即可兼容,不配置 weight 时按等权分配 - -## 配置文件路径说明 - -配置文件应放置在以下位置之一: - -| 路径 | 说明 | -|------|------| -| `qmt/config.json` | 推荐位置,专门存放 QMT 模块配置 | -| `./config.json` | 项目根目录 | -| 环境变量 `QMT_CONFIG_PATH` 指定的路径 | 通过环境变量自定义配置路径 | - -系统启动时会按上述顺序查找配置文件,找到第一个存在的配置文件后即停止搜索。 - -## 相关文件 - -| 文件 | 路径 | 说明 | -|------|------|------| -| QMT 交易引擎 | `qmt/qmt_trader.py` | 负责与 MiniQMT 终端通信 | -| QMT 引擎核心 | `qmt/qmt_engine.py` | 策略执行引擎 | -| API 服务 | `qmt/api_server.py` | 提供 REST API 接口 | -| 仪表盘 | `qmt/dashboard.html` | 交易状态可视化界面 | diff --git a/qmt/qmt_functionality.md b/qmt/qmt_functionality.md new file mode 100644 index 0000000..d939ecb --- /dev/null +++ b/qmt/qmt_functionality.md @@ -0,0 +1,331 @@ +# QMT 模块功能文档 + +## 1. 系统概述 + +QMT 模块是 NewStock 量化交易系统的实盘交易执行模块,通过 `xtquant` 库连接 QMT 交易终端,实现自动化交易功能。该模块采用多终端架构设计,支持同时管理多个 QMT 终端实例,并提供 Web 仪表盘和 RESTful API 接口进行监控和操作。 + +系统核心特性包括:多终端并行管理、异步订单处理、断线自动重连、收盘自动清算、实时心跳检测等。所有交易信号通过 Redis 消息队列接收,确保交易指令的可靠传递和执行。 + +## 2. 核心组件 + +### 2.1 文件结构 + +| 文件 | 说明 | +|------|------| +| [`run.py`](run.py) | 系统启动入口,负责初始化多终端管理器并启动 API 服务 | +| [`qmt_engine.py`](qmt_engine.py) | 核心引擎模块,包含多终端管理器和交易执行单元 | +| [`qmt_trader.py`](qmt_trader.py) | 旧版单终端交易引擎(保留兼容) | +| [`api_server.py`](api_server.py) | FastAPI Web 服务,提供 RESTful API 接口 | +| [`dashboard.html`](dashboard.html) | Web 仪表盘前端页面 | +| [`start.bat`](start.bat) | Windows 启动脚本 | +| [`logs/`](logs/) | 系统运行日志目录 | + +### 2.2 核心类说明 + +#### qmt_engine.py + +| 类名 | 功能说明 | +|------|----------| +| `MultiEngineManager` | 多终端管理器单例,负责管理所有 QMT 终端实例和交易路由 | +| `TradingUnit` | 终端执行单元,代表单个 QMT 进程的管理器 | +| `PositionManager` | Redis 虚拟持仓管理器,维护策略级别的持仓状态 | +| `DailySettlement` | 日终对账处理器,执行收盘后的持仓核对 | +| `AutoReconnectScheduler` | 定时自动重连调度器,支持配置重连时间和启用状态 | +| `UnitCallback` | 终端回调处理器,处理成交回报和错误通知 | +| `TerminalStatus` | 终端状态数据类,封装终端连接状态信息 | + +#### qmt_trader.py + +| 类名 | 功能说明 | +|------|----------| +| `SystemState` | 全局状态管理器,维护交易系统运行状态 | +| `PositionManager` | 虚拟持仓管理器,管理策略与股票的持仓映射 | +| `DailySettlement` | 日终清算处理器,处理收盘后的撤单和持仓修正 | +| `MyXtQuantTraderCallback` | QMT 交易回调,处理成交和错误事件 | + +## 3. 功能详细说明 + +### 3.1 多终端管理 + +系统支持同时连接和管理多个 QMT 终端实例,每个终端可以配置独立的账户信息。每个 `TradingUnit` 对应一个 QMT 终端,具备独立的连接状态、回调处理和交易能力。终端之间相互隔离,可以通过配置文件定义每个策略使用哪个终端执行交易。 + +多终端管理器的核心职责包括:终端初始化、连接状态监控、健康检查、断线重连、交易消息路由等。主循环每 25 秒执行一次健康检查,通过查询资产验证物理连接有效性。当检测到连接丢失时,系统自动执行重连操作,并避开 QMT 夜间重启高峰期。 + +### 3.2 交易消息处理 + +交易信号通过 Redis 消息队列传递,每个策略对应一个独立的队列。消息格式为 JSON 对象,包含股票代码、操作类型、价格、时间戳等字段。系统对每条消息进行严格校验,包括日期校验、时间戳校验、必填字段校验等,确保只有当天的有效指令才会被执行。 + +买入逻辑支持槽位控制,通过 `total_slots` 参数限制同时持有的股票数量。系统根据可用资金和目标槽位自动计算每只股票的买入数量,金额过小或股数不足的请求会被拦截。卖出逻辑则根据 Redis 中的虚拟持仓和实盘可用持仓计算实际卖出数量,确保不会超卖。 + +### 3.3 持仓管理 + +持仓管理采用虚拟账本与实盘持仓双轨制。虚拟账本记录策略意图持有的股票,通过 Redis Hash 结构存储,使用 `POS:{strategy_name}` 作为键。当策略发出买入指令时,系统先在虚拟账本中标记持仓,再执行实际委托。 + +成交回调会实时更新虚拟持仓数量,买入增加持仓,卖出减少持仓。如果下单失败,系统会自动回滚虚拟持仓的槽位占用。日终结算时会核对虚拟持仓与实盘持仓的差异,发现幽灵持仓或占位符不一致时自动修正。 + +### 3.4 断线重连机制 + +系统实现了三级断线检测和自动重连机制。第一级是回调通知,当 QMT 底层检测到连接断开时触发 `on_disconnected` 回调。第二级是逻辑状态跟踪,系统维护 `callback.is_connected` 标志反映回调状态。第三级是物理探测,通过查询账户资产验证连接是否真正有效。 + +重连策略包含智能避让机制,在每日 21:32 至 21:50 的 QMT 维护时段内不执行重连操作,避免与系统重启冲突。自动重连调度器支持配置定时执行重连任务,可在盘后 22:00 自动断开并重新建立所有连接。 + +### 3.5 日终清算 + +日终清算是系统的重要保障机制,在每个交易日收盘后自动执行。清算流程包括三个步骤:首先撤销所有可撤单订单,释放未成交的委托;然后查询实盘真实持仓,建立持仓映射;最后遍历所有策略的虚拟持仓,与实盘进行比对和修正。 + +清算过程中发现的异常情况包括:幽灵持仓(Redis 有记录但实盘无持仓)和占位符不一致(Redis 记录为 0 但实盘有持仓)。这些异常会被自动修正,确保系统状态与实际账户一致。清算完成后设置标志位,防止重复执行。 + +### 3.6 日志系统 + +系统采用增强型日志系统,支持文件和控制台双路输出。日志格式包含时间戳、线程名、级别和消息内容,便于追踪问题。文件日志按日期命名,自动存放在 `logs/` 目录下。控制台输出强制刷新流,确保在 Windows 环境下日志实时显示。 + +日志级别分为 INFO、WARNING、ERROR 三级,重要操作和状态变化都会记录。交易相关日志特别标注策略名称和股票代码,方便后续分析和审计。 + +## 4. API 接口列表 + +### 4.1 端点列表 + +| 方法 | 路径 | 功能说明 | +|------|------|----------| +| GET | `/` | 返回 Web 仪表盘页面 | +| GET | [`/api/status`](api_server.py:154) | 获取所有终端的连接状态 | +| GET | [`/api/positions`](api_server.py:177) | 获取实盘持仓和虚拟持仓 | +| GET | [`/api/logs`](api_server.py:234) | 获取系统运行日志 | +| GET | [`/api/health`](api_server.py:240) | 健康检查接口 | +| GET | [`/api/config`](api_server.py:251) | 获取自动重连配置 | +| POST | [`/api/config`](api_server.py:260) | 更新自动重连配置 | +| POST | [`/api/reconnect`](api_server.py:279) | 手动触发所有终端重连 | +| GET | [`/api/file_config`](api_server.py:288) | 获取配置文件内容(敏感信息脱敏) | + +### 4.2 响应模型 + +#### StatusResponse + +```json +{ + "running": true, + "start_time": "2026-01-27 10:00:00", + "terminals": [ + { + "qmt_id": "terminal_001", + "alias": "主账户", + "account_id": "****1234", + "is_connected": true, + "callback_connected": true, + "physical_connected": true, + "last_heartbeat": "10:30:15" + } + ] +} +``` + +#### PositionsResponse + +```json +{ + "real_positions": { + "terminal_001": [ + {"code": "600519", "volume": 1000, "can_use": 500, "market_value": 850000.00} + ] + }, + "virtual_positions": { + "strategy_a": {"600519": "500", "000001": "1000"} + } +} +``` + +#### ConfigResponse + +```json +{ + "reconnect_time": "22:00", + "auto_reconnect_enabled": true +} +``` + +## 5. 配置说明 + +### 5.1 配置文件结构 + +系统使用 `config.json` 作为主配置文件,文件结构如下: + +```json +{ + "redis": { + "host": "localhost", + "port": 6379, + "db": 0, + "password": null + }, + "qmt_terminals": [ + { + "qmt_id": "terminal_001", + "alias": "主账户", + "path": "C:/QMT/xiadan/", + "account_id": "12345678", + "account_type": "STOCK" + } + ], + "strategies": { + "strategy_a": { + "qmt_id": "terminal_001", + "total_slots": 5, + "execution": { + "buy_amount_per_stock": 20000, + "min_buy_amount": 2000 + } + } + }, + "auto_reconnect": { + "enabled": true, + "reconnect_time": "22:00" + } +} +``` + +### 5.2 配置项说明 + +| 配置项 | 类型 | 说明 | +|--------|------|------| +| `redis` | Object | Redis 连接配置,支持 host、port、db、password 等参数 | +| `qmt_terminals` | Array | QMT 终端列表,每个终端包含唯一标识、别名、路径、账户信息 | +| `strategies` | Object | 策略配置,键为策略名,值包含使用的终端 ID 和执行参数 | +| `total_slots` | Integer | 策略的最大持仓股票数量 | +| `auto_reconnect` | Object | 自动重连配置,包含启用状态和执行时间 | + +## 6. Web 仪表盘功能 + +### 6.1 功能概览 + +Web 仪表盘基于 Vue 3 和 Naive UI 组件库开发,提供可视化的系统监控界面。仪表盘支持暗黑主题,采用卡片式布局展示各类信息。页面每 30 秒自动刷新,也支持手动点击刷新按钮获取最新数据。 + +### 6.2 功能模块 + +| 模块 | 功能说明 | +|------|----------| +| 顶部状态栏 | 显示系统运行状态总览,提供配置查看、重连、刷新按钮 | +| 终端状态卡片 | 展示每个 QMT 终端的连接状态、账户信息、心跳时间 | +| 持仓统计卡片 | 显示持仓品种数、总持仓量、总市值、策略数 | +| 实盘持仓面板 | 按终端分组展示真实持仓,包含代码、持仓量、可用量、市值 | +| 虚拟账本面板 | 按策略分组展示 Redis 持仓记录 | +| 系统日志面板 | 实时滚动显示系统运行日志,按级别着色 | +| 配置查看模态框 | 展示 Redis 配置、终端配置、策略配置,支持复制 JSON 源码 | + +### 6.3 访问地址 + +仪表盘默认访问地址为 `http://localhost:8001`,该地址在系统启动时打印在控制台。首次访问时会自动加载所有终端状态、持仓信息和系统日志。 + +## 7. 系统架构 + +### 7.1 组件关系图 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ QMT 交易系统架构 │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ +│ │ 启动入口 │ │ 多终端管理器 │ │ API 服务器 │ │ +│ │ run.py │ ──> │ MultiEngineMgr │ <──> │ FastAPI + uvicorn │ │ +│ └─────────────┘ │ │ │ │ │ +│ └────────┬────────┘ └───────────┬─────────────┘ │ +│ │ │ │ +│ ┌──────────────────────┼──────────────────────────┤ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ +│ │ 日志系统 │ │ 终端执行单元 │ │ Web 仪表盘 │ │ +│ │ logs/ │ │ TradingUnit │ │ dashboard.html │ │ +│ └─────────────┘ │ × N │ │ │ │ +│ └────────┬────────┘ └─────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ QMT 终端 │ │ +│ │ xtquant 连接 │ │ +│ └─────────────────┘ │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ 外部依赖 │ +│ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ +│ │ Redis │ │ QMT 终端 │ │ 浏览器客户端 │ │ +│ │ 消息队列 │ │ 实盘交易 │ │ HTTP 请求 │ │ +│ └─────────────┘ └─────────────────┘ └─────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 7.2 数据流向图 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ 数据流向 │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 策略信号 ──> Redis 队列 ──> 消息处理循环 ──> 槽位检查 ──> 资金检查 │ +│ │ │ +│ ▼ │ +│ 订单执行 (QMT API) │ +│ │ │ +│ ┌───────────────────────┼───────────────────────┐ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ 成交回调处理 错误回调处理 持仓更新 (Redis) │ +│ │ │ │ │ +│ └───────────────────────┴───────────────────────┘ │ +│ │ │ +│ ▼ │ +│ 日终清算 / 状态同步 │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ 监控数据流向 │ +│ │ +│ 系统状态 ──> API 端点 ──> JSON 响应 ──> Web 仪表盘渲染 │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 7.3 消息处理流程 + +1. **消息接收**:系统从 Redis 队列 `{strategy_name}_real` 中取出消息 +2. **消息解析**:将 JSON 消息解析为结构化数据,验证必填字段 +3. **日期校验**:检查消息日期是否为当天,过期消息丢弃 +4. **槽位检查**:查询策略已占用槽位,判断是否允许新买入 +5. **资金检查**:查询账户可用资金,计算单只股票可买入金额 +6. **数量计算**:根据资金和价格计算买入股数(向下取整为百股) +7. **订单执行**:调用 QMT API 下单,成功则缓存订单信息 +8. **状态更新**:标记虚拟持仓,异步等待成交回调 + +## 8. 启动与停止 + +### 8.1 Windows 启动 + +使用提供的 `start.bat` 脚本启动系统: + +```batch +start.bat +``` + +或手动启动: + +```bash +cd qmt +python run.py +``` + +### 8.2 日志文件位置 + +系统日志保存在 `qmt/logs/{日期}.log` 目录下,文件名格式为 `2026-01-27.log`。日志按日期自动切分,当日期变化时创建新的日志文件。 + +### 8.3 端口说明 + +| 服务 | 默认端口 | 说明 | +|------|----------|------| +| API 服务 | 8001 | Web 仪表盘和 RESTful API 监听端口 | + +## 9. 注意事项 + +1. **QMT 终端要求**:确保 QMT 终端已登录且路径配置正确 +2. **Redis 服务**:系统依赖 Redis 运行,请确保 Redis 服务可用 +3. **交易日时间**:交易逻辑仅在 09:15-11:30 和 13:00-15:00 期间执行 +4. **维护时段**:每日 21:32-21:50 为 QMT 维护时段,此时段不执行重连 +5. **权限要求**:确保程序有权限写入 `logs/` 目录 diff --git a/qmt/start.bat b/qmt/start.bat index bced865..907c52d 100644 --- a/qmt/start.bat +++ b/qmt/start.bat @@ -20,13 +20,31 @@ set MAX_RETRIES=10 set RETRY_COUNT=0 set RETRY_WAIT=10 -:: 6. 日志目录 (仅在 SHOW_OUTPUT=0 时生效) +:: 6. 是否使用 Conda 环境 (1=是, 0=否) +set USE_CONDA=0 + +:: 7. 日志目录 (仅在 SHOW_OUTPUT=0 时生效) set "LOG_DIR=%WORK_DIR%logs\launcher" :: =========================================== +:: 解析命令行参数 +:PARSE_ARGS +if "%~1"=="" goto :END_ARGS +if /i "%~1"=="--conda" set USE_CONDA=1 +if /i "%~1"=="-c" set USE_CONDA=1 +shift +goto :PARSE_ARGS +:END_ARGS + cd /d "%WORK_DIR%" title QMT 自动化交易系统 [准备中] +:: 激活 Conda 环境 +if "%USE_CONDA%"=="1" ( + echo [%time%] 正在激活 Conda 环境 [stock]... + call conda activate stock +) + :: 构建启动命令前缀 if "%USE_UV%"=="1" ( set "CMD_PREFIX=uv run python"