Files
big-qmt/docs/api.md
2026-09-07 21:01:36 +08:00

14 KiB
Raw Blame History

QMT REST API 参考

根据 api/qmt_rest_new.py 的路由、Handler 和格式化函数重新生成。更新日期2026-09-07。启动说明见 README.md

1. 公共约定

  • Base URLhttp://<host>:10086,监听 0.0.0.0
  • 所有已注册接口均要求 X-Token: <服务端 TOKEN>,没有免鉴权接口。
  • POST 请求体为 JSON 对象,使用 Content-Type: application/json
  • 账户取自服务端 QMT_ACCOUNT_ID,账户类型固定为 stock,请求不能切换账户。
  • 成功响应没有统一包装,具体形状见各接口。
  • 资产、持仓、委托、成交字段为小写下划线;下单请求仍使用驼峰字段;行情及原始查询保留 QMT 字段。
  • 字段类型按 QMT 属性约定列出;除资产金额四舍五入外,格式化函数不强制类型转换、不填默认值、不转换枚举和日期。
  • 枚举含义、原始日期格式、行情和其他透传结果由 QMT 决定,本文件不扩展源码未定义的契约。

2. 接口清单

方法 路径 用途
GET /api/context/info 策略上下文
GET /api/get/{handler_type} 单证券查询
GET /api/portfolio 聚合资产、持仓、委托
GET /api/portfolio/assets 资产
GET /api/portfolio/positions 持仓
GET /api/portfolio/order 委托数组
GET /api/portfolio/deal 成交数组
GET /api/portfolio/org/{handler_type} 原始记录
POST /api/data/full_tick 实时行情
POST /api/trade/passorder 下单
POST /api/trade/cancel_by_id 撤单
POST /api/trade/ipo_data 发行数据
GET /api/sys/python_version Python 版本

3. 策略上下文

GET /api/context/info,无参数,返回以下对象字段:

字段 来源
period ContextInfo.period
barpos ContextInfo.barpos
time_tick_size ContextInfo.time_tick_size
stockcode ContextInfo.stockcode
dividend_type ContextInfo.dividend_type
market ContextInfo.market
do_back_test ContextInfo.do_back_test
benchmark ContextInfo.benchmark
capital ContextInfo.capital
timetag ContextInfo.timetag
universe ContextInfo.get_universe()

属性按原值输出;stockcode 是此接口的实际字段名。

4. 单证券查询

GET /api/get/{handler_type}?stock_code=600000.SH

stock_code 为必填 Query 字符串,去除首尾空格后不能为空,整体传入底层函数,不拆分逗号。

handler_type 调用
stock_name ContextInfo.get_stock_name(stock_code)
open_date ContextInfo.get_open_date(stock_code)
last_volume ContextInfo.get_last_volume(stock_code)
total_share ContextInfo.get_total_share(stock_code)
svol ContextInfo.get_svol(stock_code)
bvol ContextInfo.get_bvol(stock_code)
divid_factors ContextInfo.get_divid_factors(stock_code)
etf_info 全局 get_etf_info(stock_code)
etf_iopv 全局 get_etf_iopv(stock_code)
instrumentdetail ContextInfo.get_instrumentdetail(stock_code)
his_st_data ContextInfo.get_his_st_data(stock_code)

响应示例:

{"stock_code":"600000.SH","ref":"示例证券名称"}

ref 透传底层结果,可为字符串、数值、对象、数组或 null无法直接序列化的值通过 str() 转换。缺失或空代码返回 HTTP 500不支持的路径类型通常因路由不匹配返回 404。

5. 账户查询

以下接口均无请求参数。

5.1 聚合快照

GET /api/portfolio

依次调用 get_trade_detail_data(account_id, 'stock', 'account' / 'position' / 'order'),分别格式化为以下三个字段:

{
  "assets":{"total":100000.0,"available":30000.0},
  "positions":{},
  "orders":[]
}

不包含成交。三次底层查询顺序执行,不保证同一时刻的原子快照;资产为空时整个请求失败。

5.2 资产

GET /api/portfolio/assets,查询 account,仅使用第一条记录。

字段 JSON 类型 QMT 来源 / 转换
total number m_dBalanceround(..., 2)
available number m_dAvailableround(..., 2)
{"total":100000.0,"available":30000.0}

total 来源为账户余额字段,客户端作为总资产使用;available 为可用资金。无账户数据返回 HTTP 500。四舍五入不保证 JSON 文本固定显示两位小数。

5.3 持仓

GET /api/portfolio/positions,查询 position

