Compare commits

...

2 Commits

Author SHA1 Message Date
e407225d29 feat(qmt): 优化定时重连机制避免与健康检查冲突
- 添加 is_scheduled_reconnecting 标志位协调重连逻辑
- 增强定时重连任务的日志前缀便于追踪
- 改进异常处理和资源清理日志
- 优化代码格式和注释
2026-02-09 22:12:14 +08:00
7ae3d16a5e feat: start脚本支持 conda activate stock 2026-01-28 00:22:01 +08:00
17 changed files with 1383 additions and 1058 deletions

View File

@@ -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) - 读取限制规则

View File

@@ -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) - 代码格式化规则

View File

@@ -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/ # 因子计算模块

View File

@@ -83,32 +83,32 @@
"output_type": "stream",
"text": [
" ts_code trade_date close open high low \\\n",
"0 000905.SH 20260123 8590.1659 8422.3561 8590.1659 8417.7520 \n",
"1 000905.SH 20260122 8387.5950 8355.6781 8396.1328 8337.1950 \n",
"2 000905.SH 20260121 8340.1133 8196.5565 8351.4545 8196.5565 \n",
"3 000905.SH 20260120 8247.8049 8307.6416 8342.8738 8142.1424 \n",
"4 000905.SH 20260119 8287.9470 8199.4986 8318.3703 8195.0890 \n",
"0 000905.SH 20260206 8146.4128 8054.2180 8247.2968 8014.6599 \n",
"1 000905.SH 20260205 8146.1073 8203.0627 8224.7847 8081.4283 \n",
"2 000905.SH 20260204 8299.0574 8270.8420 8309.8579 8179.3522 \n",
"3 000905.SH 20260203 8286.7005 8135.8699 8286.7005 8075.3738 \n",
"4 000905.SH 20260202 8037.0456 8279.7152 8324.4341 8032.3500 \n",
"... ... ... ... ... ... ... \n",
"14029 399006.SZ 20100607 1069.4680 1005.0280 1075.2250 1001.7020 \n",
"14030 399006.SZ 20100604 1027.6810 989.6810 1027.6810 986.5040 \n",
"14031 399006.SZ 20100603 998.3940 1002.3550 1026.7020 997.7750 \n",
"14032 399006.SZ 20100602 997.1190 967.6090 997.1190 952.6110 \n",
"14033 399006.SZ 20100601 973.2330 986.0150 994.7930 948.1180 \n",
"14059 399006.SZ 20100607 1069.4680 1005.0280 1075.2250 1001.7020 \n",
"14060 399006.SZ 20100604 1027.6810 989.6810 1027.6810 986.5040 \n",
"14061 399006.SZ 20100603 998.3940 1002.3550 1026.7020 997.7750 \n",
"14062 399006.SZ 20100602 997.1190 967.6090 997.1190 952.6110 \n",
"14063 399006.SZ 20100601 973.2330 986.0150 994.7930 948.1180 \n",
"\n",
" pre_close change pct_chg vol amount \n",
"0 8387.5950 202.5709 2.4151 3.196901e+08 6.394214e+08 \n",
"1 8340.1133 47.4817 0.5693 2.688052e+08 5.461381e+08 \n",
"2 8247.8049 92.3084 1.1192 2.433044e+08 5.175922e+08 \n",
"3 8287.9470 -40.1421 -0.4843 2.898645e+08 5.881715e+08 \n",
"4 8232.6740 55.2730 0.6714 2.614974e+08 5.609261e+08 \n",
"0 8146.1073 0.3055 0.0038 2.186421e+08 4.183734e+08 \n",
"1 8299.0574 -152.9501 -1.8430 2.318405e+08 4.352777e+08 \n",
"2 8286.7005 12.3569 0.1491 2.688603e+08 5.018867e+08 \n",
"3 8037.0456 249.6549 3.1063 2.722271e+08 5.432645e+08 \n",
"4 8370.5203 -333.4747 -3.9839 2.996460e+08 5.460557e+08 \n",
"... ... ... ... ... ... \n",
"14029 1027.6810 41.7870 4.0661 2.655275e+06 9.106095e+06 \n",
"14030 998.3940 29.2870 2.9334 1.500295e+06 5.269441e+06 \n",
"14031 997.1190 1.2750 0.1279 1.616805e+06 6.240835e+06 \n",
"14032 973.2330 23.8860 2.4543 1.074628e+06 4.001206e+06 \n",
"14033 1000.0000 -26.7670 -2.6767 1.356285e+06 4.924177e+06 \n",
"14059 1027.6810 41.7870 4.0661 2.655275e+06 9.106095e+06 \n",
"14060 998.3940 29.2870 2.9334 1.500295e+06 5.269441e+06 \n",
"14061 997.1190 1.2750 0.1279 1.616805e+06 6.240835e+06 \n",
"14062 973.2330 23.8860 2.4543 1.074628e+06 4.001206e+06 \n",
"14063 1000.0000 -26.7670 -2.6767 1.356285e+06 4.924177e+06 \n",
"\n",
"[14034 rows x 11 columns]\n"
"[14064 rows x 11 columns]\n"
]
}
],

View File

@@ -6,8 +6,8 @@
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2025-10-17T07:14:47.275Z",
"start_time": "2025-10-17T07:14:46.966401Z"
"end_time": "2026-01-30T19:47:50.093496Z",
"start_time": "2026-01-30T19:47:49.972697Z"
}
},
"source": [
@@ -20,13 +20,25 @@
"ts.set_token('3a0741c702ee7e5e5f2bf1f0846bafaafe4e320833240b2a7e4a685f')\n",
"pro = ts.pro_api()"
],
"outputs": [],
"outputs": [
{
"ename": "ModuleNotFoundError",
"evalue": "No module named 'tushare'",
"output_type": "error",
"traceback": [
"\u001B[31m---------------------------------------------------------------------------\u001B[39m",
"\u001B[31mModuleNotFoundError\u001B[39m Traceback (most recent call last)",
"\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[1]\u001B[39m\u001B[32m, line 3\u001B[39m\n\u001B[32m 1\u001B[39m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01moperator\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m index\n\u001B[32m----> \u001B[39m\u001B[32m3\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mtushare\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mts\u001B[39;00m\n\u001B[32m 4\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mpandas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mas\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mpd\u001B[39;00m\n\u001B[32m 5\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mtime\u001B[39;00m\n",
"\u001B[31mModuleNotFoundError\u001B[39m: No module named 'tushare'"
]
}
],
"execution_count": 1
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-10-17T07:15:47.631705Z",
"end_time": "2026-01-30T19:47:50.172803200Z",
"start_time": "2025-10-17T07:15:47.491485Z"
}
},

View File

