本帖最后由 流光 于 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内置函数了:

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

|