[Add]新增FutuTrader,修改futuGateway兼容Python3新版

This commit is contained in:
vn.py 2018-07-22 20:42:32 +08:00
parent 9f5b786d1e
commit 1c5abeb986
9 changed files with 143 additions and 53 deletions

View File

@ -0,0 +1,19 @@
[
{
"name": "double ema",
"className": "DoubleMaStrategy",
"vtSymbol": "rb1805"
},
{
"name": "atr rsi",
"className": "AtrRsiStrategy",
"vtSymbol": "IC1802"
},
{
"name": "king keltner",
"className": "KkStrategy",
"vtSymbol": "IH1802"
}
]

View File

@ -0,0 +1,7 @@
{
"host": "127.0.0.1",
"port": 11111,
"market": "US",
"password": "123123",
"env": "REAL"
}

View File

@ -0,0 +1,10 @@
{
"active": false,
"orderFlowLimit": 50,
"orderFlowClear": 1,
"orderSizeLimit": 100,
"tradeLimit": 1000,
"workingOrderLimit": 20,
"orderCancelLimit": 10,
"marginRatioLimit": 0.85
}

View File

@ -0,0 +1,20 @@
{
"fontFamily": "微软雅黑",
"fontSize": 12,
"mongoHost": "localhost",
"mongoPort": 27017,
"mongoLogging": true,
"darkStyle": true,
"language": "chinese",
"logActive": true,
"logLevel": "debug",
"logConsole": true,
"logFile": true,
"tdPenalty": ["IF", "IH", "IC"],
"maxDecimal": 4
}

View File

@ -0,0 +1,46 @@
# encoding: UTF-8
import sys
# vn.trader模块
from vnpy.event import EventEngine
from vnpy.trader.vtEngine import MainEngine
from vnpy.trader.uiQt import createQApp
from vnpy.trader.uiMainWindow import MainWindow
# 加载底层接口
from vnpy.trader.gateway import futuGateway
# 加载上层应用
from vnpy.trader.app import riskManager#, ctaStrategy
#----------------------------------------------------------------------
def main():
"""主程序入口"""
# 创建Qt应用对象
qApp = createQApp()
# 创建事件引擎
ee = EventEngine()
# 创建主引擎
me = MainEngine(ee)
# 添加交易接口
me.addGateway(futuGateway)
# 添加上层应用
me.addApp(riskManager)
#me.addApp(ctaStrategy)
# 创建主窗口
mw = MainWindow(me, ee)
mw.showMaximized()
# 在主线程中启动Qt事件循环
sys.exit(qApp.exec_())
if __name__ == '__main__':
main()

Binary file not shown.

View File

@ -0,0 +1 @@
'data', (0, 1462865)

View File

@ -1,7 +0,0 @@
{
"username": "请在quantos.org申请",
"token": "请在quantos.org申请",
"strategy": 625,
"tradeAddress": "tcp://gw.quantos.org:8901",
"dataAddress": "tcp://data.tushare.org:8910"
}

View File