@@ -39,15 +39,15 @@
"3 000006.SZ 20250312\n",
"4 000007.SZ 20250312\n",
"... ... ...\n",
"27277 920978.BJ 20260112\n",
"27278 920981.BJ 20260112\n",
"27279 920982.BJ 20260112\n",
"27280 920985.BJ 20260112\n",
"27281 920992.BJ 20260112\n",
"27312 920978.BJ 20260126\n",
"27313 920981.BJ 20260126\n",
"27314 920982.BJ 20260126\n",
"27315 920985.BJ 20260126\n",
"27316 920992.BJ 20260126\n",
"\n",
"[8597722 rows x 2 columns]\n",
"20260116\n",
"start_date: 20260119\n"
"[8652365 rows x 2 columns]\n",
"20260130\n",
"start_date: 20260202\n"
]
}
],
@@ -64,7 +64,7 @@
" max_date = df['trade_date'].max()\n",
"\n",
"print(max_date)\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260201')\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260310')\n",
"trade_cal = trade_cal[trade_cal['is_open'] == 1] # 只保留交易日\n",
"trade_dates = trade_cal[trade_cal['cal_date'] > max_date]['cal_date'].tolist()\n",
"start_date = min(trade_dates)\n",
@@ -86,16 +86,27 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260130 完成\n",
"任务 20260129 完成\n",
"任务 20260128 完成\n",
"任务 20260127 完成\n",
"任务 20260126 完成\n",
"任务 20260123 完成\n",
"任务 20260122 完成\n",
"任务 20260121 完成\n",
"任务 20260120 完成\n",
"任务 20260119 完成\n"
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260304 完成\n",
"任务 20260303 完成\n",
"任务 20260227 完成\n",
"任务 20260302 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260209 完成\n",
"任务 20260210 完成\n",
"任务 20260205 完成\n",
"任务 20260206 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
]
}
],

View File

@@ -39,15 +39,15 @@
"3 801005.SI 20250221\n",
"4 801010.SI 20250221\n",
"... ... ...\n",
"2190 859811.SI 20260112\n",
"2191 859821.SI 20260112\n",
"2192 859822.SI 20260112\n",
"2193 859852.SI 20260112\n",
"2194 859951.SI 20260112\n",
"2190 859811.SI 20260126\n",
"2191 859821.SI 20260126\n",
"2192 859822.SI 20260126\n",
"2193 859852.SI 20260126\n",
"2194 859951.SI 20260126\n",
"\n",
"[1140973 rows x 2 columns]\n",
"20260116\n",
"start_date: 20260119\n"
"[1145363 rows x 2 columns]\n",
"20260130\n",
"start_date: 20260202\n"
]
}
],
@@ -64,7 +64,7 @@
" max_date = df['trade_date'].max()\n",
"\n",
"print(max_date)\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260201')\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260310')\n",
"trade_cal = trade_cal[trade_cal['is_open'] == 1] # 只保留交易日\n",
"trade_dates = trade_cal[trade_cal['cal_date'] > max_date]['cal_date'].tolist()\n",
"start_date = min(trade_dates)\n",
@@ -86,16 +86,27 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260130 完成\n",
"任务 20260129 完成\n",
"任务 20260128 完成\n",
"任务 20260127 完成\n",
"任务 20260126 完成\n",
"任务 20260123 完成\n",
"任务 20260122 完成\n",
"任务 20260121 完成\n",
"任务 20260120 完成\n",
"任务 20260119 完成\n"
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260304 完成\n",
"任务 20260303 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260211 完成\n",
"任务 20260212 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
]
}
],

View File

