通达信 + miniQMT 期权期货量化交易 技术方案

基于通达信技术指标信号触发,通过 miniQMT 极速执行通道实现期权期货自动化交易

版本 v2.1 日期 2026-05-15 品类 股指期权 / 商品期货 / 商品期权 执行平台 miniQMT (xtquant)

1. 背景与目标

1.1 问题域

在期权期货交易中,交易者面临以下核心痛点:

1.2 方案目标

1.3 适用读者

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.xWindows 10/11
信号文件作为层间契约,承载结构化信号数据JSON Lines (.jsonl) / CSVNTFS 文件系统
监控引擎轮询或事件驱动读取信号文件Python 3.10+ / watchdogWindows (与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: 文件变更检测< 50mswatchdog 事件通知延迟
T3: 信号解析 + 风控< 50msJSON 解析 + 内存校验
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_idstring是唯一信号 ID,格式:YYYYMMDD_HHMMSS_SSS
tsint64是Unix 时间戳(毫秒)
symbolstring是合约代码,格式遵循交易所标准
directionenum是buy_open / sell_open / buy_close / sell_close
pricefloat是目标价格(0 表示市价)
qtyint是手数/张数
reasonstring否信号触发原因,用于日志和审计
indicatorobject否触发时刻的指标快照,用于事后分析

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 通达信条件预警设置

  1. 菜单:功能 → 条件预警 → 条件预警设置
  2. 勾选需要监控的指标公式和股票/合约
  3. 输出设置:"预警输出到文件",路径 D:\signals\
  4. 格式选择"自定义格式",配置如下:
# 通达信预警自定义格式模板
# 导出字段映射(通过通头信输出设置界面配置)
# {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 硬件要求

组件OSCPU内存存储网络
通达信Windows 10/11i5 / 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. 术语表

术语全称 / 说明
QMTQuantitative Trading Platform,迅投科技开发的量化交易平台
miniQMTQMT 的极简运行模式,支持外部 Python 调用 xtquant SDK
xtquant迅投提供的 Python SDK 包,包含行情(xdata)和交易(xttrader)接口
CTP综合交易平台(上期技术),期货市场的标准交易接口
LDP极速交易柜台,券商提供的低延迟交易通道
passorderxtquant 中的核心委托函数,用于发送交易指令
IO沪深 300 股指期权合约代码前缀
IF / IC / IH沪深 300 / 中证 500 / 上证 50 股指期货合约代码
Greeks期权风险度量指标(Delta, Gamma, Theta, Vega, Rho)
熔断 (Circuit Breaker)达到预设亏损阈值后自动停止交易的保护机制
布隆过滤器 (Bloom Filter)高效的集合成员检测数据结构,用于去重场景
JSON Lines每行一个 JSON 对象的文件格式,适合流式处理