返回以证券代码为 key 的对象,每个 value 包含下表全部字段。空结果为 {};同一代码多条记录以后面的覆盖前面的,不合并数量。

字段 JSON 类型 QMT 来源 / 转换
stock_code string m_strInstrumentID + "." + m_strExchangeID
stock_name string m_strInstrumentName
direction integer m_nDirection
volume integer m_nVolume
open_price number m_dOpenPrice
open_cost number m_dOpenCost
float_profit number m_dFloatProfit
market_value number m_dMarketValue
stock_holder string m_strStockHolder
frozen_volume integer m_nFrozenVolume
can_use_volume integer m_nCanUseVolume
on_road_volume integer m_nOnRoadVolume
yesterday_volume integer m_nYesterdayVolume
last_price number m_dLastPrice
profit_rate number m_dProfitRate
future_trade_type integer m_eFutureTradeType
expire_date string m_strExpireDate

volume 为持仓数量,can_use_volume 为可用数量,frozen_volume 为冻结数量,on_road_volume 为在途数量,yesterday_volume 为昨日数量。open_priceopen_costfloat_profitmarket_value 分别保留开仓价、开仓成本、浮动盈亏、市值原值。profit_rate 不乘以 100也不换算单位。

外层示意:{"600000.SH": {上述持仓字段}}

5.4 委托

GET /api/portfolio/order,查询 order,返回对象数组,空结果为 []

字段 JSON 类型 QMT 来源 / 转换
stock_code string m_strInstrumentID + "." + m_strExchangeID
order_sys_id string m_strOrderSysID
ref integer m_nRef
order_ref string m_strOrderRef
direction integer m_nDirection
offset_flag integer m_nOffsetFlag
limit_price number m_dLimitPrice
volume_total_original integer m_nVolumeTotalOriginal
volume_traded integer m_nVolumeTraded
volume_total integer m_nVolumeTotal
traded_price number m_dTradedPrice
trade_amount number m_dTradeAmount
insert_date string m_strInsertDate
insert_time string m_strInsertTime
remark string m_strRemark
order_status integer m_nOrderStatus

order_sys_id 为柜台系统订单号,撤单时使用。volume_total_original 为原始委托数量,volume_traded 为已成交数量,volume_total 为剩余数量。日期、时间、备注及状态枚举保持原值。

服务端不按状态过滤,不排序或分页,不从备注中派生 local_order_idsidecreated_at 等字段。

5.5 成交

GET /api/portfolio/deal,查询 deal,返回对象数组,空结果为 []

字段 JSON 类型 QMT 来源 / 转换
stock_code string m_strInstrumentID + "." + m_strExchangeID
order_sys_id string m_strOrderSysID
ref integer m_nRef
order_ref string m_strOrderRef
direction integer m_nDirection
offset_flag integer m_nOffsetFlag
price number m_dPrice
volume integer m_nVolume
trade_amount number m_dTradeAmount
trade_date string m_strTradeDate
trade_time string m_strTradeTime
remark string m_strRemark
close_profit number m_dCloseProfit

pricevolumetrade_amount 分别为成交价格、数量、金额;close_profit 为平仓盈亏。记录逐条输出,不按订单合并、不去重、不分页,也不接受日期过滤。order_sys_id 是订单号,不应假定其唯一标识一条成交记录。

5.6 原始记录

GET /api/portfolio/org/{handler_type},支持 accountorderdealposition

调用 get_trade_detail_data(account_id, 'stock', handler_type),遍历每条记录的公开、非 callable 属性,响应为 {"data":[记录对象]},空结果为:

{"data":[]}

保留 m_strInstrumentID 等原始属性名,不使用前述格式化函数,不保证固定字段集合,也没有 default=str 序列化兜底。

6. 实时行情

POST /api/data/full_tick

字段 类型 必填 默认 说明
stocks array of string [] 原样传给 ContextInfo.get_full_tick(stocks)
{"stocks":["600000.SH","000001.SZ"]}

响应直接使用 QMT 行情结果,通常为证券代码到行情对象的映射;内部字段不改名、不裁剪。无法直接序列化的值转为字符串。允许空数组,但具体查询范围由 QMT 决定。底层返回空值时返回 HTTP 500。

7. 提交委托

POST /api/trade/passorder

字段 类型 必填 默认 服务端处理
opType integer int()
orderType integer 1101 int()
stockCode string 直接传入
prType integer 11 int()
price number float()
volume integer int()
quickTrade integer 2 int()
strategyName string "" str(...).strip()
orderId string "" str(...).strip(),本地订单标识

底层参数顺序:

