通达信 + miniQMT 期权期货量化交易 技术方案
基于通达信技术指标信号触发,通过 miniQMT 极速执行通道实现期权期货自动化交易
1. 背景与目标
1.1 问题域
在期权期货交易中,交易者面临以下核心痛点:
- 通达信提供强大的技术指标和公式系统,但无实盘交易接口,信号无法自动执行
- 期权期货盯盘强度高、决策时效短,人工执行难以保证纪律性和响应速度
- 多品种、多合约的跨市场套利需要程序化协调,手工无法胜任
1.2 方案目标
- 信号自动化 — 通达信技术指标信号实时捕获,零人工干预完成交易执行
- 低延迟 — 全链路端到端延迟控制在 500ms 以内(含网络传输)
- 全品种覆盖 — 股指期权、商品期货、商品期权统一接入
- 工程化风控 — 资金管理、仓位控制、异常熔断三防体系
- 可观测 — 全链路日志、实时监控、操作审计
1.3 适用读者
- 熟悉通达信指标公式、希望将其转化为自动化策略的交易者
- 具备 Python 基础、希望搭建个人量化交易系统的开发者
- 需要为团队搭建期权期货交易基础设施的 IT 人员
2. 系统架构
2.1 分层架构总览
┌─────────────────────────────────────────────────────────────────────┐
│ 通达信 (TongDaXin) 信号生成层 │
│ ┌─────────────────────────────────────┐ │
│ │ 技术指标公式 → 条件预警 → 写文件 │ ← 用户在此编写指标策略 │
│ │ 输出: D:\signals\output.txt │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ 文件系统 / Named Pipe
▼
┌─────────────────────────────────────────────────────────────────────┐
│ miniQMT (xtquant SDK) 信号处理层 │
│ ┌─────────────────────────────────────┐ │
│ │ 文件监控 (FileSystemWatcher) │ │
│ │ → 信号解析 → 策略逻辑 → 下单决策 │ │
│ │ → xttrader.passorder() 调用 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ TCP / 内部协议
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 券商极速柜台 (LDP / HTS) 交易执行层 │
│ ┌─────────────────────────────────────┐ │
│ │ 期货: CTP 6.7.x │ │
│ │ 期权: 交易所期权交易接口 │ │
│ │ 委托 → 交易所 → 成交回报 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ 交易所 (DCE/SHFE/CFFEX/...) │
└─────────────────────┘
2.2 组件职责
| 组件 | 职责 | 技术选型 | 运行环境 |
|---|---|---|---|
| 通达信 | 行情显示、指标计算、条件预警输出 | 通达信金融终端 v7.x | Windows 10/11 |
| 信号文件 | 作为层间契约,承载结构化信号数据 | JSON Lines (.jsonl) / CSV | NTFS 文件系统 |
| 监控引擎 | 轮询或事件驱动读取信号文件 | Python 3.10+ / watchdog | Windows (与QMT同机) |
| 策略决策 | 信号有效性校验、仓位计算、下单参数组装 | Python / xtquant SDK | 与QMT同进程 |
| 执行引擎 | 调用 xttrader.passorder 发送委托 | xtquant (xttrader) | miniQMT 进程 |
| 风控模块 | 前置校验:资金、仓位、频率、黑白名单 | Python 本地校验 | 与决策模块同进程 |
| 日志系统 | 全链路结构化日志 + 操作审计 | Python logging + 文件轮转 | 本地存储 |
2.3 进程拓扑
┌───────────── Windows 主机 ─────────────────────────────────────┐
│ │
│ ┌──────────────┐ ┌──────────────────────────────────────┐ │
│ │ 通达信进程 │ │ Python 策略引擎 (quant_engine.exe) │ │
│ │ (TDX.exe) │ │ ┌────────────────────────────────┐ │ │
│ │ │ │ │ watchdog (文件监控线程) │ │ │
│ │ 条件预警 │─────┼─▶│ 策略决策 (strategy_runner) │ │ │
│ │ → 写文件 │ │ │ 风控校验 (risk_controller) │ │ │
│ └──────────────┘ │ │ ↓ │ │ │
│ │ │ xtquant API client │ │ │
│ │ └──────────────┬─────────────────┘ │ │
│ └─────────────────┼─────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────┐│ │
│ │ miniQMT (xtquant 运行时) ││ │
│ │ 连接券商极速柜台 → 发送委托 ││ │
│ └─────────────────────────────────────┘│ │
│ │ │
│ ┌─────────────────────────────────────┐ │
│ │ 日志存储 (logs/) │ │
│ │ 配置存储 (config/) │ │
│ │ 数据缓存 (data/) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3. 数据流设计
3.1 正常交易流程
时序图:一个完整的信号→成交周期
通达信 策略引擎 miniQMT 券商柜台
│ │ │ │
│ 1. K线更新,指标计算 │ │ │
│─────────────────────────────▶ │ │ │
│ 2. 条件满足,写入信号文件 │ │ │
│─────────────────────────────▶ │ │ │
│ │ 3. watchdog检测到文件变更 │ │
│ │─────────────────────────▶ │ │
│ │ 4. 读取并解析信号 │ │
│ │ 5. 风控前置校验 │ │
│ │ 6. 计算下单参数(价格/数量) │ │
│ │ 7. 调用passorder() │ │
│ │─────────────────────────▶ │ │
│ │ │ 8. 发送委托到柜台 │
│ │ │─────────────────────▶ │
│ │ │ │ 9. 交易所撮合
│ │ │ │◀─────────────────────
│ │ │ 10. 成交回报 │
│ │ │◀───────────────────── │
│ │ 11. 成交回报回调 │ │
│ │◀───────────────────────── │ │
│ │ 12. 记录日志,更新状态 │ │
3.2 延迟预算分解
端到端延迟目标:< 500ms(从通达信信号触发到委托到达柜台)
| 环节 | 预算 | 说明 |
|---|---|---|
| T1: 通达信写入文件 | < 50ms | 条件预警触发到文件落盘 |
| T2: 文件变更检测 | < 50ms | watchdog 事件通知延迟 |
| T3: 信号解析 + 风控 | < 50ms | JSON 解析 + 内存校验 |
| T4: passorder 调用 | < 5ms | 本地进程间调用 |
| T5: 柜台到交易所 | ~200ms | 网络传输 + 交易所处理 |
| 合计 | < 355ms | 不含交易所排队时间 |
实测参考:沪市全链路约 25ms,深市约 3ms(2025年行业测试数据)。以上为保守设计预算。
3.3 数据一致性保障
文件锁机制
- 通达信写入端:写文件前创建
.lock哨兵文件,写完删除 - 监控端:检测到
.lock存在时跳过该文件,等待解锁 - 超时:锁持有超过 5s 触发告警,强制解锁
去重保证
- 每条信号包含唯一
signal_id(通达信时间戳+序号) - 引擎维护已处理队列(内存 + 持久化),去重后执行
- 重启后加载历史 ID 到布隆过滤器,避免重复执行
乱序处理
- 信号文件按时间戳递增写入,监控端严格按时间序处理
- 发现时间戳回退时触发告警,暂停交易直到人工确认
幂等性
- 同一信号 ID 的委托最多发送一次
- 委托发送前检查订单状态(已报/已撤),避免重复下单
4. 接口定义
4.1 通达信 → 信号文件契约
通达信条件预警输出格式定义为 JSON Lines(每行一个完整 JSON 对象):
# 文件路径: D:\signals\signals.jsonl
# 编码: UTF-8 without BOM
{"signal_id": "20260515_143021_001", "ts": 1897657821, "symbol": "IO2506-C-4000", "direction": "buy_open", "price": 125.0, "qty": 1, "reason": "MACD金叉+成交量放大", "indicator": {"macd": 2.15, "vol_ratio": 1.8}}
字段定义
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
signal_id | string | 是 | 唯一信号 ID,格式:YYYYMMDD_HHMMSS_SSS |
ts | int64 | 是 | Unix 时间戳(毫秒) |
symbol | string | 是 | 合约代码,格式遵循交易所标准 |
direction | enum | 是 | buy_open / sell_open / buy_close / sell_close |
price | float | 是 | 目标价格(0 表示市价) |
qty | int | 是 | 手数/张数 |
reason | string | 否 | 信号触发原因,用于日志和审计 |
indicator | object | 否 | 触发时刻的指标快照,用于事后分析 |
4.2 miniQMT / xtquant API 核心接口
以下为方案中使用的核心 API:
| 函数 | 用途 | 关键参数 |
|---|---|---|
xtdata.get_market_data() | 获取实时行情 | field_list, stock_list, period |
xtdata.get_instrument_detail() | 获取合约信息(乘数、保证金率等) | stock_code |
xtdata.get_full_tick() | 获取最新 Tick 数据 | stock_list |
xttrader.AccountAsset() | 查询资金账户信息 | account_id |
xttrader.AccountPosition() | 查询持仓 | account_id, stock_code |
xttrader.passorder() | 发送委托(核心交易方法) | order_type, order_mode, account_id, code, price, qty, ... |
xttrader.cancel_order() | 撤单 | account_id, order_id |
passorder 参数详解
# 方法签名
def passorder(
order_type: int, # 委托类型: 23=限价, 24=市价, 25=条件单
order_mode: int, # 买卖方向: 0=买入/买开, 1=卖出/卖平, 2=卖开, 3=买平
account_id: str, # 资金账号
code: str, # 合约代码: "IO2506-C-4000"
price: float, # 委托价格
qty: int, # 委托数量
strategy_name: str, # 策略名称(用于标识)
order_remark: str # 备注(将出现在成交记录中)
)
注意:期权期货的开平方向请参考交易所的定义。xtquant 的
order_mode 参数值与通达信的习惯可能不同,务必查阅最新的 xtquant API 文档确认。
5. 信号输出配置(通达信端)
5.1 通达信条件预警设置
- 菜单:功能 → 条件预警 → 条件预警设置
- 勾选需要监控的指标公式和股票/合约
- 输出设置:"预警输出到文件",路径
D:\signals\ - 格式选择"自定义格式",配置如下:
# 通达信预警自定义格式模板
# 导出字段映射(通过通头信输出设置界面配置)
# {DATE} {TIME} {CODE} {NAME} {PRICE} {VOL} {SIGNAL}
# 推荐配置:
"D:\signals\signals.jsonl" ← 输出文件路径
# 输出格式(建议用通达信的DLL输出接口做JSON序列化):
# 如果通头信不支持直接输出JSON,可用中间转换脚本
5.2 中间转换方案(当通达信不支持直接输出JSON时)
大部分通达信版本不支持直接输出 JSON 格式,此时采用二级方案:
通达信预警输出 TXT
│ 格式: 代码,名称,方向,价格,时间
▼
TXT 到 JSON 转换器 ← 常驻 Python 脚本
│ (tail -f 读取 + 格式转换)
▼
signals.jsonl ← 标准接口文件,供引擎消费
# 通达信输出示例(CSV格式)
IO2506-C-4000,买入开仓,125.0,1,MACD金叉,20260515,143021
6. 监控引擎实现
6.1 核心代码框架
# quant_engine.py — 监控引擎核心
import json
import os
import time
import logging
from pathlib import Path
from threading import Thread, Lock
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from xtquant import xtdata, xttrader
class SignalHandler(FileSystemEventHandler):
"""通达信信号文件监控处理器"""
def __init__(self, signal_path: str, engine):
self.signal_path = Path(signal_path)
self.engine = engine
self.processed_ids = set() # 去重集合
self._lock = Lock()
self._load_processed_ids()
def on_modified(self, event):
if not event.src_path.endswith('.jsonl'):
return
# 检测锁文件
lock_file = self.signal_path.with_suffix('.lock')
if lock_file.exists():
# 通达信仍在写入,跳过本轮
return
self._process_file(event.src_path)
def _process_file(self, filepath: str):
"""读取并处理信号文件"""
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line:
continue
try:
signal = json.loads(line)
self._handle_signal(signal)
except json.JSONDecodeError as e:
logging.error(f"JSON解析失败: {e}, line: {line}")
def _handle_signal(self, signal: dict):
"""处理单条信号:去重→风控→执行"""
signal_id = signal.get('signal_id')
if not signal_id or signal_id in self.processed_ids:
return
with self._lock:
# 风控前置校验
risk_result = self.engine.risk_controller.check(signal)
if not risk_result.passed:
logging.warning(f"风控拦截: {signal_id}, 原因: {risk_result.reason}")
return
# 执行交易
self.engine.executor.execute(signal)
self.processed_ids.add(signal_id)
def _load_processed_ids(self):
"""重启时加载已处理ID,避免重复"""
record_file = Path('data/processed_ids.parquet')
if record_file.exists():
# 加载历史 ID 到布隆过滤器
pass
6.2 执行器实现
class OrderExecutor:
"""交易执行器 - 封装 xttrader.passorder()"""
def __init__(self, account_id: str):
self.account_id = account_id
self.session = xttrader.TradeSession()
self.session.connect()
def execute(self, signal: dict) -> dict:
"""将信号转换为委托并发送"""
direction = signal['direction']
order_mode = self._direction_to_mode(direction)
# 获取实时价格(如果 signal 中 price 为 0,则用市价单)
price = signal.get('price', 0)
if price == 0:
price = self._get_market_price(signal['symbol'])
# 调用 passorder
order_id = xttrader.passorder(
order_type=23, # 限价单
order_mode=order_mode,
account_id=self.account_id,
code=signal['symbol'],
price=price,
qty=signal['qty'],
strategy_name="TDX_QUANT",
order_remark=signal.get('signal_id', '')
)
logging.info(f"委托已发送: signal_id={signal['signal_id']}, order_id={order_id}")
return {'order_id': order_id, 'status': 'sent'}
def _direction_to_mode(self, direction: str) -> int:
"""将通达信方向转换为 xtquant order_mode"""
mapping = {
'buy_open': 0, # 买入开仓
'sell_close': 1, # 卖出平仓
'sell_open': 2, # 卖出开仓
'buy_close': 3, # 买入平仓
}
mode = mapping.get(direction)
if mode is None:
raise ValueError(f"未知方向: {direction}")
return mode
def _get_market_price(self, symbol: str) -> float:
# 获取最新行情价格
tick = xtdata.get_full_tick([symbol])
return tick[symbol]['lastPrice']
7. 策略框架
7.1 在通达信中编写指标公式
以下为示例:一个基于 MACD 金叉 + 成交量确认的股指期权买入开仓信号:
{通达信公式 - MACD金叉+量能确认}
// 适用: 沪深300股指期权 IO 合约
DIFF := EMA(CLOSE,12) - EMA(CLOSE,26);
DEA := EMA(DIFF,9);
MACD := 2*(DIFF-DEA);
// 金叉条件: DIFF 上穿 DEA
CROSS_DIFF_DEA := CROSS(DIFF, DEA);
// 成交量确认: 当前成交量 > 5日均量的1.5倍
VOL_CONFIRM := VOL > MA(VOL,5) * 1.5;
// 信号输出
BUY_SIGNAL := CROSS_DIFF_DEA AND VOL_CONFIRM;
// 将信号输出到预警(在条件预警设置中绑定此公式)
DRAWTEXT(BUY_SIGNAL, LOW, 'BUY_IO');
注意:通达信公式中无法直接获取期权隐含波动率、Greeks 等数据。如需基于 Greeks 的期权策略(如 Delta 对冲、波动率交易),需要将数据源切换到 QMT,在 Python 端完成策略逻辑,通达信仅做辅助参考。
7.2 策略层设计(Python 端)
| 策略类型 | 信号来源 | 执行逻辑 | 适用合约 |
|---|---|---|---|
| 趋势突破 | 通达信指标公式 | 价格突破均线/布林带 → 买入开仓 | 股指期货 / 商品期货 |
| 期权买方 | 通达信指标 + Python Greeks | 趋势信号 → 选择实值/平值期权 → 买入开仓 | 股指期权 / 商品期权 |
| 期现套利 | Python 实时价差计算 | 基差超阈值 → 反向开仓 | 股指期货 + ETF |
| 期权卖方 | Python 波动率曲面 | IV 超历史分位 → 卖出开仓 + 对冲 | 股指期权 |
| 跨品种套利 | Python 协整检验 | 价差偏离均值 → 对冲开仓 | 商品期货对 |
7.3 Python 侧策略编排
class StrategyRouter:
"""策略路由:根据信号来源分派到具体策略"""
def __init__(self):
self.strategies = {
'trend_breakout': TrendBreakoutStrategy(),
'option_buyer': OptionBuyerStrategy(),
'basis_arbitrage': BasisArbitrageStrategy(),
}
def route(self, signal: dict) -> Optional[OrderSignal]:
"""路由决策:返回 OrderSignal 或 None(不执行)"""
symbol = signal['symbol']
strategy_type = self._classify(symbol)
strategy = self.strategies.get(strategy_type)
if not strategy:
logging.warning(f"无匹配策略: {symbol}")
return None
return strategy.process(signal)
def _classify(self, symbol: str) -> str:
"""根据合约代码判断策略类型"""
if symbol.startswith('IO') or symbol.startswith('HO'):
return 'option_buyer'
if symbol.endswith('-C-') or symbol.endswith('-P-'):
return 'option_buyer'
if any(f in symbol for f in ['IF', 'IC', 'IH', 'RB', 'MA']):
return 'trend_breakout'
return 'trend_breakout'
8. 风控体系
8.1 风控架构
风控分为 三层防线,层层拦截:
第一层:前置校验(Python端) // 信号到达后立即执行
┌─────────────────────────────────────────────┐
│ ✔ 资金充足性校验 │
│ ✔ 仓位上限校验(单品种/总仓位) │
│ ✔ 下单频率校验(防 flooding) │
│ ✔ 合约白名单校验 │
│ ✔ 价格偏离度校验(防止极端价) │
└─────────────────────────────────────────────┘
│ 通过
▼
第二层:委托拦截(miniQMT侧) // 发送到柜台前
┌─────────────────────────────────────────────┐
│ ✔ 仓位反向对冲自检 │
│ ✔ 日内亏损熔断(当日亏损 > X% 停止交易) │
│ ✔ 连续撤单率监控 │
└─────────────────────────────────────────────┘
│ 通过
▼
第三层:柜台风控(券商侧) // 券商系统内置
┌─────────────────────────────────────────────┐
│ ✔ 资金冻结校验 │
│ ✔ 持仓检查(平仓数量不超过持仓) │
│ ✔ 交易所熔断机制 │
└─────────────────────────────────────────────┘
8.2 风控参数配置
# risk_config.yaml — 风控参数
risk:
# 资金类
max_single_order_cost: 100000 # 单笔最大委托金额 (元)
max_total_position_pct: 0.7 # 总仓位上限 (总资产的70%)
max_single_position_pct: 0.3 # 单一品种仓位上限 (30%)
# 频率类
min_order_interval_ms: 1000 # 最小下单间隔 (1秒)
max_orders_per_minute: 30 # 每分钟最大委托数
max_cancel_per_minute: 10 # 每分钟最大撤单数
# 熔断类
daily_loss_limit_pct: -0.05 # 日内亏损熔断 (-5%)
daily_loss_limit_abs: -50000 # 日内亏损熔断 (-5万)
circuit_breaker_cooldown_min: 30 # 熔断后冷却时间 (30分钟)
# 价格类
price_deviation_pct: 0.03 # 价格偏离现价上限 (3%)
min_price: 0.001 # 最低委托价格
max_price: 999999 # 最高委托价格
# 白名单
whitelist_symbols: [
"IO2506-C-4000", "IO2506-P-4000",
"IF2506", "IC2506", "IH2506"
]
8.3 风控控制器实现
class RiskController:
"""风控前置校验引擎"""
def __init__(self, config: dict):
self.config = config
self.daily_pnl = 0.0 # 当日盈亏
self.order_count_minute = 0 # 本分钟委托计数
self.last_order_ts = 0 # 上次委托时间戳
self.circuit_broken = False # 熔断状态
self.circuit_break_ts = 0 # 熔断触发时间
def check(self, signal: dict) -> RiskResult:
"""风控前置校验,返回校验结果"""
now = time.time()
# 1. 熔断检查
if self.circuit_broken:
remaining = self.circuit_break_ts + \
self.config['circuit_breaker_cooldown_min'] * 60 - now
if remaining > 0:
return RiskResult(False, f"熔断中,剩余 {int(remaining)}s")
self.circuit_broken = False
# 2. 白名单检查
if signal['symbol'] not in self.config['whitelist_symbols']:
return RiskResult(False, "合约不在白名单中")
# 3. 频率检查
if now - self.last_order_ts < float(
self.config['min_order_interval_ms']) / 1000:
return RiskResult(False, "下单间隔过短")
# 4. 价格偏离检查
current_price = self._get_current_price(signal['symbol'])
deviation = abs(signal['price'] - current_price) / \
(current_price or 1)
if deviation > self.config['price_deviation_pct']:
return RiskResult(False,
f"价格偏离 {deviation:.2%} 超限")
# 5. 日内亏损熔断
if self.daily_pnl < float(self.config['daily_loss_limit_pct']) * \
self._get_total_asset():
self.circuit_broken = True
self.circuit_break_ts = now
return RiskResult(False, "日内亏损熔断触发")
return RiskResult(True, "")
9. 部署方案
9.1 硬件要求
| 组件 | OS | CPU | 内存 | 存储 | 网络 |
|---|---|---|---|---|---|
| 通达信 | Windows 10/11 | i5 / R5+ | 8GB+ | SSD 100GB+ | 宽带 50Mbps+ |
| 策略引擎 | Windows 10/11 | 同主机 | 同主机 | 同主机 | 同主机 |
| 日志/数据 | 同主机 | — | — | SSD 额外 50GB | — |
关键约束:miniQMT 和通达信必须在同一台 Windows 主机上运行。miniQMT 没有 macOS/Linux 版本,不支持远程连接行情。整个系统建议部署在一台专用于交易的 Windows 电脑上,不要与其他高负载应用混跑。
9.2 目录结构
D:\quant\
├── tdx\ # 通达信安装目录
│ ├── TdxW.exe
│ └── ...
├── signals\ # 信号文件交互目录
│ ├── signals.jsonl
│ ├── signals.jsonl.lock # 写锁文件
│ └── archive\ # 历史信号归档
├── engine\ # 策略引擎
│ ├── main.py
│ ├── config.yaml
│ ├── risk_controller.py
│ ├── strategy_router.py
│ ├── order_executor.py
│ └── requirements.txt
├── logs\ # 日志目录
│ ├── engine.log
│ ├── trades.log # 交易明细审计日志
│ └── errors.log
├── data\ # 持久化数据
│ ├── processed_ids.parquet
│ └── daily_pnl.json
└── scripts\ # 辅助脚本
├── start.bat
├── stop.bat
└── health_check.bat
9.3 启动脚本
@REM start.bat — 一键启动策略引擎
@echo off
set PYTHONPATH=D:\quant\engine
cd /d D:\quant\engine
REM 检查通达信是否运行
tasklist | findstr /i "TdxW.exe" >nul
if %errorlevel% neq 0 (
echo [WARN] 通达信未运行,请先启动通达信
)
REM 启动策略引擎
python main.py --config config.yaml >> ..\logs\engine.log 2>&1
if %errorlevel% equ 0 (
echo [OK] 策略引擎已启动
) else (
echo [ERR] 启动失败,请检查日志
)
10. 性能指标与容量规划
10.1 性能目标
| 指标 | 目标值 | 测量方法 |
|---|---|---|
| 端到端延迟 (P50) | < 200ms | 信号时间戳 → 委托到达柜台 |
| 端到端延迟 (P99) | < 500ms | 同上 |
| 信号吞吐量 | > 100 条/秒 | 引擎处理速度 |
| 委托吞吐量 | > 50 笔/秒 | passorder 调用速度 |
| 引擎可用性 | 99.9% | 交易时段内正常运行率 |
| 风控检查耗时 | < 5ms/次 | 单次全项风控检查 |
10.2 容量约束
并发品种
- 同时监控上限: 50 个合约
- 超过 50 个时需分片处理
- 建议按品种分组部署多个引擎实例
委托频率
- 建议上限: 30 笔/分钟
- 超过时触发频率风控
- 交易所端也有频率限制
日志存储
- 单日日志量: ~50MB(含交易记录)
- 建议保留: 90 天
- 日志轮转: 按天分片 + 自动压缩
系统资源
- 引擎 CPU: < 5%(空闲时)
- 引擎内存: ~200MB
- 磁盘 IO: 极低(仅日志写入)
11. 监控与告警
11.1 监控指标
| 分类 | 指标 | 告警阈值 | 响应动作 |
|---|---|---|---|
| 进程 | 引擎进程存活 | 进程退出 | 自动重启 + 通知 |
| 通达信进程存活 | 进程退出 | 桌面通知 + 尝试重启 | |
| 网络 | 柜台连接状态 | 断开 > 5s | 告警 + 自动重连 |
| 行情延迟 | > 1000ms | 告警 + 切换主站 | |
| 交易 | 委托失败率 | > 10% / 小时 | 暂停策略 + 人工介入 |
| 日内亏损 | 达到熔断阈值 | 自动熔断 + 通知 | |
| 系统 | 磁盘剩余空间 | < 10GB | 清理日志 + 告警 |
| 内存使用率 | > 80% | 告警 + 检查泄漏 |
11.2 告警通道
| 优先级 | 通道 | 适用场景 |
|---|---|---|
| P0 | 手机推送 (钉钉/企业微信) | 熔断触发、进程崩溃、委托异常 |
| P1 | 桌面弹窗 + 声音告警 | 风控拦截、连接断开 |
| P2 | 日志记录 + 次日报告 | 配置变更、常规状态 |
# 告警通知示例 — 企业微信 Webhook
import requests
def send_alert(message: str, level: str = "P0"):
webhook_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
payload = {
"msgtype": "markdown",
"markdown": {
"content": f"【{level}】{message}"
}
}
requests.post(webhook_url, json=payload, timeout=5)
11.3 交易日检查清单
【开盘前】
☐ 确认通达信已启动,行情连接正常
☐ 确认 miniQMT 已登录,柜台连接正常
☐ 确认策略引擎已启动,日志无报错
☐ 确认风控参数正确(仓位上限、止损线)
☐ 确认信号输出路径正确,文件可写
☐ 手动复位熔断状态(如昨日触发)
【盘中】
☐ 监控告警通道畅通(手机通知正常接收)
☐ 出现异常委托等 P0 事件立即暂停策略
☐ 每 30 分钟检查引擎运行状态
【收盘后】
☐ 导出当日交易记录,核对成交明细
☐ 分析信号准确率,调整指标参数
☐ 归档当日日志和信号文件
☐ 备份 processed_ids 数据
12. 容灾与恢复
12.1 故障场景应对
| 故障场景 | 影响 | 自动恢复措施 | 人工介入 |
|---|---|---|---|
| 通达信崩溃 | 信号停止生成 | 无自动恢复(需人工重启) | 重启通达信,确认预警设置恢复 |
| 引擎崩溃 | 交易执行停止 | 看门狗自动重启引擎 | 检查重启后风控状态是否正常 |
| miniQMT 断连 | 无法下单 | 自动重连(间隔 1s, 最多 30 次) | 重连失败时人工确认账户状态 |
| 主机断网 | 全链路中断 | 无自动恢复 | 检查网络,确认恢复后检查持仓 |
| 磁盘写满 | 日志/信号写入失败 | 自动清理 30 天前的归档日志 | 扩展磁盘或迁移到更大容量的分区 |
12.2 看门狗实现
# watchdog.py — 独立的进程看门狗,由 Windows Task Scheduler 拉起
import psutil
import subprocess
import time
class ProcessWatchdog:
"""监控关键进程,崩溃时自动重启"""
PROCESSES = {
'tdx': {'name': 'TdxW.exe', 'path': r'D:\quant\tdx\TdxW.exe'},
'engine': {'name': 'python.exe', 'path': r'D:\quant\engine\main.py',
'args': ['--config', 'config.yaml']},
}
def check(self):
for name, proc in self.PROCESSES.items():
running = any(p.info['name'] == proc['name']
for p in psutil.process_iter(['name']))
if not running:
logging.warning(f"进程 {name} 未运行,尝试重启...")
self._restart(name, proc)
def _restart(self, name, proc):
if name == 'engine':
subprocess.Popen(['python', proc['path']] + proc.get('args', []))
elif name == 'tdx':
subprocess.Popen([proc['path']])
13. 实施检查清单
第一阶段:基础环境
- 确认券商支持 QMT / miniQMT
- 开通期权期货交易权限
- 安装 Windows 交易主机
- 安装通达信 + 配置行情
- 安装 Python 3.10+ 环境
- 安装 xtquant SDK
第二阶段:联调测试
- 通达信条件预警写入文件测试
- 文件监控脚本读取信号测试
- 风控模块单元测试
- miniQMT 模拟交易测试
- 端到端延迟测量
第三阶段:模拟运行
- 模拟盘运行至少 5 个交易日
- 异常场景模拟(断网/崩溃)
- 策略参数调优
- 风控阈值验证
- 日志审计流程确认
第四阶段:实盘上线
- 最小资金位启动(验证用)
- 逐笔核对成交记录
- 监控告警通道验证
- 制定应急预案文档
- 逐步增加资金到目标仓位
14. 术语表
| 术语 | 全称 / 说明 |
|---|---|
| QMT | Quantitative Trading Platform,迅投科技开发的量化交易平台 |
| miniQMT | QMT 的极简运行模式,支持外部 Python 调用 xtquant SDK |
| xtquant | 迅投提供的 Python SDK 包,包含行情(xdata)和交易(xttrader)接口 |
| CTP | 综合交易平台(上期技术),期货市场的标准交易接口 |
| LDP | 极速交易柜台,券商提供的低延迟交易通道 |
| passorder | xtquant 中的核心委托函数,用于发送交易指令 |
| IO | 沪深 300 股指期权合约代码前缀 |
| IF / IC / IH | 沪深 300 / 中证 500 / 上证 50 股指期货合约代码 |
| Greeks | 期权风险度量指标(Delta, Gamma, Theta, Vega, Rho) |
| 熔断 (Circuit Breaker) | 达到预设亏损阈值后自动停止交易的保护机制 |
| 布隆过滤器 (Bloom Filter) | 高效的集合成员检测数据结构,用于去重场景 |
| JSON Lines | 每行一个 JSON 对象的文件格式,适合流式处理 |