@@ -94,17 +94,17 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9547667 entries, 0 to 27281\n",
"Index: 9602310 entries, 0 to 27316\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 218.5+ MB\n",
"memory usage: 219.8+ MB\n",
"None\n",
"20260116\n",
"20260119\n"
"20260130\n",
"20260202\n"
]
}
],
@@ -121,7 +121,7 @@
" max_date = df['trade_date'].max()\n",
"\n",
"print(max_date)\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260201')\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260310')\n",
"trade_cal = trade_cal[trade_cal['is_open'] == 1] # 只保留交易日\n",
"trade_dates = trade_cal[trade_cal['cal_date'] > max_date]['cal_date'].tolist()\n",
"start_date = min(trade_dates)\n",
@@ -144,22 +144,27 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260130 完成\n",
"任务 20260129 完成\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260127 完成\n",
"任务 20260128 完成\n",
"任务 20260126 完成\n",
"任务 20260123 完成\n",
"任务 20260122 完成\n",
"任务 20260121 完成\n",
"任务 20260120 完成\n",
"任务 20260119 完成\n"
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260305 完成\n",
"任务 20260306 完成\n",
"任务 20260303 完成\n",
"任务 20260304 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
]
}
],
@@ -230,58 +235,58 @@
"output_type": "stream",
"text": [
" ts_code trade_date close turnover_rate turnover_rate_f \\\n",
"0 301586.SZ 20260123 52.80 4.4195 6.0484 \n",
"1 600871.SH 20260123 2.63 3.5599 17.1067 \n",
"2 002067.SZ 20260123 5.91 9.5542 9.8833 \n",
"3 601225.SH 20260123 21.41 0.4692 1.3502 \n",
"4 688800.SH 20260123 90.22 4.3421 7.2546 \n",
"0 001389.SZ 20260206 99.50 6.1259 6.1259 \n",
"1 600841.SH 20260206 9.55 4.4177 14.0519 \n",
"2 300968.SZ 20260206 13.71 1.0258 2.1909 \n",
"3 300634.SZ 20260206 28.46 4.0862 6.8510 \n",
"4 300295.SZ 20260206 11.99 3.5950 3.8451 \n",
"... ... ... ... ... ... \n",
"27321 688659.SH 20260119 10.42 1.7256 3.1386 \n",
"27322 301021.SZ 20260119 55.92 5.8451 10.3979 \n",
"27323 300102.SZ 20260119 34.23 14.1090 22.0304 \n",
"27324 300088.SZ 20260119 6.36 1.9148 2.3308 \n",
"27325 002261.SZ 20260119 33.77 4.6567 5.1897 \n",
"27325 603766.SH 20260202 14.89 1.1630 1.9407 \n",
"27326 603408.SH 20260202 12.92 0.7963 3.0049 \n",
"27327 000004.SZ 20260202 11.99 0.2338 0.3161 \n",
"27328 601628.SH 20260202 48.34 0.1384 1.9210 \n",
"27329 301042.SZ 20260202 86.10 3.6207 5.4797 \n",
"\n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio \\\n",
"0 0.98 43.6343 68.1615 3.4308 6.9893 5.8003 0.9091 \n",
"1 1.91 78.9369 79.8327 5.2226 0.6148 0.6127 NaN \n",
"2 0.80 122.3105 140.3743 1.3170 1.5908 1.5491 NaN \n",
"3 1.02 9.2832 10.8507 2.1981 1.1272 1.1740 5.9699 \n",
"4 0.79 105.8709 61.3816 8.0916 7.6847 5.8974 0.2971 \n",
"0 0.83 62.6474 46.6770 11.6304 11.3424 8.6639 0.4819 \n",
"1 1.02 NaN NaN 4.1908 2.0493 2.4531 NaN \n",
"2 0.80 106.8945 225.1215 2.9871 4.6434 4.4246 0.3647 \n",
"3 0.68 55.7987 55.5119 4.4068 7.7725 7.2020 0.5590 \n",
"4 0.40 NaN NaN 2.0169 18.5210 23.1598 NaN \n",
"... ... ... ... ... ... ... ... \n",
"27321 1.01 NaN NaN 3.1071 2.6478 2.4387 NaN \n",
"27322 0.72 391.5181 198.4990 8.4757 19.1357 17.1491 0.1772 \n",
"27323 0.69 327.8681 232.9793 7.4375 12.9485 9.5346 0.1313 \n",
"27324 0.52 44.5231 45.4726 1.8179 1.4366 1.3961 0.9198 \n",
"27325 0.38 NaN NaN 16.3185 10.3586 13.1287 NaN \n",
"27325 1.04 27.2701 16.9932 3.2106 1.8177 1.5958 2.6864 \n",
"27326 0.99 11.9989 13.3289 1.7275 1.1550 1.1674 3.8700 \n",
"27327 0.05 NaN NaN 42.9590 16.0879 21.5107 NaN \n",
"27328 0.95 12.7771 8.0270 2.2069 2.5849 2.1373 1.4233 \n",
"27329 1.92 84.1572 534.3244 5.7108 8.6920 12.7424 NaN \n",
"\n",
" dv_ttm total_share float_share free_share total_mv \\\n",
"0 0.3788 8.297550e+03 5.291107e+03 3866.1069 4.381107e+05 \n",
"1 NaN 1.895705e+06 1.354701e+06 281911.5987 4.985703e+06 \n",
"2 NaN 1.474854e+05 1.337604e+05 129305.3853 8.716386e+05 \n",
"3 5.4881 9.695000e+05 9.695000e+05 336903.9335 2.075700e+07 \n",
"4 0.2971 2.056743e+04 2.056743e+04 12310.0935 1.855594e+06 \n",
"0 0.4819 4.256875e+04 1.511580e+04 15115.7957 4.235591e+06 \n",
"1 NaN 1.387822e+05 1.043024e+05 32790.9410 1.325370e+06 \n",
"2 0.3647 4.133800e+04 4.133800e+04 19355.6537 5.667440e+05 \n",
"3 0.5590 4.512109e+04 4.345735e+04 25919.5274 1.284146e+06 \n",
"4 NaN 1.896137e+04 1.675259e+04 15662.9042 2.273468e+05 \n",
"... ... ... ... ... ... \n",
"27321 NaN 1.600000e+04 1.600000e+04 8796.6880 1.667200e+05 \n",
"27322 0.1772 1.528528e+04 1.527393e+04 8586.0802 8.547528e+05 \n",
"27323 0.1313 9.203339e+04 9.163399e+04 58685.2206 3.150303e+06 \n",
"27324 0.9198 2.497734e+05 2.485504e+05 204186.7350 1.588559e+06 \n",
"27325 NaN 1.259831e+05 1.145652e+05 102798.2760 4.254451e+06 \n",
"27325 4.0296 2.053542e+05 2.053542e+05 123065.9980 3.057724e+06 \n",
"27326 5.3406 4.475730e+04 4.475730e+04 11860.1633 5.782643e+05 \n",
"27327 NaN 1.323803e+04 1.262878e+04 9339.3580 1.587240e+05 \n",
"27328 1.4233 2.826470e+06 2.082353e+06 150000.0000 1.366316e+08 \n",
"27329 NaN 6.972358e+03 6.602083e+03 4362.2827 6.003200e+05 \n",
"\n",
" circ_mv is_st \n",
"0 2.793704e+05 False \n",
"1 3.562864e+06 False \n",
"2 7.905239e+05 False \n",
"3 2.075700e+07 False \n",
"4 1.855594e+06 False \n",
"0 1.504022e+06 False \n",
"1 9.960884e+05 False \n",
"2 5.667440e+05 False \n",
"3 1.236796e+06 False \n",
"4 2.008635e+05 False \n",
"... ... ... \n",
"27321 1.667200e+05 False \n",
"27322 8.541180e+05 False \n",
"27323 3.136631e+06 False \n",
"27324 1.580780e+06 False \n",
"27325 3.868868e+06 False \n",
"27325 3.057724e+06 False \n",
"27326 5.782643e+05 False \n",
"27327 1.514190e+05 True \n",
"27328 1.006609e+08 False \n",
"27329 5.684393e+05 False \n",
"\n",
"[27326 rows x 19 columns]\n"
"[27330 rows x 19 columns]\n"
]
}
],
@@ -306,58 +311,45 @@
"output_type": "stream",
"text": [
" ts_code trade_date close turnover_rate turnover_rate_f \\\n",
"54 000615.SZ 20260123 3.32 0.7420 0.9114 \n",
"60 600228.SH 20260123 5.63 3.4275 4.8943 \n",
"88 000430.SZ 20260123 7.30 1.4748 2.3665 \n",
"96 603389.SH 20260123 48.20 0.8319 2.1042 \n",
"110 000752.SZ 20260123 10.96 1.4753 1.8177 \n",
"52 002713.SZ 20260206 9.52 4.6530 6.2693 \n",
"107 000609.SZ 20260206 8.23 0.2427 0.3213 \n",
"113 300052.SZ 20260206 13.86 3.5983 4.3260 \n",
"116 600624.SH 20260206 5.31 0.6260 0.8827 \n",
"119 300555.SZ 20260206 14.31 1.4520 1.7474 \n",
"... ... ... ... ... ... \n",
"27130 002586.SZ 20260119 4.68 1.7164 2.9874 \n",
"27154 600265.SH 20260119 19.29 0.2879 0.8066 \n",
"27193 688287.SH 20260119 6.44 0.9802 1.9881 \n",
"27195 300338.SZ 20260119 3.61 1.4127 1.5675 \n",
"27223 000669.SZ 20260119 2.79 1.1437 1.4424 \n",
"27182 000668.SZ 20260202 13.85 3.5014 5.9253 \n",
"27240 003032.SZ 20260202 6.37 2.2066 3.1223 \n",
"27305 000691.SZ 20260202 8.30 1.9108 2.2317 \n",
"27312 300167.SZ 20260202 4.65 2.1705 2.3552 \n",
"27327 000004.SZ 20260202 11.99 0.2338 0.3161 \n",
"\n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio \\\n",
"54 0.72 NaN NaN NaN 5.4217 5.8063 NaN \n",
"60 1.60 NaN NaN 5.6813 9.6204 6.3997 NaN \n",
"88 1.11 NaN NaN 22.0731 13.6938 12.9047 NaN \n",
"96 0.95 NaN NaN 54.1434 62.5718 60.6578 NaN \n",
"110 0.96 110.3513 19.6504 4.7026 6.8589 6.4652 NaN \n",
"... ... ... ... ... ... ... ... \n",
"27130 1.55 NaN NaN 1.7970 2.1568 2.2158 NaN \n",
"27154 0.79 NaN NaN 288.1848 5.6010 10.1170 NaN \n",
"27193 0.59 NaN NaN 3.1120 26.5172 26.3673 NaN \n",
"27195 0.58 NaN NaN NaN 8.5110 10.1280 NaN \n",
"27223 0.84 NaN NaN NaN 1.4522 1.5001 NaN \n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio dv_ttm \\\n",
"52 1.02 NaN NaN NaN 6.9890 12.8336 NaN NaN \n",
"107 0.05 NaN NaN NaN 8.0655 15.8232 NaN NaN \n",
"113 1.51 NaN NaN 9.6004 15.9784 18.8191 NaN NaN \n",
"116 0.60 NaN NaN 5.7984 5.5900 5.4551 NaN NaN \n",
"119 1.24 NaN NaN 6.0224 16.1604 18.5602 NaN NaN \n",
"... ... .. ... ... ... ... ... ... \n",
"27182 1.32 NaN NaN 2.8792 15.2387 7.2708 NaN NaN \n",
"27240 1.15 NaN NaN 2.0451 10.4354 7.6772 NaN NaN \n",
"27305 0.69 NaN NaN NaN 9.0850 9.0002 NaN NaN \n",
"27312 0.71 NaN 134.128 63.0032 4.3517 3.8269 NaN NaN \n",
"27327 0.05 NaN NaN 42.9590 16.0879 21.5107 NaN NaN \n",
"\n",
" dv_ttm total_share float_share free_share total_mv \\\n",
"54 NaN 178749.2693 92531.6398 75331.7788 5.934476e+05 \n",
"60 NaN 41667.2427 41603.7177 29135.5053 2.345866e+05 \n",
"88 NaN 80963.5372 37055.6486 23092.8156 5.910338e+05 \n",
"96 NaN 26275.2000 26275.2000 10387.7487 1.266465e+06 \n",
"110 NaN 26375.8491 26375.8491 21407.3042 2.890793e+05 \n",
"... ... ... ... ... ... \n",
"27130 NaN 114422.3714 108751.8003 62484.0799 5.354967e+05 \n",
"27154 NaN 12980.0000 12980.0000 4633.1947 2.503842e+05 \n",
"27193 NaN 37051.5600 37051.5600 18267.2898 2.386120e+05 \n",
"27195 NaN 40262.4692 34936.1242 31485.3582 1.453475e+05 \n",
"27223 NaN 68040.8797 68040.8797 53950.9653 1.898341e+05 \n",
" total_share float_share free_share total_mv circ_mv is_st \n",
"52 95140.5184 52650.0831 39075.6229 905737.7352 501228.7911 True \n",
"107 29926.5522 29105.8272 21991.3472 246295.5246 239540.9579 True \n",
"113 26185.8710 26185.1210 21780.6332 362936.1721 362925.7771 True \n",
"116 67934.6942 67934.6942 48180.1806 360733.2262 360733.2262 True \n",
"119 20000.0000 19798.4863 16450.7792 286200.0000 283316.3390 True \n",
"... ... ... ... ... ... ... \n",
"27182 14684.1890 14684.1890 8677.2104 203376.0177 203376.0177 True \n",
"27240 40244.7500 27621.9885 19520.7308 256359.0575 175952.0667 True \n",
"27305 48490.5000 32327.0000 27679.8405 402471.1500 268314.1000 True \n",
"27312 38937.4000 35889.3250 33073.6637 181058.9100 166885.3613 True \n",
"27327 13238.0282 12628.7768 9339.3580 158723.9581 151419.0338 True \n",
"\n",
" circ_mv is_st \n",
"54 3.072050e+05 True \n",
"60 2.342289e+05 True \n",
"88 2.705062e+05 True \n",
"96 1.266465e+06 True \n",
"110 2.890793e+05 True \n",
"... ... ... \n",
"27130 5.089584e+05 True \n",
"27154 2.503842e+05 True \n",
"27193 2.386120e+05 True \n",
"27195 1.261194e+05 True \n",
"27223 1.898341e+05 True \n",
"\n",
"[886 rows x 19 columns]\n"
"[872 rows x 19 columns]\n"
]
}
],
@@ -407,7 +399,7 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9574993 entries, 0 to 27325\n",
"Index: 9629640 entries, 0 to 27329\n",
"Data columns (total 3 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -415,7 +407,7 @@
" 1 trade_date object\n",
" 2 is_st bool \n",
"dtypes: bool(1), object(2)\n",
"memory usage: 228.3+ MB\n",
"memory usage: 229.6+ MB\n",
"None\n"
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,17 +34,17 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9336127 entries, 0 to 25845\n",
"Index: 9387872 entries, 0 to 25863\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 213.7+ MB\n",
"memory usage: 214.9+ MB\n",
"None\n",
"20260116\n",
"start_date: 20260119\n"
"20260130\n",
"start_date: 20260202\n"
]
}
],
@@ -61,7 +61,7 @@
" max_date = df['trade_date'].max()\n",
"\n",
"print(max_date)\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260201')\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260310')\n",
"trade_cal = trade_cal[trade_cal['is_open'] == 1] # 只保留交易日\n",
"trade_dates = trade_cal[trade_cal['cal_date'] > max_date]['cal_date'].tolist()\n",
"start_date = min(trade_dates)\n",
@@ -84,16 +84,27 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260129 完成\n",
"任务 20260130 完成\n",
"任务 20260128 完成\n",
"任务 20260127 完成\n",
"任务 20260126 完成\n",
"任务 20260123 完成\n",
"任务 20260122 完成\n",
"任务 20260121 完成\n",
"任务 20260120 完成\n",
"任务 20260119 完成\n"
"任务 20260310 完成\n",
"任务 20260309 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260304 完成\n",
"任务 20260303 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
]
}
],
@@ -183,71 +194,71 @@
"output_type": "stream",
"text": [
" ts_code trade_date buy_sm_vol buy_sm_amount sell_sm_vol \\\n",
"0 300284.SZ 20260123 57213 4682.01 45561 \n",
"1 002835.SZ 20260123 10930 1886.39 9809 \n",
"2 603175.SH 20260123 28945 21106.65 29993 \n",
"3 600284.SH 20260123 62561 5324.31 55101 \n",
"4 300855.SZ 20260123 41944 15903.55 33566 \n",
"0 002397.SZ 20260206 143016 6566.04 142640 \n",
"1 603882.SH 20260206 32234 10009.25 31819 \n",
"2 002824.SZ 20260206 58407 13856.33 47164 \n",
"3 603379.SH 20260206 31545 21744.99 30955 \n",
"4 600223.SH 20260206 73778 5582.50 67552 \n",
"... ... ... ... ... ... \n",
"25876 600211.SH 20260119 10915 4796.09 12174 \n",
"25877 601229.SH 20260119 225161 21704.91 267726 \n",
"25878 003042.SZ 20260119 17500 2893.60 11703 \n",
"25879 601155.SH 20260119 75731 11076.12 70817 \n",
"25880 600169.SH 20260119 81734 2005.16 84188 \n",
"25871 002774.SZ 20260202 32854 3675.61 20566 \n",
"25872 300188.SZ 20260202 54005 7416.58 48176 \n",
"25873 688173.SH 20260202 64149 10373.20 68049 \n",
"25874 300145.SZ 20260202 132990 6043.37 133529 \n",
"25875 300205.SZ 20260202 8361 364.75 6236 \n",
"\n",
" sell_sm_amount buy_md_vol buy_md_amount sell_md_vol sell_md_amount \\\n",
"0 3728.28 48486 3966.28 59366 4856.95 \n",
"1 1693.39 6499 1121.44 6017 1038.84 \n",
"2 21840.97 22701 16511.38 23142 16835.79 \n",
"3 4687.48 68181 5800.70 62114 5285.81 \n",
"4 12712.79 35383 13409.44 40111 15213.47 \n",
"0 6550.08 114346 5247.29 121777 5580.76 \n",
"1 9880.13 15560 4828.56 14519 4506.56 \n",
"2 11195.49 27988 6622.95 30015 7118.27 \n",
"3 21323.49 21708 14968.66 21044 14503.09 \n",
"4 5110.61 53914 4075.02 53354 4037.48 \n",
"... ... ... ... ... ... \n",
"25876 5348.74 9594 4215.26 8253 3626.54 \n",
"25877 25799.99 204041 19664.19 207361 19990.67 \n",
"25878 1933.74 11780 1946.25 14398 2379.72 \n",
"25879 10351.64 45622 6659.41 46251 6765.59 \n",
"25880 2063.68 129391 3172.21 137053 3360.95 \n",
"25871 2300.99 20761 2320.61 21785 2437.00 \n",
"25872 6623.07 52821 7250.13 53449 7347.52 \n",
"25873 11000.03 35320 5706.28 30270 4895.56 \n",
"25874 6066.65 114646 5208.71 97260 4422.03 \n",
"25875 272.25 9374 408.60 9827 427.93 \n",
"\n",
" buy_lg_vol buy_lg_amount sell_lg_vol sell_lg_amount buy_elg_vol \\\n",
"0 39133 3201.55 32920 2693.69 6576 \n",
"1 4067 702.11 4633 799.04 241 \n",
"2 11291 8249.67 11377 8302.90 3400 \n",
"3 46517 3960.29 57644 4906.75 23366 \n",
"4 24315 9212.24 24640 9342.34 5111 \n",
"0 85477 3926.44 87204 3989.37 28400 \n",
"1 5474 1697.68 6390 1982.08 721 \n",
"2 11723 2778.17 15330 3630.71 3939 \n",
"3 13069 9000.74 15789 10882.14 7583 \n",
"4 27279 2062.59 22583 1709.48 10118 \n",
"... ... ... ... ... ... \n",
"25876 5507 2419.57 5204 2286.10 2 \n",
"25877 134694 12983.30 86737 8363.03 24453 \n",
"25878 4038 668.49 7218 1194.87 0 \n",
"25879 23725 3458.86 23634 3453.46 21891 \n",
"25880 63062 1545.61 49278 1208.05 5904 \n",
"25871 8975 1002.99 18793 2100.36 0 \n",
"25872 31050 4271.36 35903 4923.97 7655 \n",
"25873 11829 1915.52 12687 2050.68 2000 \n",
"25874 81164 3682.66 113414 5149.25 41421 \n",
"25875 6887 302.35 8559 375.51 0 \n",
"\n",
" buy_elg_amount sell_elg_vol sell_elg_amount net_mf_vol \\\n",
"0 539.18 13561 1110.11 -4914 \n",
"1 41.60 1278 220.26 1923 \n",
"2 2437.55 1825 1325.59 1620 \n",
"3 1991.65 25767 2196.91 46602 \n",
"4 1934.73 8437 3191.36 -19491 \n",
"0 1293.83 19618 913.39 42201 \n",
"1 223.34 1261 390.07 -823 \n",
"2 935.53 9548 2248.51 2997 \n",
"3 5221.72 6117 4227.39 6215 \n",
"4 766.07 21600 1628.62 -9839 \n",
"... ... ... ... ... \n",
"25876 0.88 388 170.41 -44 \n",
"25877 2359.23 26525 2557.95 -37774 \n",
"25878 0.00 0 0.00 6587 \n",
"25879 3125.39 26267 3749.10 28653 \n",
"25880 144.65 9571 234.95 -10865 \n",
"25871 0.00 1446 160.86 -20182 \n",
"25872 1053.35 8003 1096.85 -12903 \n",
"25873 319.00 2291 367.73 -5670 \n",
"25874 1881.32 26018 1178.15 -70082 \n",
"25875 0.00 0 0.00 -1678 \n",
"\n",
" net_mf_amount \n",
"0 -391.89 \n",
"1 333.04 \n",
"2 1372.40 \n",
"3 3982.07 \n",
"4 -7354.89 \n",
"0 1943.09 \n",
"1 -246.33 \n",
"2 705.13 \n",
"3 4367.94 \n",
"4 -741.40 \n",
"... ... \n",
"25876 -16.04 \n",
"25877 -3603.98 \n",
"25878 1092.73 \n",
"25879 4152.29 \n",
"25880 -256.23 \n",
"25871 -2251.19 \n",
"25872 -1769.73 \n",
"25873 -918.58 \n",
"25874 -3146.31 \n",
"25875 -68.42 \n",
"\n",
"[25881 rows x 20 columns]\n"
"[25876 rows x 20 columns]\n"
]
}
],

