Skip to content

提供一个通用的restful接口,让迅投QMT可以跨平台使用,便于在Windows Server启动miniQMT,在Linux Server做量化处理。

License

Notifications You must be signed in to change notification settings

liqimore/quant-qmt-proxy

Repository files navigation

xtquant-proxy

🚧 开发状态: v0.0.1 迭代中 | 当前版本覆盖 REST/gRPC/WebSocket 多协议,默认用于本地联调与策略验证,请勿直接用于生产环境

基于 FastAPI + gRPC + WebSocket 的 xtquant 量化交易代理服务

Python FastAPI gRPC License

提供 RESTful APIgRPCWebSocket 多协议接口,封装国金 QMT xtquant SDK 的数据和交易功能

快速开始API 文档技术架构测试覆盖


✨ 核心特性

🎯 双协议支持

  • 🌐 REST API: 基于 FastAPI,提供 HTTP/HTTPS 接口,自动生成 Swagger 文档
  • gRPC: 高性能 RPC 框架,支持流式调用和双向通信
  • 🔔 WebSocket: 提供行情订阅实时推送,内置心跳与限流控制
  • 🔄 统一服务: 两种协议共享相同的业务逻辑层,一次部署同时服务

🛡️ 安全可靠

  • 🔐 API Key 认证: 多环境 API Key 管理
  • 🚦 交易拦截: dev 模式自动拦截真实交易,保护账户安全
  • 📝 完整日志: 基于 Loguru 的结构化日志,支持日志轮转和压缩
  • 🔒 异常保护: 全局异常处理,xtdata 连接超时保护

📊 功能完整

  • 📈 市场数据: K线、分时、tick、财务数据、板块数据、行情订阅
  • 💼 交易功能: 下单、撤单、持仓查询、订单管理
  • ❤️ 健康检查: REST 和 gRPC 双协议健康检查
  • 🎯 三种模式: mock/dev/prod 灵活切换

⚙️ 配置灵活

  • 📋 统一配置: config.yml 集中管理所有配置
  • 🔄 环境切换: 通过 APP_MODE 环境变量一键切换模式
  • 🎨 单例模式: 配置和服务单例加载,避免重复初始化

📁 项目结构

quant-qmt-proxy/
├── app/
│   ├── main.py                 # FastAPI 应用入口
│   ├── grpc_server.py          # gRPC 服务器入口
│   ├── grpc_client.py          # gRPC 客户端封装
│   ├── config.py               # 配置管理(单例)
│   ├── dependencies.py         # 依赖注入(单例服务)
│   ├── models/                 # Pydantic 数据模型
│   │   ├── data_models.py      # 数据相关模型
│   │   └── trading_models.py   # 交易相关模型
│   ├── routers/                # REST API 路由
│   │   ├── data.py             # 数据服务 API
│   │   ├── trading.py          # 交易服务 API
│   │   ├── health.py           # 健康检查 API
│   │   └── websocket.py        # WebSocket 行情推送
│   ├── grpc_services/          # gRPC 服务实现
│   │   ├── data_grpc_service.py      # 数据服务 gRPC
│   │   ├── trading_grpc_service.py   # 交易服务 gRPC
│   │   └── health_grpc_service.py    # 健康检查 gRPC
│   ├── services/               # 业务服务层(REST 和 gRPC 共享)
│   │   ├── data_service.py     # 数据服务(xtdata 封装)
│   │   ├── trading_service.py  # 交易服务(xttrader 封装)
│   │   └── subscription_manager.py  # 行情订阅管理器
│   └── utils/                  # 工具函数
│       ├── exceptions.py       # 自定义异常
│       ├── helpers.py          # 辅助函数
│       └── logger.py           # 日志配置
├── proto/                      # Protocol Buffers 定义
│   ├── common.proto            # 公共消息定义
│   ├── data.proto              # 数据服务定义
│   ├── trading.proto           # 交易服务定义
│   └── health.proto            # 健康检查定义
├── generated/                  # protobuf 生成的 Python 代码
│   ├── data_pb2.py             # 数据服务消息
│   ├── data_pb2_grpc.py        # 数据服务 stub
│   ├── trading_pb2.py          # 交易服务消息
│   ├── trading_pb2_grpc.py     # 交易服务 stub
│   └── ...
├── tests/                      # 测试套件
│   ├── rest/                   # REST API 测试
│   │   ├── test_data_api.py
│   │   ├── test_trading_api.py
│   │   └── test_health_api.py
│   └── grpc/                   # gRPC 测试
│       ├── test_data_grpc_service.py
│       ├── test_trading_grpc_service.py
│       └── test_health_grpc_service.py
├── xtquant/                    # xtquant SDK(国金 QMT)请自行下载
├── scripts/                    # 工具脚本
│   └── generate_proto.py       # protobuf 代码生成脚本
├── logs/                       # 日志文件目录
├── config.yml                  # 统一配置文件
├── requirements.txt            # Python 依赖
├── run.py                      # 启动脚本(同时启动 REST + gRPC)
└── README.md                   # 项目说明