@ -11,8 +11,9 @@ from time import sleep
from datetime import datetime from datetime import datetime
from copy import copy from copy import copy
import futuquant as ft from futuquant import (OpenQuoteContext, OpenHKTradeContext, OpenUSTradeContext,
from futuquant import (RET_ERROR, RET_OK, TrdEnv, RET_ERROR, RET_OK,
TrdEnv, TrdSide, OrderType, OrderStatus, ModifyOrderOp,
StockQuoteHandlerBase, OrderBookHandlerBase, StockQuoteHandlerBase, OrderBookHandlerBase,
TradeOrderHandlerBase, TradeDealHandlerBase) TradeOrderHandlerBase, TradeDealHandlerBase)
@ -33,23 +34,20 @@ productMap[PRODUCT_WARRANT] = 'WARRANT'
productMap[PRODUCT_BOND] = 'BOND' productMap[PRODUCT_BOND] = 'BOND'
directionMap = {} directionMap = {}
directionMap[DIRECTION_LONG] = '0' directionMap[DIRECTION_LONG] = TrdSide.BUY
directionMap[DIRECTION_SHORT] = '1' directionMap[DIRECTION_SHORT] = TrdSide.SELL
directionMapReverse = {v:k for k,v in directionMap.items()} directionMapReverse = {v:k for k,v in directionMap.items()}
statusMapReverse = {} statusMapReverse = {}
statusMapReverse['0'] = STATUS_UNKNOWN statusMapReverse[OrderStatus.NONE] = STATUS_UNKNOWN
statusMapReverse['1'] = STATUS_NOTTRADED statusMapReverse[OrderStatus.SUBMITTED] = STATUS_NOTTRADED
statusMapReverse['2'] = STATUS_PARTTRADED statusMapReverse[OrderStatus.FILLED_PART] = STATUS_PARTTRADED
statusMapReverse['3'] = STATUS_ALLTRADED statusMapReverse[OrderStatus.FILLED_ALL] = STATUS_ALLTRADED
statusMapReverse['4'] = STATUS_CANCELLED statusMapReverse[OrderStatus.CANCELLED_ALL] = STATUS_CANCELLED
statusMapReverse['5'] = STATUS_REJECTED statusMapReverse[OrderStatus.CANCELLED_PART] = STATUS_CANCELLED
statusMapReverse['6'] = STATUS_CANCELLED statusMapReverse[OrderStatus.SUBMIT_FAILED] = STATUS_REJECTED
statusMapReverse['7'] = STATUS_CANCELLED statusMapReverse[OrderStatus.FAILED] = STATUS_REJECTED
statusMapReverse['8'] = STATUS_UNKNOWN statusMapReverse[OrderStatus.DISABLED] = STATUS_CANCELLED
statusMapReverse['21'] = STATUS_UNKNOWN
statusMapReverse['22'] = STATUS_UNKNOWN
statusMapReverse['23'] = STATUS_UNKNOWN
@ -137,7 +135,7 @@ class FutuGateway(VtGateway):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def connectQuote(self): def connectQuote(self):
"""连接行情功能""" """连接行情功能"""
self.quoteCtx = ft.OpenQuoteContext(self.host, self.port) self.quoteCtx = OpenQuoteContext(self.host, self.port)
# 继承实现处理器类 # 继承实现处理器类
class QuoteHandler(StockQuoteHandlerBase): class QuoteHandler(StockQuoteHandlerBase):
@ -176,9 +174,9 @@ class FutuGateway(VtGateway):
"""连接交易功能""" """连接交易功能"""
# 连接交易接口 # 连接交易接口
if self.market == 'US': if self.market == 'US':
self.tradeCtx = ft.OpenUSTradeContext(self.host, self.port) self.tradeCtx = OpenUSTradeContext(self.host, self.port)
else: else:
self.tradeCtx = ft.OpenHKTradeContext(self.host, self.port) self.tradeCtx = OpenHKTradeContext(self.host, self.port)
# 继承实现处理器类 # 继承实现处理器类
class OrderHandler(TradeOrderHandlerBase): class OrderHandler(TradeOrderHandlerBase):
@ -204,7 +202,7 @@ class FutuGateway(VtGateway):
return RET_OK, content return RET_OK, content
# 只有港股实盘交易才需要解锁 # 只有港股实盘交易才需要解锁
if self.market == 'HK' and self.env == 0: if self.market == 'HK' and self.env == TrdEnv.REAL:
self.tradeCtx.unlock_trade(self.password) self.tradeCtx.unlock_trade(self.password)
# 设置回调处理对象 # 设置回调处理对象
@ -229,26 +227,25 @@ class FutuGateway(VtGateway):
def sendOrder(self, orderReq): def sendOrder(self, orderReq):
"""发单""" """发单"""
side = directionMap[orderReq.direction] side = directionMap[orderReq.direction]
priceType = 0 # 只支持限价单 priceType = OrderType.NORMAL # 只支持限价单
# 设置价格调整模式为向内调整(即买入调整后价格比原始价格低) # 设置价格调整模式为向内调整(即买入调整后价格比原始价格低)
if orderReq.direction == DIRECTION_LONG: if orderReq.direction == DIRECTION_LONG:
priceMode = PriceRegularMode.LOWER adjustLimit = 0.05
else: else:
priceMode = PriceRegularMode.UPPER adjustLimit = -0.05
code, data = self.tradeCtx.place_order(orderReq.price, orderReq.volume, code, data = self.tradeCtx.place_order(orderReq.price, orderReq.volume,
orderReq.symbol, side, orderReq.symbol, side, priceType,
priceType, self.env, trd_env=self.env,
order_deal_push=True, adjust_limit=adjustLimit)
price_mode=priceMode)
if code: if code:
self.writeError(code, u'委托失败:%s' %data) self.writeError(code, u'委托失败:%s' %data)
return '' return ''
for ix, row in data.iterrows(): for ix, row in data.iterrows():
orderID = str(row['orderid']) orderID = str(row['order_id'])
vtOrderID = '.'.join([self.gatewayName, orderID]) vtOrderID = '.'.join([self.gatewayName, orderID])
@ -257,8 +254,8 @@ class FutuGateway(VtGateway):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def cancelOrder(self, cancelOrderReq): def cancelOrder(self, cancelOrderReq):
"""撤单""" """撤单"""
code, data = self.tradeCtx.set_order_status(0, int(cancelOrderReq.orderID), code, data = self.tradeCtx.modify_order(ModifyOrderOp.CANCEL, cancelOrderReq.orderID,
self.env) 0, 0, trd_env=self.env)
if code: if code:
self.writeError(code, u'撤单失败:%s' %data) self.writeError(code, u'撤单失败:%s' %data)
@ -304,9 +301,8 @@ class FutuGateway(VtGateway):
account.accountID = '%s_%s' %(self.gatewayName, self.market) account.accountID = '%s_%s' %(self.gatewayName, self.market)
account.vtAccountID = '.'.join([self.gatewayName, account.accountID]) account.vtAccountID = '.'.join([self.gatewayName, account.accountID])
account.balance = float(row['ZCJZ']) account.balance = float(row['total_assets'])
account.margin = float(row['GPBZJ']) account.available = float(row['avl_withdrawal_cash'])
account.available = float(row['XJJY'])
self.onAccount(account) self.onAccount(account)
@ -448,7 +444,7 @@ class FutuGateway(VtGateway):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def processOrderBook(self, data): def processOrderBook(self, data):
"""订单簿推送""" """订单簿推送"""
symbol = data['stock_code'] symbol = data['code']
tick = self.tickDict.get(symbol, None) tick = self.tickDict.get(symbol, None)
if not tick: if not tick:
@ -487,25 +483,24 @@ class FutuGateway(VtGateway):
order.symbol = row['code'] order.symbol = row['code']
order.vtSymbol = order.symbol order.vtSymbol = order.symbol
order.orderID = str(row['orderid']) order.orderID = str(row['order_id'])
order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) order.vtOrderID = '.'.join([self.gatewayName, order.orderID])
order.price = float(row['price']) order.price = float(row['price'])
order.totalVolume = int(row['qty']) order.totalVolume = int(row['qty'])
order.tradedVolume = int(row['dealt_qty']) order.tradedVolume = int(row['dealt_qty'])
order.orderTime = row['create_time'].split(' ')[-1]
t = datetime.fromtimestamp(float(row['submited_time']))
order.orderTime = t.strftime('%H:%M:%S')
order.status = statusMapReverse.get(str(row['status']), STATUS_UNKNOWN) order.status = statusMapReverse.get(row['order_status'], STATUS_UNKNOWN)
order.direction = directionMapReverse[str(row['order_side'])] order.direction = directionMapReverse[row['trd_side']]
self.onOrder(order) self.onOrder(order)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def processDeal(self, data): def processDeal(self, data):
"""处理成交推送""" """处理成交推送"""
for ix, row in data.iterrows(): for ix, row in data.iterrows():
tradeID = row['dealid'] tradeID = row['deal_id']
if tradeID in self.tradeSet: if tradeID in self.tradeSet:
continue continue
self.tradeSet.add(tradeID) self.tradeSet.add(tradeID)
@ -519,14 +514,13 @@ class FutuGateway(VtGateway):
trade.tradeID = tradeID trade.tradeID = tradeID
trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID]) trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID])
trade.orderID = row['orderid'] trade.orderID = row['order_id']
trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID]) trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID])
trade.price = float(row['price']) trade.price = float(row['price'])
trade.volume = float(row['qty']) trade.volume = float(row['qty'])
trade.direction = directionMapReverse[str(row['order_side'])] trade.direction = directionMapReverse[row['trd_side']]
t = datetime.fromtimestamp(float(row['time'])) trade.tradeTime = row['create_time'].split(' ')[-1]
trade.tradeTime = t.strftime('%H:%M:%S')
self.onTrade(trade) self.onTrade(trade)