View File

@@ -34,23 +34,23 @@
"output_type": "stream",
"text": [
" ts_code trade_date\n",
"4959 600211.SH 20260116\n",
"4960 600212.SH 20260116\n",
"4961 600215.SH 20260116\n",
"4949 600197.SH 20260116\n",
"3732 301501.SZ 20260116\n",
"4971 600208.SH 20260130\n",
"4972 600210.SH 20260130\n",
"4973 600211.SH 20260130\n",
"4961 600195.SH 20260130\n",
"7441 920964.BJ 20260130\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 11701107 entries, 0 to 37139\n",
"Index: 11775527 entries, 0 to 37233\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 267.8+ MB\n",
"memory usage: 269.5+ MB\n",
"None\n",
"20260116\n",
"20260119\n"
"20260130\n",
"20260202\n"
]
}
],
@@ -68,7 +68,7 @@
" max_date = df['trade_date'].max()\n",
"\n",
"print(max_date)\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260201')\n",
"trade_cal = pro.trade_cal(exchange='', start_date='20170101', end_date='20260310')\n",
"trade_cal = trade_cal[trade_cal['is_open'] == 1] # 只保留交易日\n",
"trade_dates = trade_cal[trade_cal['cal_date'] > max_date]['cal_date'].tolist()\n",
"start_date = min(trade_dates)\n",
@@ -91,22 +91,27 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260130 完成\n",
"任务 20260129 完成\n",
"任务 20260128 完成\n",
"任务 20260127 完成\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260126 完成\n",
"任务 20260123 完成\n",
"任务 20260122 完成\n",
"任务 20260121 完成\n",
"任务 20260120 完成\n",
"任务 20260119 完成\n"
"任务 20260310 完成\n",
"任务 20260309 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260303 完成\n",
"任务 20260304 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
]
}
],
@@ -158,71 +163,71 @@
"output_type": "stream",
"text": [
"[ trade_date ts_code up_limit down_limit\n",
"0 20260123 000001.SZ 12.18 9.96\n",
"1 20260123 000002.SZ 5.45 4.46\n",
"2 20260123 000004.SZ 12.59 11.39\n",
"3 20260123 000006.SZ 10.62 8.69\n",
"4 20260123 000007.SZ 12.47 10.21\n",
"0 20260206 000001.SZ 12.20 9.98\n",
"1 20260206 000002.SZ 5.37 4.39\n",
"2 20260206 000004.SZ 10.79 9.77\n",
"3 20260206 000006.SZ 9.90 8.10\n",
"4 20260206 000007.SZ 12.31 10.07\n",
"... ... ... ... ...\n",
"7435 20260123 920978.BJ 44.56 24.00\n",
"7436 20260123 920981.BJ 45.61 24.57\n",
"7437 20260123 920982.BJ 295.08 158.90\n",
"7438 20260123 920985.BJ 10.20 5.50\n",
"7439 20260123 920992.BJ 24.32 13.10\n",
"7459 20260206 920978.BJ 41.60 22.40\n",
"7460 20260206 920981.BJ 41.63 22.43\n",
"7461 20260206 920982.BJ 298.63 160.81\n",
"7462 20260206 920985.BJ 11.37 6.13\n",
"7463 20260206 920992.BJ 22.32 12.02\n",
"\n",
"[7440 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260122 000001.SZ 12.18 9.96\n",
"1 20260122 000002.SZ 5.51 4.51\n",
"2 20260122 000004.SZ 11.99 10.85\n",
"3 20260122 000006.SZ 10.62 8.69\n",
"4 20260122 000007.SZ 12.41 10.15\n",
"[7464 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260205 000001.SZ 12.07 9.87\n",
"1 20260205 000002.SZ 5.39 4.41\n",
"2 20260205 000004.SZ 11.36 10.28\n",
"3 20260205 000006.SZ 9.97 8.15\n",
"4 20260205 000007.SZ 12.32 10.08\n",
"... ... ... ... ...\n",
"7433 20260122 920978.BJ 45.48 24.50\n",
"7434 20260122 920981.BJ 45.61 24.57\n",
"7435 20260122 920982.BJ 301.76 162.50\n",
"7436 20260122 920985.BJ 9.84 5.30\n",
"7437 20260122 920992.BJ 23.95 12.91\n",
"7454 20260205 920978.BJ 41.48 22.34\n",
"7455 20260205 920981.BJ 42.00 22.62\n",
"7456 20260205 920982.BJ 289.43 155.85\n",
"7457 20260205 920985.BJ 12.16 6.56\n",
"7458 20260205 920992.BJ 22.32 12.02\n",
"\n",
"[7438 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260121 000001.SZ 12.28 10.04\n",
"1 20260121 000002.SZ 5.27 4.31\n",
"2 20260121 000004.SZ 12.02 10.88\n",
"3 20260121 000006.SZ 10.27 8.41\n",
"4 20260121 000007.SZ 12.08 9.88\n",
"[7459 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260204 000001.SZ 11.92 9.76\n",
"1 20260204 000002.SZ 5.17 4.23\n",
"2 20260204 000004.SZ 11.96 10.82\n",
"3 20260204 000006.SZ 9.77 7.99\n",
"4 20260204 000007.SZ 12.32 10.08\n",
"... ... ... ... ...\n",
"7433 20260121 920978.BJ 45.60 24.56\n",
"7434 20260121 920981.BJ 43.81 23.59\n",
"7435 20260121 920982.BJ 304.34 163.88\n",
"7436 20260121 920985.BJ 9.90 5.34\n",
"7437 20260121 920992.BJ 24.11 12.99\n",
"7453 20260204 920978.BJ 38.15 20.55\n",
"7454 20260204 920981.BJ 43.01 23.17\n",
"7455 20260204 920982.BJ 279.50 150.50\n",
"7456 20260204 920985.BJ 10.66 5.74\n",
"7457 20260204 920992.BJ 22.28 12.00\n",
"\n",
"[7438 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260120 000001.SZ 12.23 10.01\n",
"1 20260120 000002.SZ 5.20 4.26\n",
"2 20260120 000004.SZ 11.46 10.36\n",
"3 20260120 000006.SZ 10.07 8.24\n",
"4 20260120 000007.SZ 12.49 10.22\n",
"[7458 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260203 000001.SZ 11.95 9.77\n",
"1 20260203 000002.SZ 5.15 4.21\n",
"2 20260203 000004.SZ 12.59 11.39\n",
"3 20260203 000006.SZ 9.58 7.84\n",
"4 20260203 000007.SZ 12.09 9.89\n",
"... ... ... ... ...\n",
"7431 20260120 920978.BJ 46.41 24.99\n",
"7432 20260120 920981.BJ 44.26 23.84\n",
"7433 20260120 920982.BJ 310.42 167.16\n",
"7434 20260120 920985.BJ 9.97 5.37\n",
"7435 20260120 920992.BJ 24.49 13.19\n",
"7453 20260203 920978.BJ 37.93 20.43\n",
"7454 20260203 920981.BJ 42.52 22.90\n",
"7455 20260203 920982.BJ 279.35 150.43\n",
"7456 20260203 920985.BJ 10.15 5.47\n",
"7457 20260203 920992.BJ 21.95 11.83\n",
"\n",
"[7436 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260119 000001.SZ 12.31 10.07\n",
"1 20260119 000002.SZ 5.20 4.26\n",
"2 20260119 000004.SZ 11.70 10.58\n",
"3 20260119 000006.SZ 10.13 8.29\n",
"4 20260119 000007.SZ 12.43 10.17\n",
"[7458 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260202 000001.SZ 11.91 9.75\n",
"1 20260202 000002.SZ 5.37 4.39\n",
"2 20260202 000004.SZ 13.25 11.99\n",
"3 20260202 000006.SZ 9.86 8.06\n",
"4 20260202 000007.SZ 11.97 9.79\n",
"... ... ... ... ...\n",
"7429 20260119 920978.BJ 46.26 24.92\n",
"7430 20260119 920981.BJ 45.51 24.51\n",
"7431 20260119 920982.BJ 305.50 164.50\n",
"7432 20260119 920985.BJ 9.88 5.32\n",
"7433 20260119 920992.BJ 24.28 13.08\n",
"7450 20260202 920978.BJ 40.36 21.74\n",
"7451 20260202 920981.BJ 45.50 24.50\n",
"7452 20260202 920982.BJ 287.80 154.98\n",
"7453 20260202 920985.BJ 10.33 5.57\n",
"7454 20260202 920992.BJ 22.63 12.19\n",
"\n",
"[7434 rows x 4 columns]]\n"
"[7455 rows x 4 columns]]\n"
]
}
],