📈 最新进展

🎉 v0.0.1-dev (2025-11-02)

核心修复与增强:

  • 修复 gRPC 行情订阅: 解决 asyncio.Queue 在 gRPC 线程中无法创建的问题,实现惰性队列初始化
  • 复权参数透传: 实现 adjust_type (前复权/后复权) 正确传递到 xtdata API
  • 空标的校验: 添加多层验证(Pydantic + 业务逻辑 + gRPC),禁止创建空股票列表订阅
  • 事件循环管理: gRPC 服务自动检测并创建事件循环,确保订阅管理器正常运行
  • 测试覆盖增强: gRPC 订阅测试全部通过 (7 passed, 1 skipped)

测试结果:

tests/grpc/test_subscription_grpc.py::TestSubscriptionGrpc
✅ test_subscribe_quote_mock_mode - 基本订阅功能
✅ test_unsubscribe_quote - 取消订阅
✅ test_get_subscription_info - 获取订阅信息
✅ test_subscribe_with_adjust_type - 复权类型订阅
✅ test_subscribe_with_empty_symbols - 空标的校验
7 passed, 1 skipped in 1.35s

近期用例测试结果

image

🚀 快速开始

1. 前置要求

  • Python 3.10+
  • 国金 QMT 客户端(dev/prod 模式需要)
  • Windows 系统(QMT 仅支持 Windows)

2. 安装依赖

pip install -r requirements.txt

建议先使用 python -m venv .venv 创建虚拟环境并激活,再安装依赖;根据实际凭证将 env.example 复制为 .env 后补全机密配置。

3. 配置 QMT 路径

编辑 config.yml,修改 QMT 安装路径:

xtquant:
  qmt_userdata_path: "C:/quant/国金QMT交易端模拟/userdata_mini"

4. 启动服务

服务默认同时启动 REST API (端口 8000) 和 gRPC (端口 50051)。

# mock 模式 - 不连接 QMT,使用模拟数据(无需 QMT)
$env:APP_MODE="mock"; python run.py

# dev 模式 - 连接 QMT,获取真实数据,禁止交易(默认,推荐开发使用)
$env:APP_MODE="dev"; python run.py

# prod 模式 - 连接 QMT,获取真实数据,允许交易(生产环境)
$env:APP_MODE="prod"; python run.py

5. 访问服务

启动后可访问:

服务 地址 说明
REST API http://localhost:8000 RESTful API 主入口
gRPC localhost:50051 gRPC 服务端口
Swagger UI http://localhost:8000/docs 交互式 API 文档
ReDoc http://localhost:8000/redoc API 文档(阅读友好)
健康检查 http://localhost:8000/health/ 服务健康状态
WebSocket 测试页 http://localhost:8000/ws/test 行情推送调试页面

6. 运行测试

# REST API 测试
pytest tests/rest/ -v

# gRPC 测试
pytest tests/grpc/ -v

