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