View File

@@ -78,7 +78,7 @@
"cyq perf\n",
"left merge on ['ts_code', 'trade_date']\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 9359748 entries, 0 to 9359747\n",
"RangeIndex: 9410807 entries, 0 to 9410806\n",
"Data columns (total 33 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -116,7 +116,7 @@
" 31 weight_avg float64 \n",
" 32 winner_rate float64 \n",
"dtypes: bool(1), datetime64[ns](1), float64(30), object(1)\n",
"memory usage: 2.2+ GB\n",
"memory usage: 2.3+ GB\n",
"None\n"
]
}
@@ -600,7 +600,7 @@
"Calculating cs_rank_size...\n",
"Finished cs_rank_size.\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 5042085 entries, 0 to 5042084\n",
"RangeIndex: 5072276 entries, 0 to 5072275\n",
"Columns: 181 entries, ts_code to cs_rank_size\n",
"dtypes: bool(10), datetime64[ns](1), float64(165), int64(3), object(2)\n",
"memory usage: 6.5+ GB\n",
@@ -1409,7 +1409,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 9.39it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 10.05it/s]\n"
]
},
{
@@ -1424,7 +1424,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.45it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:16<00:00, 8.05it/s]\n"
]
},
{
@@ -1464,13 +1464,13 @@
"截面 MAD 去极值处理完成。\n",
"feature_columns: ['vol', 'pct_chg', 'turnover_rate', 'volume_ratio', 'winner_rate', 'undist_profit_ps', 'ocfps', 'AR', 'BR', 'AR_BR', 'cashflow_to_ev_factor', 'book_to_price_ratio', 'turnover_rate_mean_5', 'variance_20', 'bbi_ratio_factor', 'daily_deviation', 'lg_elg_net_buy_vol', 'flow_lg_elg_intensity', 'sm_net_buy_vol', 'total_buy_vol', 'lg_elg_buy_prop', 'flow_struct_buy_change', 'lg_elg_net_buy_vol_change', 'flow_lg_elg_accel', 'chip_concentration_range', 'chip_skewness', 'floating_chip_proxy', 'cost_support_15pct_change', 'cat_winner_price_zone', 'flow_chip_consistency', 'profit_taking_vs_absorb', 'cat_is_positive', 'upside_vol', 'downside_vol', 'vol_ratio', 'return_skew', 'return_kurtosis', 'volume_change_rate', 'cat_volume_breakout', 'turnover_deviation', 'cat_turnover_spike', 'avg_volume_ratio', 'cat_volume_ratio_breakout', 'vol_spike', 'vol_std_5', 'atr_14', 'atr_6', 'obv', 'maobv_6', 'rsi_3', 'return_5', 'return_20', 'std_return_5', 'std_return_90', 'std_return_90_2', 'act_factor1', 'act_factor2', 'act_factor3', 'act_factor4', 'rank_act_factor1', 'rank_act_factor2', 'rank_act_factor3', 'cov', 'delta_cov', 'alpha_22_improved', 'alpha_003', 'alpha_007', 'alpha_013', 'vol_break', 'weight_roc5', 'smallcap_concentration', 'cost_stability', 'high_cost_break_days', 'liquidity_risk', 'turnover_std', 'mv_volatility', 'volume_growth', 'mv_growth', 'momentum_factor', 'resonance_factor', 'log_close', 'cat_vol_spike', 'up', 'down', 'obv_maobv_6', 'std_return_5_over_std_return_90', 'std_return_90_minus_std_return_90_2', 'cat_af2', 'cat_af3', 'cat_af4', 'act_factor5', 'act_factor6', 'active_buy_volume_large', 'active_buy_volume_big', 'active_buy_volume_small', 'buy_lg_vol_minus_sell_lg_vol', 'buy_elg_vol_minus_sell_elg_vol', 'ctrl_strength', 'low_cost_dev', 'asymmetry', 'lock_factor', 'cat_vol_break', 'cost_atr_adj', 'cat_golden_resonance', 'mv_turnover_ratio', 'mv_adjusted_volume', 'mv_weighted_turnover', 'nonlinear_mv_volume', 'mv_volume_ratio', 'mv_momentum', 'lg_flow_mom_corr_20_60', 'lg_flow_accel', 'profit_pressure', 'underwater_resistance', 'cost_conc_std_20', 'profit_decay_20', 'vol_amp_loss_20', 'vol_drop_profit_cnt_5', 'lg_flow_vol_interact_20', 'cost_break_confirm_cnt_5', 'atr_norm_channel_pos_14', 'turnover_diff_skew_20', 'lg_sm_flow_diverge_20', 'pullback_strong_20_20', 'vol_wgt_hist_pos_20', 'vol_adj_roc_20', 'cs_rank_net_lg_flow_val', 'cs_rank_elg_buy_ratio', 'cs_rank_rel_profit_margin', 'cs_rank_cost_breadth', 'cs_rank_dist_to_upper_cost', 'cs_rank_winner_rate', 'cs_rank_intraday_range', 'cs_rank_close_pos_in_range', 'cs_rank_pos_in_hist_range', 'cs_rank_vol_x_profit_margin', 'cs_rank_lg_flow_price_concordance', 'cs_rank_turnover_per_winner', 'cs_rank_volume_ratio', 'cs_rank_elg_buy_sell_sm_ratio', 'cs_rank_cost_dist_vol_ratio', 'cs_rank_size', 'cat_up_limit', 'industry_obv', 'industry_return_5', 'industry_return_20', 'industry__ema_5', 'industry__ema_13', 'industry__ema_20', 'industry__ema_60', 'industry_act_factor1', 'industry_act_factor2', 'industry_act_factor3', 'industry_act_factor4', 'industry_act_factor5', 'industry_act_factor6', 'industry_rank_act_factor1', 'industry_rank_act_factor2', 'industry_rank_act_factor3', 'industry_return_5_percentile', 'industry_return_20_percentile', '000852.SH_MACD', '000905.SH_MACD', '399006.SZ_MACD', '000852.SH_MACD_hist', '000905.SH_MACD_hist', '399006.SZ_MACD_hist', '000852.SH_RSI', '000905.SH_RSI', '399006.SZ_RSI', '000852.SH_Signal_line', '000905.SH_Signal_line', '399006.SZ_Signal_line', '000852.SH_amount_change_rate', '000905.SH_amount_change_rate', '399006.SZ_amount_change_rate', '000852.SH_amount_mean', '000905.SH_amount_mean', '399006.SZ_amount_mean', '000852.SH_daily_return', '000905.SH_daily_return', '399006.SZ_daily_return', '000852.SH_up_ratio_20d', '000905.SH_up_ratio_20d', '399006.SZ_up_ratio_20d', '000852.SH_volatility', '000905.SH_volatility', '399006.SZ_volatility', '000852.SH_volume_change_rate', '000905.SH_volume_change_rate', '399006.SZ_volume_change_rate']\n",
"df最小日期: 2019-01-02\n",
"df最大日期: 2026-01-23\n",
"2055951\n",
"df最大日期: 2026-02-06\n",
"2055944\n",
"train_data最小日期: 2020-01-02\n",
"train_data最大日期: 2022-12-30\n",
"2267560\n",
"2297633\n",
"test_data最小日期: 2023-01-03\n",
"test_data最大日期: 2026-01-23\n",
"test_data最大日期: 2026-02-06\n",
" ts_code trade_date log_circ_mv\n",
"0 000001.SZ 2019-01-02 16.574219\n",
"1 000001.SZ 2019-01-03 16.583965\n",
@@ -1754,7 +1754,7 @@
{
"data": {
"text/plain": [
"<catboost.core.CatBoostClassifier at 0x7cca5687f800>"
"<catboost.core.CatBoostClassifier at 0x7b3eec333d70>"
]
},
"execution_count": 19,
@@ -1841,7 +1841,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5584 2055951\n",
"5584 2055944\n",
" ts_code trade_date turnover_rate\n",
"0 000001.SZ 2023-01-03 1.1307\n",
"1 000001.SZ 2023-01-04 1.1284\n",
@@ -1849,13 +1849,13 @@
"3 000001.SZ 2023-01-06 0.6162\n",
"4 000001.SZ 2023-01-09 0.5450\n",
"... ... ... ...\n",
"2267555 605599.SH 2026-01-19 0.6158\n",
"2267556 605599.SH 2026-01-20 0.9493\n",
"2267557 605599.SH 2026-01-21 1.1732\n",
"2267558 605599.SH 2026-01-22 0.8848\n",
"2267559 605599.SH 2026-01-23 0.9550\n",
"2297628 605599.SH 2026-02-02 2.6968\n",
"2297629 605599.SH 2026-02-03 1.6084\n",
"2297630 605599.SH 2026-02-04 3.9328\n",
"2297631 605599.SH 2026-02-05 3.0072\n",
"2297632 605599.SH 2026-02-06 3.1129\n",
"\n",
"[2267560 rows x 3 columns]\n"
"[2297633 rows x 3 columns]\n"
]
}
],