# 所有测试
pytest tests/ -v

🎯 运行模式说明

项目支持三种运行模式,通过环境变量 APP_MODE 切换:

模式 连接 xtquant 真实交易 使用场景
mock ❌ 否 ❌ 禁止 开发测试,无需 QMT 客户端
dev ✅ 是 ❌ 禁止 开发调试,获取真实数据但不下单
prod ✅ 是 ✅ 允许 生产环境,真实交易

模式特性

🎭 mock 模式

  • ✅ 不需要运行 QMT 客户端
  • ✅ 使用模拟数据响应 API 请求
  • ✅ 适合前端开发、接口测试
  • 📝 订单 ID 前缀: mock_order_*

🔧 dev 模式(推荐开发使用)

  • ✅ 需要运行 QMT 客户端
  • ✅ 获取真实的市场数据、财务数据
  • 交易请求被拦截,返回模拟订单
  • ✅ 适合策略开发、回测验证
  • 📝 订单 ID 前缀: mock_order_*
  • 🔒 日志记录所有拦截操作

🚀 prod 模式(谨慎使用)

  • ✅ 需要运行 QMT 客户端
  • ✅ 获取真实数据
  • ⚠️ 允许真实交易下单
  • ⚠️ 适合生产环境、实盘交易
  • 📝 订单 ID: xttrader 返回的真实订单号

📡 API 接口说明

REST API 接口

数据服务 (/api/v1/data/)

  • POST /api/v1/data/market - 获取市场行情数据
  • POST /api/v1/data/financial - 获取财务数据
  • GET /api/v1/data/sectors - 获取板块列表
  • POST /api/v1/data/sector - 获取板块成分股
  • POST /api/v1/data/index-weight - 获取指数权重
  • GET /api/v1/data/trading-calendar/{year} - 获取交易日历
  • GET /api/v1/data/instrument/{stock_code} - 获取合约信息
  • GET /api/v1/data/etf/{etf_code} - 获取 ETF 基础信息
  • POST /api/v1/data/subscription - 创建行情订阅(支持前复权/后复权)
  • GET /api/v1/data/subscription/{subscription_id} - 查询订阅详情
  • GET /api/v1/data/subscriptions - 获取订阅列表
  • DELETE /api/v1/data/subscription/{subscription_id} - 取消订阅

交易服务 (/api/v1/trading/)

  • POST /api/v1/trading/connect - 连接交易账户
  • POST /api/v1/trading/disconnect/{session_id} - 断开账户
  • GET /api/v1/trading/account/{session_id} - 获取账户信息
  • GET /api/v1/trading/positions/{session_id} - 获取持仓信息
  • POST /api/v1/trading/order/{session_id} - 提交订单
  • POST /api/v1/trading/cancel/{session_id} - 撤销订单
  • GET /api/v1/trading/orders/{session_id} - 获取订单列表
  • GET /api/v1/trading/trades/{session_id} - 获取成交记录
  • GET /api/v1/trading/asset/{session_id} - 获取资产信息
  • GET /api/v1/trading/risk/{session_id} - 获取风险指标
  • GET /api/v1/trading/strategies/{session_id} - 获取策略列表
  • GET /api/v1/trading/status/{session_id} - 查询连接状态

系统服务 (/health/)

  • GET /health/ - 健康检查
  • GET /health/ready - 就绪检查
  • GET /health/live - 存活检查

gRPC 接口

数据服务 (DataService)

  • GetMarketData() - 获取市场数据
  • GetFinancialData() - 获取财务数据
  • GetSectorList() - 获取板块列表
  • GetStockListInSector() - 获取板块成分股
  • GetIndexWeight() - 获取指数权重
  • GetTradingCalendar() - 获取交易日历
  • GetInstrumentDetail() - 获取合约信息
  • SubscribeQuote() - 订阅行情(流式推送,支持复权)
  • SubscribeWholeQuote() - 订阅全推行情(流式推送)
  • UnsubscribeQuote() - 取消订阅
  • GetSubscriptionInfo() - 获取订阅详情
  • ListSubscriptions() - 列出所有订阅

