本帖最后由 流光 于 2023-12-18 22:55 编辑  
 
一、程序骨架首先导入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内置函数了: 
 
 
 
 欢迎关注我的公众号“量化实战”,原创技术文章第一时间推送。 
 
 
  
  
 |