View File

@@ -1483,3 +1483,23 @@ trade_date,score,ts_code
2026-01-22,0.5392295112943043,002193.SZ
2026-01-23,0.4433520823626358,001211.SZ
2026-01-23,0.5104712391758388,002193.SZ
2026-01-26,0.44845793700606645,600768.SH
2026-01-26,0.5184014597753998,002193.SZ
2026-01-27,0.38801810040527523,002719.SZ
2026-01-27,0.4660343777911184,002193.SZ
2026-01-28,0.3752951609014855,002963.SZ
2026-01-28,0.3844631540327193,002193.SZ
2026-01-29,0.3957310272373612,002188.SZ
2026-01-29,0.4154973074156361,002193.SZ
2026-01-30,0.4406255680708698,002193.SZ
2026-01-30,0.6387329035097701,600768.SH
2026-02-02,0.46452469502542476,600543.SH
2026-02-02,0.48096075649083675,002719.SZ
2026-02-03,0.4682296506349894,002719.SZ
2026-02-03,0.6074115272186936,002193.SZ
2026-02-04,0.441433034204454,600847.SH
2026-02-04,0.6491590676980965,002193.SZ
2026-02-05,0.43576482005305384,002719.SZ
2026-02-05,0.6383257473564533,002193.SZ
2026-02-06,0.45969830258066396,600493.SH
2026-02-06,0.6311025962732058,002193.SZ
1 trade_date,score,ts_code
1483 2026-01-22,0.5392295112943043,002193.SZ
1484 2026-01-23,0.4433520823626358,001211.SZ
1485 2026-01-23,0.5104712391758388,002193.SZ
1486 2026-01-26,0.44845793700606645,600768.SH
1487 2026-01-26,0.5184014597753998,002193.SZ
1488 2026-01-27,0.38801810040527523,002719.SZ
1489 2026-01-27,0.4660343777911184,002193.SZ
1490 2026-01-28,0.3752951609014855,002963.SZ
1491 2026-01-28,0.3844631540327193,002193.SZ
1492 2026-01-29,0.3957310272373612,002188.SZ
1493 2026-01-29,0.4154973074156361,002193.SZ
1494 2026-01-30,0.4406255680708698,002193.SZ
1495 2026-01-30,0.6387329035097701,600768.SH
1496 2026-02-02,0.46452469502542476,600543.SH
1497 2026-02-02,0.48096075649083675,002719.SZ
1498 2026-02-03,0.4682296506349894,002719.SZ
1499 2026-02-03,0.6074115272186936,002193.SZ
1500 2026-02-04,0.441433034204454,600847.SH
1501 2026-02-04,0.6491590676980965,002193.SZ
1502 2026-02-05,0.43576482005305384,002719.SZ
1503 2026-02-05,0.6383257473564533,002193.SZ
1504 2026-02-06,0.45969830258066396,600493.SH
1505 2026-02-06,0.6311025962732058,002193.SZ