交易服务 (TradingService)

  • Connect() - 连接交易账户
  • Disconnect() - 断开连接
  • GetAccountInfo() - 获取账户信息
  • GetPositions() - 获取持仓
  • SubmitOrder() - 提交订单
  • CancelOrder() - 撤销订单
  • GetOrders() - 查询订单
  • GetTrades() - 查询成交
  • GetAsset() - 查询资产
  • GetRiskInfo() - 查询风险
  • GetStrategies() - 查询策略列表

健康检查服务 (HealthService)

  • Check() - 健康检查
  • Watch() - 健康状态订阅(流式)

WebSocket 接口

  • GET /ws/quote/{subscription_id} - 行情订阅推送,支持 ping/pong 心跳
  • GET /ws/test - 内置测试页面,可浏览器直接调试订阅

✨ 行情订阅特性:

  • 支持多股票同时订阅
  • 支持复权类型选择(none/front/back)
  • 自动队列管理,防止内存溢出
  • gRPC 流式推送,低延迟高吞吐
  • WebSocket 实时推送,内置心跳与重连

🔧 技术架构

核心技术栈

  • FastAPI: 现代高性能 Web 框架
  • gRPC: 高性能 RPC 框架
  • Protocol Buffers: 数据序列化协议
  • Pydantic: 数据验证和序列化
  • uvicorn: ASGI 服务器
  • Loguru: 结构化日志库
  • xtquant: 国金 QMT Python SDK

设计模式

  • 依赖注入: 使用 FastAPI 的 Depends 系统
  • 单例模式: 服务实例全局唯一,避免重复初始化
  • 策略模式: 不同模式下的不同行为
  • 拦截器模式: 交易请求拦截保护
  • 适配器模式: REST 和 gRPC 共享业务逻辑

架构优势

  • 🎯 分层架构: Router → Service → SDK,职责清晰
  • 🔄 代码复用: REST 和 gRPC 共享同一套业务服务
  • 高性能: gRPC 二进制传输,FastAPI 异步处理,惰性队列初始化
  • 🛡️ 可靠性: 完整的异常处理、多层数据校验、事件循环自动管理
  • 📈 可扩展: 易于添加新接口和功能
  • 🧵 线程安全: gRPC 订阅支持多线程环境,自动处理事件循环

🧪 测试覆盖

REST API 测试 (tests/rest/)

  • ✅ 健康检查测试
  • ✅ 数据服务测试(市场数据、财务数据、板块数据)
  • ✅ 交易服务测试(下单、撤单、持仓查询)
  • ✅ 行情订阅测试(订阅创建、查询、取消、空标的校验)

gRPC 测试 (tests/grpc/)

  • ✅ 健康检查服务测试(Check、Watch)
  • ✅ 数据服务测试(14 个接口)
  • ✅ 交易服务测试(8 个接口)
  • ✅ 行情订阅测试(订阅、取消、复权、空标的、流式推送)
  • ✅ 订阅管理器单元测试(初始化、多订阅、流式数据)

测试特性

  • 🎯 使用 pytest 框架
  • 🔄 支持 mock/dev/prod 三种模式测试
  • 📊 详细的测试报告和日志
  • ✅ gRPC 订阅测试 7 passed, 1 skipped
  • ✅ 订阅管理器测试 3 passed, 1 skipped
  • 🚀 CI/CD 集成就绪

📊 功能实现进度

已实现功能 ✅

💡 接口覆盖率: 20/125+ ≈ 16% | ✨ 最新更新: gRPC 行情订阅完整实现