passorder(opType, orderType, account_id, stockCode, prType, price,
          volume, strategyName, quickTrade, orderId, ContextInfo)

请求结构示例(实际提交会调用交易函数):

{
  "opType":23,
  "orderType":1101,
  "stockCode":"600000.SH",
  "prType":11,
  "price":10.0,
  "volume":100,
  "quickTrade":2,
  "strategyName":"trend",
  "orderId":"trend-BUY-example"
}

响应示例:

{
  "status":"success",
  "opType":23,
  "stockCode":"600000.SH",
  "strategy_name":"trend",
  "local_order_id":"trend-BUY-example",
  "order_ref":"None"
}

order_refstr(passorder返回值);示例对应底层返回 None,不保证提供柜台系统订单号。它与查询接口中来源于 m_strOrderRef 的同名字段来源不同。

success 仅表示底层调用未抛异常,不代表已经成交或最终报单成功。服务端未按 orderId 做幂等去重,请求超时不能证明未提交。

缺字段、JSON 解析失败及捕获到的类型 / 数值转换错误返回 HTTP 400底层普通异常返回 502底层 HTTPError 原样传播。封装未检查价格、数量正负、代码非空或枚举有效性。表中为 REST 服务默认值SDK 显式传参可能不同。

8. 撤单

POST /api/trade/cancel_by_id

字段 类型 必填 说明
order_id string 柜台系统订单号,即查询的 order_sys_id,不是本地 orderId
{"order_id":"示例柜台订单号"}

先调用 can_cancel_order(order_id, account_id, 'stock'),可撤时调用 cancel(order_id, account_id, 'stock', ContextInfo)

成功响应:

{"status":"success","order_id":"示例柜台订单号"}

不可撤时响应仍为 HTTP 200

{
  "status":"failed",
  "order_id":"示例柜台订单号",
  "message":"Order does not exist or cannot currently be canceled"
}

cancel() 返回值严格为 False,返回 {"status":"failed","order_id":"示例柜台订单号"},无 message,仍为 HTTP 200其他返回值均标记 success。最终结果应再查询委托确认。缺失或空字符串订单号返回 400QMT 普通调用异常返回 500。

9. 发行数据

POST /api/trade/ipo_data

字段 类型 必填 默认 说明
type string "STOCK" 原样传给全局 get_ipo_data(type),不转换大小写或校验枚举
{"type":"STOCK"}

响应直接序列化底层结果,不包装或重命名字段,具体结构由 QMT 提供。使用默认参数也需发送 {}

10. Python 版本

GET /api/sys/python_version,无参数。

{
  "python_version":"<sys.version>",
  "python_version_info":{
    "major":3,
    "minor":11,
    "micro":0,
    "releaselevel":"final",
    "serial":0
  }
}

值仅为示例,实际取自服务进程的 sys.versionsys.version_info

11. 错误响应

匹配到 BaseHandler 的接口默认声明 Content-Type: application/json; charset=utf-8,但 write_error() 实际输出 self._reason 原始文本,不是 JSON 错误对象。客户端应先检查 HTTP 状态,错误正文按文本处理。

场景 HTTP 状态 行为
Token 缺失或不匹配 500 未显式设置 reason正文通常为 Internal Server Error
单证券查询缺代码 / 无资产 / 无行情 500 通常为默认错误原因文本
safe_call() 中普通异常 500 QMT: <函数名> call failed.
下单参数解析 / 转换异常 400 Invalid order parameters: ...
下单底层普通异常 502 QMT order submission failed
撤单订单号缺失或为空 400 通常为 Bad Request
不可撤或底层明确返回 False 200 JSON 中 status=failed
路由不存在 404 Tornado 默认错误处理,不保证上述格式
方法不支持 405 已匹配 Handler 的错误处理

除下单外POST 未统一捕获 JSON 解析错误,非法 JSON 可能返回 500非对象 JSON 也未统一校验。safe_call() 遇到底层 HTTPError 原样传播。

12. 只读调用示例

PowerShell 示例,不提交交易:

$apiBase = 'http://127.0.0.1:10086'
$apiHeaders = @{ 'X-Token' = '<服务端 TOKEN>' }
Invoke-RestMethod -Uri "$apiBase/api/portfolio" -Headers $apiHeaders
Invoke-RestMethod -Uri "$apiBase/api/get/stock_name?stock_code=600000.SH" -Headers $apiHeaders
Invoke-RestMethod -Method Post -Uri "$apiBase/api/data/full_tick" -Headers $apiHeaders -ContentType 'application/json' -Body '{"stocks":["600000.SH"]}'