View File

@@ -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` 越小,换手率越低,交易成本降低但灵活性也降低
### QRedis 连接失败怎么办?
A请检查以下几点
1. Redis 服务是否已启动
2. `host``port` 配置是否正确
3. 防火墙是否允许 Redis 端口访问
4. 如果设置了密码,`password` 是否正确
### Q如何配置策略的资金分配权重
A通过 `weight` 字段可以配置策略的资金分配权重:
- `weight` 是可选字段,不配置时默认为 1
- 下单金额计算公式:可用资金 × 策略权重 / Σ(各策略槽位数 × 权重)
- 示例两个策略A 的 weight=1、total_slots=5B 的 weight=2、total_slots=5则 A 分配 1/(1×5+2×5)=1/15B 分配 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` | 交易状态可视化界面 |

View File

@@ -209,39 +209,41 @@ class AutoReconnectScheduler:
time.sleep(60)
def _scheduled_reconnect(self):
"""执行定时重连任务"""
self.logger.info(f"执行定时重连任务,时间: {self.reconnect_time}")
"""执行定时重连任务(强制重连模式)"""
self.logger.info(f"[AutoReconnectScheduler] 执行定时重连任务,时间: {self.reconnect_time}")
# 1. 检测当前连接状态
statuses = self.manager.get_all_status()
connected_count = sum(1 for s in statuses if s.is_connected)
self.logger.info(f"当前连接状态: {connected_count}/{len(statuses)} 个终端在线")
# 设置重连中标志位,通知主循环暂停健康检查重连
self.manager.is_scheduled_reconnecting = True
# 2. 如果有连接,先断开
if connected_count > 0:
self.logger.info("正在断开所有终端连接...")
try:
# 强制断开所有终端连接(无论当前是否在线)
self.logger.info("[AutoReconnectScheduler] 正在断开所有终端连接...")
for unit in self.manager.units.values():
try:
if unit.xt_trader:
unit.cleanup()
self.logger.info(f"[AutoReconnectScheduler] 已断开终端 {unit.alias} 的连接")
except Exception as e:
self.logger.warning(f"断开终端 {unit.alias} 失败: {e}")
self.logger.warning(f"[AutoReconnectScheduler] 断开终端 {unit.alias} 失败: {e}")
# 3. 等待几秒后重新连接
self.logger.info("等待 3 秒后重新连接...")
time.sleep(3)
# 等待几秒后重新连接(固定等待时间)
self.logger.info("[AutoReconnectScheduler] 等待 3 秒后重新连接...")
time.sleep(3)
# 4. 重新连接所有终端
self.logger.info("正在重新连接所有终端...")
success_count = 0
for unit in self.manager.units.values():
if unit.connect():
success_count += 1
self.logger.info(f"终端 {unit.alias} 重连成功")
else:
self.logger.warning(f"终端 {unit.alias} 重连失败")
# 重新连接所有终端
self.logger.info("[AutoReconnectScheduler] 正在重新连接所有终端...")
success_count = 0
for unit in self.manager.units.values():
if unit.connect():
success_count += 1
self.logger.info(f"[AutoReconnectScheduler] 终端 {unit.alias} 重连成功")
else:
self.logger.warning(f"[AutoReconnectScheduler] 终端 {unit.alias} 重连失败")
self.logger.info(f"定时重连完成: {success_count}/{len(self.manager.units)} 个终端重连成功")
self.logger.info(f"[AutoReconnectScheduler] 定时重连完成: {success_count}/{len(self.manager.units)} 个终端重连成功")
finally:
# 确保无论成功与否都重置标志位
self.manager.is_scheduled_reconnecting = False
def start(self):
"""启动定时任务"""
@@ -351,11 +353,11 @@ class TradingUnit:
try:
logging.getLogger("QMT_Engine").info(f"正在销毁终端 {self.alias} 的旧资源...")
self.xt_trader.stop()
self.xt_trader = None # 显式置空
self.xt_trader = None # 显式置空
self.callback = None
time.sleep(1.5) # 给 C++ 引擎留出释放 down_queue 锁的时间
except:
pass
time.sleep(1.5) # 给 C++ 引擎留出释放 down_queue 锁的时间
except Exception as e:
logging.getLogger("QMT_Engine").warning(f"销毁终端 {self.alias} 资源时出现异常: {e}")
def connect(self):
"""连接 QMT 终端"""
@@ -401,6 +403,7 @@ class MultiEngineManager:
self.config = {}
self.is_running = True
self.start_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.is_scheduled_reconnecting = False # 定时重连调度器正在执行标志
self._initialized = True
def initialize(self, config_file='config.json'):
@@ -467,8 +470,12 @@ class MultiEngineManager:
if not is_unit_alive:
# 避让 QMT 夜间重启高峰 (21:32 - 21:50)
if not ('213200' <= curr_hms <= '215000'):
self.logger.warning(f"🚫 终端 {unit.alias} 物理连接丢失,执行重连...")
unit.connect()
# 检查是否正在执行定时重连调度
if self.is_scheduled_reconnecting:
self.logger.info(f"⏳ 定时重连调度器正在执行,跳过健康检查重连...")
else:
self.logger.warning(f"🚫 终端 {unit.alias} 物理连接丢失,执行重连...")
unit.connect()
else:
self.logger.info(f"⏳ 处于 QMT 重启时段 ({curr_hms}),跳过重连操作...")

331
qmt/qmt_functionality.md Normal file
View File

@@ -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/` 目录

View File

@@ -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"