数据模块 (14/50+)

  • ✅ 市场数据获取(K线、分时、tick)
  • ✅ 财务数据查询
  • ✅ 板块数据管理
  • ✅ 指数权重查询
  • ✅ 交易日历查询
  • ✅ 合约信息查询
  • ✅ ETF 信息查询(占位)
  • ✅ 行情订阅管理(REST API 完整实现)
  • ✅ gRPC 行情订阅(流式推送,支持复权)
  • ✅ WebSocket 行情推送(实时数据,心跳保活)
  • ✅ 订阅队列管理(惰性初始化,防溢出)
  • ✅ 空标的校验(多层验证)
  • ✅ 复权参数透传(前复权/后复权)
  • ✅ 事件循环自动管理(gRPC 线程安全)

交易模块 (6/60+)

  • ✅ 账户连接管理
  • ✅ 下单/撤单
  • ✅ 持仓查询
  • ✅ 订单查询
  • ✅ 交易模式拦截
  • ✅ 资产/风险/策略查询(mock 数据)

系统模块

  • ✅ 配置管理(单例模式)
  • ✅ 日志系统(Loguru,结构化日志)
  • ✅ 健康检查(REST + gRPC)
  • ✅ API 认证(API Key)
  • ✅ 异常处理(统一错误码映射)
  • ✅ 行情订阅管理(SubscriptionManager)
  • ✅ WebSocket 推送(心跳保活,限流控制)
  • ✅ 事件循环管理(gRPC 线程安全)
  • ✅ 队列管理(惰性初始化,自动溢出控制)

待实现功能 🚧

高优先级 (P0)

  • 🔄 L2 行情数据接口(Level2 逐笔数据)
  • ❌ 资产查询接口(真实数据)
  • ❌ 成交查询接口(真实数据)
  • ❌ 异步下单/撤单
  • ❌ 交易回调推送(WebSocket)

中优先级 (P1)

  • ❌ 历史数据下载管理
  • ❌ 财务数据下载管理
  • ❌ 新股申购功能
  • ❌ 行情订阅性能优化(批量订阅)

低优先级 (P2)

  • ❌ 信用交易(融资融券)
  • ❌ 资金管理(银证转账)
  • ❌ 约券功能
  • ❌ 板块管理

当前进度: 数据模块 14/50+,交易模块 6/60+,系统模块核心功能完成


📝 配置说明

config.yml 结构

app:
  name: "xtquant-proxy"
  version: "1.0.0"

# gRPC 配置
grpc:
  enabled: true
  host: "0.0.0.0"
  port: 50051
  max_workers: 10

# 日志配置
logging:
  file: "logs/app.log"
  error_file: "logs/error.log"
  rotation: "10 MB"
  retention: "30 days"
  compression: "zip"

# xtquant 配置
xtquant:
  qmt_userdata_path: "C:/quant/国金QMT交易端模拟/userdata_mini"

# 运行模式配置
modes:
  mock:
    connect_xtquant: false
    allow_real_trading: false
    
  dev:
    connect_xtquant: true
    allow_real_trading: false  # 🔒 拦截交易
    
  prod:
    connect_xtquant: true
    allow_real_trading: true   # ⚠️ 允许真实交易

💡 开发建议

本地开发流程

  1. 使用 mock 模式 进行前端开发和接口测试
  2. 使用 dev 模式 连接真实 QMT 进行策略开发
  3. 充分测试后切换到 prod 模式 进行实盘交易

API 认证

默认使用 API Key 认证,请求头格式:

X-API-Key: your-api-key

dev 模式可用的 API Key(在 config.yml 中配置):

  • dev-api-key-001
  • dev-api-key-002

日志查看

# 查看应用日志
Get-Content logs/app.log -Wait -Tail 50

# 查看错误日志
Get-Content logs/error.log -Wait -Tail 50

扩展开发

  1. app/services/ 中添加新的业务服务
  2. app/models/ 中定义 Pydantic 数据模型
  3. app/routers/ 中添加 REST API 路由
  4. proto/ 中定义 gRPC 服务和消息
  5. 运行 python scripts/generate_proto.py 生成代码
  6. app/grpc_services/ 中实现 gRPC 服务
  7. tests/ 中添加测试用例

⚠️ 注意事项

