[Mod]更新富途接口为futu-api

This commit is contained in:
vn.py 2018-12-20 09:55:48 +08:00
parent dbd967bb6d
commit 97fcd7f19a
4 changed files with 7 additions and 750 deletions

View File

@ -3,7 +3,6 @@ websocket-client
msgpack-python msgpack-python
qdarkstyle qdarkstyle
SortedContainers SortedContainers
futuquant
wmi wmi
future future
flask-socketio flask-socketio
@ -16,4 +15,4 @@ pyqtgraph
qtpy qtpy
psutil psutil
ta-lib ta-lib
futu-api

View File

@ -1,742 +0,0 @@
# encoding: UTF-8
'''
vnpy.api.bithumb的gateway接入
'''
import json
from collections import defaultdict
from datetime import datetime
from vnpy.api.bithumb import BithumbRestApi
from vnpy.trader.vtFunction import getJsonPath
from vnpy.trader.vtGateway import *
# 方向映射
directionMap = {
constant.DIRECTION_LONG: 'bid',
constant.DIRECTION_SHORT: 'ask'
}
directionMapReverse = {v: k for k, v in directionMap.items()}
# 从https://www.bithumb.com/u1/US127中https://api.bithumb.com/trade/place的API说明中得到
minimum_ticks = {
'BTC': 0.001,
'ETH': 0.01,
'DASH': 0.01,
'LTC': 0.01,
'ETC': 0.1,
'XRP': 10,
'BCH': 0.001,
'XMR': 0.01,
'ZEC': 0.01,
'QTUM': 0.1,
'BTG': 0.1,
'EOS': 0.1,
'ICX': 1,
'VEN': 1,
'TRX': 100,
'ELF': 10,
'MITH': 10,
'MCO': 10,
'OMG': 0.1,
'KNC': 1,
'GNT': 10,
'HSR': 1,
'ZIL': 100,
'ETHOS': 1,
'PAY': 1,
'WAX': 10,
'POWR': 10,
'LRC': 10,
'GTO': 10,
'STEEM': 10,
'STRAT': 1,
'ZRX': 1,
'REP': 0.1,
'AE': 1,
'XEM': 10,
'SNT': 10,
'ADA': 10
}
########################################################################
class BithumbGateway(VtGateway):
#----------------------------------------------------------------------
def __init__(self, eventEngine, gatewayName='BithumbGateway'):
super(BithumbGateway, self).__init__(eventEngine, gatewayName)
self.restApi = RestApi(self) # type: RestApi
self.qryEnabled = False
self.fileName = self.gatewayName + '_connect.json'
self.filePath = getJsonPath(self.fileName, __file__)
#----------------------------------------------------------------------
def connect(self):
"""连接"""
try:
f = open(self.filePath)
except IOError:
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'读取连接配置出错,请检查'
self.onLog(log)
return
# 解析json文件
setting = json.load(f)
f.close()
try:
apiKey = str(setting['apiKey'])
apiSecret = str(setting['apiSecret'])
# symbols = setting['symbols']
except KeyError:
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'连接配置缺少字段,请检查'
self.onLog(log)
return
# 创建行情和交易接口对象
self.restApi.connect(apiKey, apiSecret)
# 初始化并启动查询
self.initQuery()
#----------------------------------------------------------------------
def subscribe(self, subscribeReq):
"""订阅行情"""
pass
#----------------------------------------------------------------------
def sendOrder(self, orderReq):
"""发单"""
return self.restApi.sendOrder(orderReq)
#----------------------------------------------------------------------
def cancelOrder(self, cancelOrderReq):
"""撤单"""
self.restApi.cancelOrder(cancelOrderReq)
#----------------------------------------------------------------------
def close(self):
"""关闭"""
self.restApi.close()
#----------------------------------------------------------------------
def initQuery(self):
"""初始化连续查询"""
# if self.qryEnabled:
# 需要循环的查询函数列表
# self.qryFunctionList = [self.restApi.qryTickers,
# self.restApi.qryDepth,
# self.restApi.qryPosition,
# self.restApi.qryOrder]
#
# self.qryCount = 0 # 查询触发倒计时
# self.qryTrigger = 1 # 查询触发点
# self.qryNextFunction = 0 # 上次运行的查询函数索引
#
# self.startQuery()
pass
#----------------------------------------------------------------------
def query(self, event):
"""注册到事件处理引擎上的查询函数"""
# self.qryCount += 1
#
# if self.qryCount > self.qryTrigger:
# # 清空倒计时
# self.qryCount = 0
#
# # 执行查询函数
# function = self.qryFunctionList[self.qryNextFunction]
# function()
#
# # 计算下次查询函数的索引如果超过了列表长度则重新设为0
# self.qryNextFunction += 1
# if self.qryNextFunction == len(self.qryFunctionList):
# self.qryNextFunction = 0
pass
#----------------------------------------------------------------------
def startQuery(self):
"""启动连续查询"""
self.eventEngine.register(EVENT_TIMER, self.query)
#----------------------------------------------------------------------
def setQryEnabled(self, qryEnabled):
"""设置是否要启动循环查询"""
self.qryEnabled = qryEnabled
########################################################################
# noinspection PyUnusedLocal
class RestApi(BithumbRestApi):
"""REST API实现"""
#----------------------------------------------------------------------
def __init__(self, gateway):
"""Constructor"""
super(RestApi, self).__init__()
self.gateway = gateway # type: BithumbGateway # gateway对象
self.gatewayName = gateway.gatewayName # gateway对象名称
self.localID = 0
self.tradeID = 0
self.orders = {} # type: dict[str, VtOrderData] # localID:order
self.sysLocalDict = {} # type: dict[str, str] # sysID: localID
self.localSysDict = {} # type: dict[str, str] # localID: sysID
self.reqOrderDict = {} # type: dict[int, VtOrderData] # reqID:order
self.cancelDict = {} # type: dict[str, VtCancelOrderReq] # localID:req
self.tickDict = {}
#----------------------------------------------------------------------
def connect(self, apiKey, apiSecret):
"""连接服务器"""
self.init(apiKey, apiSecret)
self.start()
# self.symbols = symbols
self.writeLog(u'REST API启动成功')
self.qryContract()
#----------------------------------------------------------------------
def writeLog(self, content):
"""发出日志"""
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = content
self.gateway.onLog(log)
#----------------------------------------------------------------------
def generateLocalOrder(self, ):
self.localID += 1
localID = str(self.localID)
order = VtOrderData()
order.gatewayName = self.gatewayName
order.status = constant.STATUS_UNKNOWN
order.exchange = constant.EXCHANGE_BITHUMB
order.orderID = localID
order.vtOrderID = '.'.join([self.gatewayName, localID])
self.orders[localID] = order
return order
#----------------------------------------------------------------------
def sendOrder(self, orderReq):
"""下单"""
req = {
'order_currency': orderReq.symbol,
'Payment_currency': orderReq.currency, # todo: 无论如何服务器都会以KRW作为单位
'type': directionMap[orderReq.direction],
'price': int(orderReq.price),
'units': orderReq.volume
}
reqid = self.addReq('POST', '/trade/place', self.onSendOrder, postdict=req)
# 缓存委托数据对象
order = self.generateLocalOrder()
self.fillLocalOrder(order,
orderReq.symbol,
orderReq.price,
orderReq.volume,
orderReq.direction)
self.reqOrderDict[reqid] = order
return order.vtOrderID
#----------------------------------------------------------------------
def onSendOrder(self, data, reqid): # type: (dict, int)->None
"""下单回执"""
if self.checkError(u'委托', data):
return
order = self.reqOrderDict[reqid]
localID = order.orderID
sysID = data['order_id']
self.saveSysIDForOrder(order, sysID)
self.gateway.onOrder(order)
# 发出等待的撤单委托
if localID in self.cancelDict:
req = self.cancelDict[localID]
self.cancelOrder(req)
del self.cancelDict[localID]
#----------------------------------------------------------------------
@staticmethod
def fillLocalOrder(order, symbol, price, totalVolume, direction):
order.symbol = symbol
order.vtSymbol = '.'.join([order.symbol, order.exchange])
order.price = price
order.totalVolume = totalVolume
order.direction = direction
#----------------------------------------------------------------------
def saveSysIDForOrder(self, order, sysID): # type: (VtOrderData, str)->None
self.sysLocalDict[sysID] = order.orderID
self.localSysDict[order.orderID] = sysID
#----------------------------------------------------------------------
def qryOrder(self, order): # type: (VtOrderData)->None
sysID = self.getSysIDForOrder(order)
req = {
'currency': order.symbol,
'order_id': sysID
}
self.addReq('POST', '/info/orders', self.onQryOrders, postdict=req)
#----------------------------------------------------------------------
def qryOrders(self, currency='XML'): # type: (VtOrderData)->None
sysID = self.getSysIDForOrder(order)
req = {
'currency': order.symbol,
}
self.addReq('POST', '/info/orders', self.onQryOrders, postdict=req)
#----------------------------------------------------------------------
def onQryOrders(self, data, reqid):
if self.checkError(u'订单查询', data):
return
orders = data['data']
for detail in orders:
sysID = detail['order_id']
order = self.getOrderBySysID(sysID)
if not order:
# 查询到了新的order(以前的order)
order = self.generateLocalOrder()
self.fillLocalOrder(order,
detail['order_currency'],
detail['price'],
detail['units'],
directionMapReverse[detail['type']])
order.tradedVolume = order.totalVolume - detail['units_remaining']
# todo: payment_currency
# payment_currency = detail['payment_currency']
self.saveSysIDForOrder(order, sysID)
# 推送
self.gateway.onOrder(order)
continue
originalTradeVolume = order.tradedVolume
order.tradedVolume = newTradeVolume = order.totalVolume - detail['units_remaining']
if newTradeVolume != originalTradeVolume:
# 推送更新
self.gateway.onOrder(order)
# 尝试更新状态
# todo: 这一句还未测试不知道成交之后date_completed是不是就会有值
order.status = constant.STATUS_ALLTRADED if detail['date_completed'] else order.status
if order.status == constant.STATUS_ALLTRADED:
# 推送成交
self.pushOrderAsTraded(order)
#----------------------------------------------------------------------
def pushOrderAsTraded(self, order):
trade = VtTradeData()
trade.gatewayName = order.gatewayName
trade.symbol = order.symbol
trade.vtSymbol = order.vtSymbol
trade.orderID = order.orderID
trade.vtOrderID = order.vtOrderID
self.tradeID += 1
trade.tradeID = str(self.tradeID)
trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID])
trade.direction = order.direction
trade.price = order.price
trade.volume = order.tradedVolume
trade.tradeTime = datetime.now().strftime('%H:%M:%S')
self.gateway.onTrade(trade)
#----------------------------------------------------------------------
def cancelOrder(self, cancelOrderReq): # type: (self, VtCancelOrderReq)->None
""""""
localID = cancelOrderReq.orderID
order = self.getOrderByLocalID(localID)
if self.isOrderPosted(order):
sysID = self.getSysIDForOrder(order)
req = {
'type': directionMap[order.direction],
'order_id': sysID,
'currency': cancelOrderReq.symbol
}
self.addReq('POST',
'/trade/cancel',
callback=lambda data, reqid: self.onCancelOrder(localID, data, reqid),
postdict=req)
else:
self.cancelDict[localID] = cancelOrderReq
#----------------------------------------------------------------------
def onCancelOrder(self, localID, data, reqid):
if self.checkError(u'撤单', data):
return
order = self.getOrderByLocalID(localID)
order.status = constant.STATUS_CANCELLED
#----------------------------------------------------------------------
def qryContract(self):
""""""
contract = VtContractData()
contract.gatewayName = self.gatewayName
for symbol, tick in minimum_ticks.items():
contract.symbol = symbol
contract.exchange = constant.EXCHANGE_BITHUMB
contract.vtSymbol = '.'.join([contract.symbol, contract.exchange])
contract.name = contract.vtSymbol
contract.productClass = constant.PRODUCT_SPOT
contract.priceTick = tick
contract.size = 1
self.gateway.onContract(contract)
#----------------------------------------------------------------------
def qryPublicTick(self, symbol='ALL'):
""" symbol 可以是'BTC', 'ETC'等等电子货币符号;也可以使用'ALL',表示要获取所有货币的行情"""
url = '/public/ticker/' + symbol
if symbol.upper() == 'ALL':
self.addReq('GET', url, self.onQryMultiPublicTicker)
else:
self.addReq('GET', url,
callback=lambda data, reqid: self.onQrySinglePublicTicker(symbol, data, id))
#----------------------------------------------------------------------
def qryPublicOrderBook(self, symbol='ALL'):
""" symbol 可以是'BTC', 'ETC'等等电子货币符号;也可以使用'ALL',表示要获取所有货币的行情"""
url = '/public/orderbook/' + symbol
if symbol.upper() == 'ALL':
self.addReq('GET', url, self.onQryMultiPublicOrderBook)
else:
self.addReq('GET', url,
callback=lambda data, reqid: self.onQrySinglePublicOrderBook(symbol, data, id))
#----------------------------------------------------------------------
def qryPrivateTick(self, symbol, currency='CNY'):
""""""
req = {
'order_currency': symbol,
'payment_currency': currency,
}
self.addReq('POST', '/info/ticker', self.onQryPrivateTicker, postdict=req)
#----------------------------------------------------------------------
def qryPosition(self, symbol='ALL'):
""""""
req = {
'currency': symbol,
}
self.addReq('POST', '/info/balance', self.onQryPosition, postdict=req)
pass
#----------------------------------------------------------------------
def onQryPosition(self, data, reqid): # type: (self, dict, int)->None
""""""
if self.checkError(u'查询持仓', data):
return
datas = data['data'] # type: dict
# 先分类一下
infos = defaultdict(dict) # type: dict[str, dict[str, str]]
for key, val in datas.items(): # type: str, str
split_position = key.rfind('_')
infoType, symbol = key[:split_position], key[split_position+1:]
infos[symbol.upper()][infoType] = val
for symbol in infos.keys():
info = infos[symbol]
if symbol == u'LAST': # 过滤掉xcoin_last这个值表示的是最后一次交易量
continue
if symbol == u'KRW':
accountData = VtAccountData()
# todo: accountID必须从另一个API获取
# accountData.accountID =
accountData.balance = info['total']
accountData.available = info['available']
self.gateway.onAccount(accountData)
pass
else:
pos = VtPositionData()
pos.gatewayName = self.gatewayName
pos.symbol = symbol
pos.exchange = constant.EXCHANGE_BITHUMB
pos.vtSymbol = '.'.join([pos.symbol, pos.exchange])
pos.direction = constant.DIRECTION_NET
pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction])
pos.position = float(info['total'])
pos.frozen = float(info['in_use'])
self.gateway.onPosition(pos)
#----------------------------------------------------------------------
def parsePublicTickerData(self, symbol, info):
dt = datetime.now()
date = dt.strftime('%Y%m%d')
time = dt.strftime('%H:%M:%S')
tick = self.getTick(symbol)
tick.openPrice = float(info['opening_price'])
tick.highPrice = float(info['max_price'])
tick.lowPrice = float(info['min_price'])
tick.lastPrice = float(info['closing_price']) # todo: 也许应该是'buy_price'?
tick.volume = float(info['volume_1day'])
tick.datetime = datetime
tick.date = date
tick.time = time
# 只有订阅了深度行情才推送
if tick.bidPrice1:
self.gateway.onTick(tick)
#----------------------------------------------------------------------
def onQrySinglePublicTicker(self, symbol, data, reqid):
if self.checkError(u'查询行情', data):
return
info = data['data']
self.parsePublicTickerData(symbol=symbol, info=info)
#----------------------------------------------------------------------
def onQryMultiPublicTicker(self, data, reqid):
if self.checkError(u'查询行情', data):
return
for symbol, info in data['data'].items():
# 里面可能会出现一对date: int这样的值所以要过滤掉
if isinstance(info, dict):
self.parsePublicTickerData(symbol=symbol, info=info)
pass
#----------------------------------------------------------------------
def parsePublicOrderBookData(self, symbol, info):
dt = datetime.now()
date = dt.strftime('%Y%m%d')
time = dt.strftime('%H:%M:%S')
tick = self.getTick(symbol)
for i in range(5):
tick.__setattr__('askPrice' + str(i + 1), float(info['asks'][i]['price']))
tick.__setattr__('askVolume' + str(i + 1), float(info['asks'][i]['quantity']))
for i in range(5):
tick.__setattr__('bidPrice' + str(i + 1), float(info['bids'][i]['price']))
tick.__setattr__('bidVolume' + str(i + 1), float(info['bids'][i]['quantity']))
tick.datetime = datetime
tick.date = date
tick.time = time
# 只有订阅了深度行情才推送
if tick.bidPrice1:
self.gateway.onTick(tick)
#----------------------------------------------------------------------
def onQrySinglePublicOrderBook(self, symbol, data, reqid):
if self.checkError(u'五档行情', data):
return
info = data['data']
self.parsePublicTickerData(symbol=symbol, info=info)
pass
#----------------------------------------------------------------------
def onQryMultiPublicOrderBook(self, data, reqid):
if self.checkError(u'五档行情', data):
return
for symbol, info in data['data'].items():
self.parsePublicTickerData(symbol=symbol, info=info)
pass
#----------------------------------------------------------------------
def onQryPrivateTicker(self, data, reqid):
pass
#----------------------------------------------------------------------
def getTick(self, symbol):
""""""
tick = self.tickDict.get(symbol, None) # type: VtTickData
if not tick:
tick = VtTickData()
tick.gatewayName = self.gatewayName
tick.symbol = symbol
tick.exchange = constant.EXCHANGE_BITHUMB
tick.vtSymbol = '.'.join([tick.symbol, tick.exchange])
self.tickDict[symbol] = tick
return tick
#----------------------------------------------------------------------
def checkError(self, name, data):
""""""
status = data.get('status', None)
if status == u'0000':
return False
elif not status:
self.writeLog(u'%s触发错误:%s' % (name, u"未知的响应报文 : %s".format(data)))
return True
msg = data.get('message', u'unknown')
self.writeLog(u'%s触发错误:%s' % (name, msg))
return True
#----------------------------------------------------------------------
def getOrderByLocalID(self, localID): # type: (str)->VtOrderData
"""如果没有该订单,这个函数会出错"""
return self.orders[localID]
#----------------------------------------------------------------------
def getOrderByVtOrderID(self, vtOrderId): # type: (str)->VtOrderData
"""如果没有该订单,这个函数会出错"""
localID = vtOrderId[vtOrderId.rfind('.') + 1:]
return self.getOrderByLocalID(localID)
#----------------------------------------------------------------------
def getOrderBySysID(self, sysID): # type: (str)->VtOrderData
return self.getOrderByLocalID(self.getLocalIDBySysID(sysID))
#----------------------------------------------------------------------
def getLocalIDBySysID(self, sysID): # type: (str)->str
return self.sysLocalDict[sysID]
#----------------------------------------------------------------------
def isOrderPosted(self, order): # type: (VtOrderData)->bool
"""检查服务器是否响应了一个下单请求如果已经响应了返回True否则False"""
return order.orderID in self.localSysDict
#----------------------------------------------------------------------
def getSysIDForOrder(self, order): # type: (VtOrderData)->str
return self.localSysDict[order.orderID]
#----------------------------------------------------------------------
def hasSysID(self, sysID):
return sysID in self.sysLocalDict
if __name__ == '__main__':
# default test secret:
API_KEY = '0c2f5621ac18d26d51ce640b25eb44f9'
API_SECRET = '62bb8b4e263476f443f8d3dbf0aad6bc'
api = BithumbRestApi()
api.init(apiKey=API_KEY, apiSecret=API_SECRET)
api.start(1)
eventEngine = EventEngine2()
rest = RestApi(BithumbGateway(eventEngine=eventEngine))
rest.connect(API_KEY, API_SECRET)
translateDict = {
u'\uac70\ub798 \uccb4\uacb0\ub0b4\uc5ed\uc774 '
u'\uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.': "交易记录不存在",
u'\uac70\ub798 \uc9c4\ud589\uc911\uc778 \ub0b4\uc5ed\uc774 '
u'\uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.': "没有正在进行的交易",
u'\ub9e4\uc218\uae08\uc561\uc774 \uc0ac\uc6a9\uac00\ub2a5 KRW'
u' \ub97c \ucd08\uacfc\ud558\uc600\uc2b5\ub2c8\ub2e4.': "购买金额超过可用KRW",
u'\ub9e4\uc218\uac74\uc758 \uc0c1\ud0dc\uac00 \uc9c4\ud589\uc911\uc774 \uc544\ub2d9\ub2c8\ub2e4. '
u'\ucde8\uc18c\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.': "购买查询的状态未在进行中。 它无法取消。",
u'\uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ud654\ud3d0\uc785\ub2c8\ub2e4. [347]': "不支持该货币单位。[347]",
}
def printError(jsonObj):
if rest.checkError('', data=jsonObj):
print('error : ')
msg = jsonObj['message']
print(translateDict.get(msg, msg))
def manualCancelOrder(sysID):
def onTradeCancel(jsonObj, reqid):
print('onTradeCancel : \n{}'.format(jsonObj))
printError(jsonObj)
rest.addReq('POST', '/trade/cancel', onTradeCancel,
postdict={'type': 'bid', 'order_id': sysID, 'currency': 'XMR'})
def apiCancelOrder(localId):
cancelReq = VtCancelOrderReq()
cancelReq.symbol = order.symbol
cancelReq.orderID = localId
rest.cancelOrder(cancelReq)
# query tick
rest.qryPublicTick('BTC')
rest.qryPublicTick('ALL')
rest.qryPosition('BTC')
rest.qryPosition('ALL')
# send order
sendOrderReq = VtOrderReq()
sendOrderReq.symbol = 'XMR'
sendOrderReq.direction = constant.DIRECTION_LONG
sendOrderReq.volume = minimum_ticks['XMR']
# sendOrderReq.price = 700
# sendOrderReq.currency = 'CNY' # 不可用
# sendOrderReq.price = 16.6461
# sendOrderReq.currency = 'USD' # 不可用
sendOrderReq.price = 17500
sendOrderReq.currency = 'KRW'
vtOrderId = rest.sendOrder(sendOrderReq)
order = rest.getOrderByVtOrderID(vtOrderId)
# todo: order的状态表示不够清晰
while not rest.isOrderPosted(order):
time.sleep(0.1)
sysID = rest.getSysIDForOrder(order)
print("sysID : ")
print(sysID)
def onOrders(jsonObj, reqid):
print('on_orders : \n{}'.format(jsonObj))
printError(jsonObj)
for detail in jsonObj['data']:
sysID = detail['order_id']
if rest.hasSysID(sysID):
apiCancelOrder(rest.getLocalIDBySysID(sysID))
else:
manualCancelOrder(sysID)
after = '1531926544794' # 2018-07-18T15:09:04.794Z
# rest.addReq('POST', '/info/orders', on_orders,
# postdict={'order_id': sysID, 'type': 'bid', 'after': after, 'currency': 'XMR'}) # got
#
# rest.addReq('POST', '/info/orders', on_orders,
# postdict={'order_id': sysID, 'type': 'bid', 'currency': 'XMR'}) # got
#
# rest.addReq('POST', '/info/orders', on_orders,
# postdict={'after': after, 'currency': 'XMR'}) # got
rest.addReq('POST', '/info/orders', onOrders, postdict={'currency': 'XMR'}) # got
# rest.addReq('POST', '/info/orders', on_orders,
# postdict={'order_id': sysID, 'type': 'bid', 'after': after}) # 没有正在进行的交易
#
# rest.addReq('POST', '/info/orders', on_orders, postdict={'after': after}) # 没有正在进行的交易
# rest.addReq('POST', '/info/orders', on_orders, postdict={}) # 没有正在进行的交易
# rest.addReq('POST', '/info/orders', on_orders, postdict={'currency': 'ALL'}) # 不支持该货币单位
raw_input()

