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