安全警告

  • ⚠️ 生产环境必须修改默认 API Key
  • ⚠️ prod 模式会真实下单,请谨慎使用
  • ⚠️ 建议使用 HTTPS 和更严格的 CORS 配置
  • ⚠️ 不要将包含真实账号密码的配置文件提交到 Git

已知限制

  • xtquant 仅支持 Windows 系统
  • 需要 QMT 客户端正在运行(dev/prod 模式)
  • xtdata 连接有 5 秒超时限制
  • 连接失败会自动降级到模拟模式
  • gRPC 最大消息大小限制为 50MB
  • 订阅队列默认最大长度 1000,超出会丢弃旧数据
  • 单实例最大订阅数默认限制为 100

性能建议

  • ✅ 使用单例模式避免重复初始化
  • ✅ xtdata 连接成功后会复用
  • ✅ gRPC 使用连接池提升性能
  • ✅ 订阅队列惰性初始化,减少内存占用
  • ✅ 队列满时自动丢弃旧数据,防止内存溢出
  • 📋 考虑添加 Redis 缓存高频查询数据(可选)
  • 📋 考虑添加数据库持久化订阅配置(可选)
  • 📋 批量订阅优化,减少 xtdata 调用次数(规划中)

🐛 故障排查

服务启动失败

  1. 检查 Python 版本 >= 3.10
  2. 确认所有依赖已安装: pip install -r requirements.txt
  3. 检查端口 8000 和 50051 是否被占用
  4. 查看启动日志: logs/app.log

xtdata 连接失败

  1. 确认 QMT 客户端正在运行
  2. 检查 config.yml 中的 QMT 路径是否正确
  3. 查看错误日志: logs/error.log
  4. 尝试重启 QMT 客户端

API 返回 401 错误

  1. 检查请求头是否包含 X-API-Key: xxx
  2. 确认 API Key 在 config.yml 的当前模式配置中
  3. 检查 API Key 是否正确

gRPC 连接失败

  1. 确认 gRPC 服务已启动(查看启动日志)
  2. 检查端口 50051 是否被占用
  3. 确认客户端使用正确的地址: localhost:50051
  4. 检查防火墙设置

WebSocket 无行情推送

  1. 使用 REST 接口确认订阅状态为 active
  2. 检查 WebSocket 是否按需发送 ping 保持心跳
  3. mock 模式下推送为模拟数据,若需真实行情请使用 dev/prod 模式
  4. 查看 logs/app.log 是否有订阅队列过载或 xtdata 异常
  5. 检查股票代码列表是否为空(已添加多层校验)

gRPC 订阅报错

  1. 确认使用 mock 模式测试: $env:APP_MODE="mock"
  2. 检查是否传入空股票列表(会返回 INVALID_ARGUMENT)
  3. 查看是否有 RuntimeError 关于 asyncio.Queue(已修复)
  4. 检查复权参数是否正确: none/front/back

交易被拦截

  • 这是正常行为!dev 模式会拦截所有交易请求
  • 如需真实交易,切换到 prod 模式
  • 检查订单 ID 前缀区分模拟/真实订单

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

开发环境设置

# 克隆仓库
git clone https://github.com/liqimore/quant-qmt-proxy.git
cd quant-qmt-proxy

# 安装依赖
pip install -r requirements.txt

# 生成 protobuf 代码
python scripts/generate_proto.py

# 运行测试
pytest tests/ -v

提交规范

  • feat: 新功能
  • fix: 修复 bug
  • docs: 文档更新
  • refactor: 代码重构
  • test: 测试相关
  • chore: 构建/工具相关

📄 许可证

MIT License - 详见 LICENSE 文件


🔗 相关链接


如果觉得项目有帮助,请给个 ⭐ Star 支持一下!

Made with ❤️ by liqimore

About

提供一个通用的restful接口,让迅投QMT可以跨平台使用,便于在Windows Server启动miniQMT,在Linux Server做量化处理。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors 2

  •  
  •  

Languages