迅投QMT主程序暴露交易和行情接口

迅投QMT主程序暴露交易和行情接口

本帖最后由 streamer 于 2023-10-31 23:20 编辑



部分券商提供的迅投QMT量化平台并不支持极简客户端,并限制了Python库白名单,让我们使用起来不太方便。本文以国泰君安的君智QMT系统为例,介绍如何在此类受限系统通过内置的tornado库实现类似MiniQMT的功能,在享受极低佣金的同时更自由地利用QMT实现量化交易。

一、程序骨架

首先导入tornado库,设置9000端口为Web访问接口:

# -*- coding: gbk -*-

import json, locale, datetime
import pandas as pd
from tornado.web import Application, RequestHandler
from tornado.ioloop import IOLoop

locale.setlocale(locale.LC_CTYPE, 'chinese')

def init(ContextInfo):
    ContextInfo.accountID = 'xxxxxx' # 改成你的实盘账号
    commissionList = [0, 0.0005, 0.00008, 0.00008, 0.00008, 0] # 设置交易佣金万0.8
    ContextInfo.set_commission(0, commissionList)
   
    # Web服务
    app = make_app()
    app.ContextInfo = ContextInfo
    app.accountID = ContextInfo.accountID
    app.listen(9000)
    IOLoop.instance().start()

这里比较重要的是Web服务配置,通过make_app()函数,我们构建了一个tornado实例,然后将ContextInfo和accountID全局变量传入到实例中,监听9000端口,最后启动Web服务。

二、核心功能

这里分别以交易和行情两个接口介绍暴露的方法:

2.1 交易

下面代码分别包装了获取持仓、当日成交、剩余可用金额的功能,其他下单、撤单等比较类似,可根据这种写法补充更多功能。

def get_holding(accountID):
    '''
    获取持仓,包含可用股票以及所有股票数量
    '''

    holding = {}
    position_info = get_trade_detail_data(accountID, 'stock', 'position')
    for position in position_info:
        if position.m_nVolume > 0:
            stock = position.m_strInstrumentID + '.' + position.m_strExchangeID
            holding[stock] = [position.m_nVolume, position.m_nCanUseVolume,  position.m_dOpenPrice]
    return holding

def get_deal(accountID):
    '''
    获取当日成交数据
    '''

    deals = []
    deal_info = get_trade_detail_data(accountID, 'stock', 'deal')
    for deal in deal_info:
        deals.append({
          'StockCode': deal.m_strInstrumentID + '.' + deal.m_strExchangeID,
          'StockName': deal.m_strInstrumentName,
          'TradeID': deal.m_strTradeID,
          'OrderRef': deal.m_strOrderRef,
          'OrderSysID': deal.m_strOrderSysID,
          'Direction': deal.m_nDirection,
          'OffsetFlag': deal.m_nOffsetFlag,
          'Price': deal.m_dPrice,
          'Volume': deal.m_nVolume,
          'TradeDate': deal.m_strTradeDate,
          'TradeTime': deal.m_strTradeTime,
          'TradeAmount': deal.m_dTradeAmount,
          'OrderPriceType': deal.m_nOrderPriceType
        })
    return deals
   
class HoldingHandler(RequestHandler):
  def get(self):
    self.write({"Holding": get_holding(self.application.accountID)})

class DealHandler(RequestHandler):
  def get(self):
    self.write({"Deal": get_deal(self.application.accountID)})
   
class MoneyHandler(RequestHandler):
  def get(self):
    acct_info = get_trade_detail_data(self.application.accountID, 'stock', 'account')
    total_money = acct_info[0].m_dAvailable
    self.write({"AvailableMoney": total_money})
  • RequestHandler:封装对请求处理的所有信息和处理方法
  • get/post/..:封装对应的请求方式
  • write():封装响应信息,写响应信息的一个方法
2.2 行情

以获取指数成分股和查询K线为例:

class SectorHandler(RequestHandler):
  def get(self):
    index = self.get_argument('index','000300.SH')
    self.write({index: self.application.ContextInfo.get_sector(index)})
   
class KlineHandler(RequestHandler):
  def get(self):
    stocks = self.get_argument('stocks','510050.SH,159919.SZ').split(',')
    period = self.get_argument('period','1m')
    start_time = self.get_argument('start_time','')
    end_time = self.get_argument('end_time','')
    count = int(self.get_argument('count','-1'))
    data = self.application.ContextInfo.get_market_data_ex(stock_code=stocks,period=period,start_time=start_time,end_time=end_time,count=count,dividend_type='follow',fill_data=True,subscribe=True)
    result = {i: data.to_dict('records') for i in data}
    self.write(result)
  • get_argument:传递访问参数,可设置默认值
三、配置访问路由

tornado与Flask和Sanic写法稍有不同,url访问路由与Handler对应成一个元组,传入Application函数中。

def make_app():
  urls = [
    ("/quote/sector", SectorHandler),
    ("/quote/kline", KlineHandler),
    ("/trade/holding", HoldingHandler),
    ("/trade/deal", DealHandler),
    ("/trade/money", MoneyHandler)
  ]
  return Application(urls)

把上面所有代码合到一处,便完成了整个Demo程序的构建。通过访问http://localhost:9000/trade/deal便可以获取当日成交,其他功能也类似。

四、部署

新建一个策略,把上述代码粘贴进去,编译保存后,在模型交易菜单里设置实盘运行,便可以像MiniQMT一样在外部使用QMT内置函数了:


欢迎关注我的公众号“量化实战”,原创技术文章第一时间推送。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

所有评论 0
您需要登录后才可以回帖 登录 | 立即注册