View File

@ -11,11 +11,11 @@ from time import sleep
from datetime import datetime from datetime import datetime
from copy import copy from copy import copy
from futuquant import (OpenQuoteContext, OpenHKTradeContext, OpenUSTradeContext, from futu import (OpenQuoteContext, OpenHKTradeContext, OpenUSTradeContext,
RET_ERROR, RET_OK, RET_ERROR, RET_OK,
TrdEnv, TrdSide, OrderType, OrderStatus, ModifyOrderOp, TrdEnv, TrdSide, OrderType, OrderStatus, ModifyOrderOp,
StockQuoteHandlerBase, OrderBookHandlerBase, StockQuoteHandlerBase, OrderBookHandlerBase,
TradeOrderHandlerBase, TradeDealHandlerBase) TradeOrderHandlerBase, TradeDealHandlerBase)
from vnpy.trader.vtGateway import * from vnpy.trader.vtGateway import *
from vnpy.trader.vtConstant import GATEWAYTYPE_INTERNATIONAL from vnpy.trader.vtConstant import GATEWAYTYPE_INTERNATIONAL

View File

@ -36,7 +36,7 @@ class MainWindow(QtWidgets.QMainWindow):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def initUi(self): def initUi(self):
"""初始化界面""" """初始化界面"""
self.setWindowTitle('VnTrader') self.setWindowTitle('VN Trader')
self.initCentral() self.initCentral()
self.initMenu() self.initMenu()
self.initStatusBar() self.initStatusBar()