From f408cb30cade7bd21af5cda213cab15d9ec88a29 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sat, 16 Jun 2018 22:10:36 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90BitMEX?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/CryptoTrader/BINANCE_connect.json | 5 + examples/CryptoTrader/BITFINEX_connect.json | 5 + examples/CryptoTrader/BITMEX_connect.json | 6 + examples/CryptoTrader/HUOBI_connect.json | 6 + examples/CryptoTrader/OKEX_connect.json | 6 + examples/CryptoTrader/run.py | 4 +- vnpy/api/bitmex/vnbitmex.py | 70 ++- .../bitfinexGateway/bitfinexGateway.py | 6 +- vnpy/trader/gateway/bitmexGateway/__init__.py | 10 + .../gateway/bitmexGateway/bitmexGateway.py | 536 ++++++++++++++++++ vnpy/trader/language/chinese/constant.py | 1 + vnpy/trader/language/english/constant.py | 1 + 12 files changed, 628 insertions(+), 28 deletions(-) create mode 100644 examples/CryptoTrader/BINANCE_connect.json create mode 100644 examples/CryptoTrader/BITFINEX_connect.json create mode 100644 examples/CryptoTrader/BITMEX_connect.json create mode 100644 examples/CryptoTrader/HUOBI_connect.json create mode 100644 examples/CryptoTrader/OKEX_connect.json create mode 100644 vnpy/trader/gateway/bitmexGateway/__init__.py create mode 100644 vnpy/trader/gateway/bitmexGateway/bitmexGateway.py diff --git a/examples/CryptoTrader/BINANCE_connect.json b/examples/CryptoTrader/BINANCE_connect.json new file mode 100644 index 00000000..01d370e4 --- /dev/null +++ b/examples/CryptoTrader/BINANCE_connect.json @@ -0,0 +1,5 @@ +{ + "apiKey": "", + "secretKey": "", + "symbols": ["BTCUSDT", "ETHUSDT", "ETHBTC"] +} \ No newline at end of file diff --git a/examples/CryptoTrader/BITFINEX_connect.json b/examples/CryptoTrader/BITFINEX_connect.json new file mode 100644 index 00000000..ae25ff9c --- /dev/null +++ b/examples/CryptoTrader/BITFINEX_connect.json @@ -0,0 +1,5 @@ +{ + "apiKey": "", + "secretKey": "", + "symbols": ["BTCUSD", "ETHUSD", "ETHBTC"] +} \ No newline at end of file diff --git a/examples/CryptoTrader/BITMEX_connect.json b/examples/CryptoTrader/BITMEX_connect.json new file mode 100644 index 00000000..4aef1612 --- /dev/null +++ b/examples/CryptoTrader/BITMEX_connect.json @@ -0,0 +1,6 @@ +{ + "apiKey": "", + "apiSecret": "", + "sessionCount": 3, + "symbols": ["XBTUSD", "EOSM18", "XRPM18"] +} \ No newline at end of file diff --git a/examples/CryptoTrader/HUOBI_connect.json b/examples/CryptoTrader/HUOBI_connect.json new file mode 100644 index 00000000..8255a46f --- /dev/null +++ b/examples/CryptoTrader/HUOBI_connect.json @@ -0,0 +1,6 @@ +{ + "exchange": "huobi", + "accessKey": "", + "secretKey": "", + "symbols": ["btcusdt","ethusdt","ethbtc"] +} \ No newline at end of file diff --git a/examples/CryptoTrader/OKEX_connect.json b/examples/CryptoTrader/OKEX_connect.json new file mode 100644 index 00000000..5c77f027 --- /dev/null +++ b/examples/CryptoTrader/OKEX_connect.json @@ -0,0 +1,6 @@ +{ + "apiKey": "", + "secretKey": "", + "trace": false, + "symbols": ["eth_btc", "btc_usdt", "eth_usdt"] +} \ No newline at end of file diff --git a/examples/CryptoTrader/run.py b/examples/CryptoTrader/run.py index a09cb3dc..9088f66e 100644 --- a/examples/CryptoTrader/run.py +++ b/examples/CryptoTrader/run.py @@ -21,7 +21,8 @@ from vnpy.trader.uiMainWindow import MainWindow # 加载底层接口 from vnpy.trader.gateway import (huobiGateway, okexGateway, - binanceGateway, bitfinexGateway) + binanceGateway, bitfinexGateway, + bitmexGateway) # 加载上层应用 from vnpy.trader.app import (riskManager, algoTrading) @@ -40,6 +41,7 @@ def main(): me = MainEngine(ee) # 添加交易接口 + me.addGateway(bitmexGateway) me.addGateway(huobiGateway) me.addGateway(okexGateway) me.addGateway(binanceGateway) diff --git a/vnpy/api/bitmex/vnbitmex.py b/vnpy/api/bitmex/vnbitmex.py index 6791e7fb..91e5c303 100644 --- a/vnpy/api/bitmex/vnbitmex.py +++ b/vnpy/api/bitmex/vnbitmex.py @@ -4,6 +4,7 @@ import hashlib import hmac import json import ssl +import traceback from queue import Queue, Empty from multiprocessing.dummy import Pool @@ -84,14 +85,20 @@ class BitmexRestApi(object): url = REST_HOST + path expires = int(time() + 5) + rq = requests.Request(url=url, data=postdict) + p = rq.prepare() + header = copy(self.header) header['api-expires'] = str(expires) header['api-key'] = self.apiKey - header['api-signature'] = self.generateSignature(method, path, expires, params, postdict) + header['api-signature'] = self.generateSignature(method, path, expires, params, body=p.body) # 使用长连接的session,比短连接的耗时缩短80% session = self.sessionDict[i] - resp = session.request(method, url, headers=header, params=params, json=postdict) + resp = session.request(method, url, headers=header, params=params, data=postdict) + + #resp = requests.request(method, url, headers=header, params=params, data=postdict) + code = resp.status_code d = resp.json() @@ -113,21 +120,17 @@ class BitmexRestApi(object): pass #---------------------------------------------------------------------- - def generateSignature(self, method, path, expires, params=None, postdict=None): + def generateSignature(self, method, path, expires, params=None, body=None): """生成签名""" # 对params在HTTP报文路径中,以请求字段方式序列化 if params: query = urlencode(sorted(params.items())) path = path + '?' + query - - msg = method + '/api/v1' + path + str(expires) - # 对postdict在HTTP报文体中,是作为表单内容以json序列化 - # 因此这里需要采用同样方式,不能直接用str()来转换 - if postdict: - buf = json.dumps(postdict) - msg += buf + if body is None: + body = '' + msg = method + '/api/v1' + path + str(expires) + body signature = hmac.new(self.apiSecret, msg, digestmod=hashlib.sha256).hexdigest() return signature @@ -171,7 +174,7 @@ class BitmexWebsocketApi(object): #---------------------------------------------------------------------- def reconnect(self): """重连""" - self.ws = websocket.create_connection(WEBSOCKET_V2_URL, + self.ws = websocket.create_connection(WEBSOCKET_HOST, sslopt={'cert_reqs': ssl.CERT_NONE}) self.onConnect() @@ -205,7 +208,11 @@ class BitmexWebsocketApi(object): #---------------------------------------------------------------------- def onData(self, data): """数据回调""" - print data + print '-' * 30 + l = data.keys() + l.sort() + for k in l: + print k, data[k] #---------------------------------------------------------------------- def onError(self, msg): @@ -226,22 +233,39 @@ if __name__ == '__main__': API_SECRET = '' ## REST测试 - #rest = BitmexRestApi() - #rest.init(API_KEY, API_SECRET) - #rest.start(3) + rest = BitmexRestApi() + rest.init(API_KEY, API_SECRET) + rest.start(3) - #data = { - #'token': 'test' - #} - #rest.addReq('POST', '/confirmEmail', rest.onData, postdict=data) + data = { + 'symbol': 'XBTUSD' + } + rest.addReq('POST', '/position/isolate', rest.onData, postdict=data) #rest.addReq('GET', '/instrument', rest.onData) # WEBSOCKET测试 - ws = BitmexWebsocketApi() - ws.start() + #ws = BitmexWebsocketApi() + #ws.start() - req = {"op": "subscribe", "args": ['quote']} - ws.sendReq(req) + #req = {"op": "subscribe", "args": ['order', 'trade', 'position', 'margin']} + #ws.sendReq(req) + + #expires = int(time()) + #method = 'GET' + #path = '/realtime' + #msg = method + path + str(expires) + #signature = hmac.new(API_SECRET, msg, digestmod=hashlib.sha256).hexdigest() + + #req = { + #'op': 'authKey', + #'args': [API_KEY, expires, signature] + #} + + #ws.sendReq(req) + + #req = {"op": "subscribe", "args": ['order', 'execution', 'position', 'margin']} + #req = {"op": "subscribe", "args": ['instrument']} + #ws.sendReq(req) raw_input() diff --git a/vnpy/trader/gateway/bitfinexGateway/bitfinexGateway.py b/vnpy/trader/gateway/bitfinexGateway/bitfinexGateway.py index dd9178bd..1e622ad4 100644 --- a/vnpy/trader/gateway/bitfinexGateway/bitfinexGateway.py +++ b/vnpy/trader/gateway/bitfinexGateway/bitfinexGateway.py @@ -157,7 +157,7 @@ class GatewayApi(BitfinexApi): self.gateway = gateway # gateway对象 self.gatewayName = gateway.gatewayName # gateway对象名称 - self.orderId = 0 + self.orderId = 1000000 self.date = int(datetime.now().strftime('%y%m%d%H%M%S')) * self.orderId self.apiKey = '' @@ -245,8 +245,6 @@ class GatewayApi(BitfinexApi): #---------------------------------------------------------------------- def sendOrder(self, orderReq): """""" - orderReq.volume = 0.02 - self.orderId += 1 orderId = self.date + self.orderId vtOrderID = '.'.join([self.gatewayName, str(orderId)]) @@ -468,7 +466,7 @@ class GatewayApi(BitfinexApi): pos.exchange = EXCHANGE_BITFINEX pos.vtSymbol = '.'.join([pos.vtSymbol, pos.direction]) pos.direction = DIRECTION_LONG - pos.vtPositionName = '.'.join([pos.symbol, pos.direction]) + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) pos.position = float(data[2]) if data[-1] is None: diff --git a/vnpy/trader/gateway/bitmexGateway/__init__.py b/vnpy/trader/gateway/bitmexGateway/__init__.py new file mode 100644 index 00000000..4c149c8f --- /dev/null +++ b/vnpy/trader/gateway/bitmexGateway/__init__.py @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +from vnpy.trader import vtConstant +from .bitmexGateway import BitmexGateay + +gatewayClass = BitmexGateay +gatewayName = 'BITMEX' +gatewayDisplayName = 'BITMEX' +gatewayType = vtConstant.GATEWAYTYPE_BTC +gatewayQryEnabled = False \ No newline at end of file diff --git a/vnpy/trader/gateway/bitmexGateway/bitmexGateway.py b/vnpy/trader/gateway/bitmexGateway/bitmexGateway.py new file mode 100644 index 00000000..2fd9b262 --- /dev/null +++ b/vnpy/trader/gateway/bitmexGateway/bitmexGateway.py @@ -0,0 +1,536 @@ +# encoding: UTF-8 + +''' +vnpy.api.bitmex的gateway接入 +''' + +import os +import json +import hashlib +import hmac +import time +import traceback +from datetime import datetime, timedelta +from copy import copy +from math import pow + +from vnpy.api.bitmex import BitmexRestApi, BitmexWebsocketApi +from vnpy.trader.vtGateway import * +from vnpy.trader.vtFunction import getJsonPath, getTempPath + +# 委托状态类型映射 +statusMapReverse = {} +statusMapReverse['New'] = STATUS_NOTTRADED +statusMapReverse['Partially filled'] = STATUS_PARTTRADED +statusMapReverse['Filled'] = STATUS_ALLTRADED +statusMapReverse['Canceled'] = STATUS_CANCELLED +statusMapReverse['Rejected'] = STATUS_REJECTED + +# 方向映射 +directionMap = {} +directionMap[DIRECTION_LONG] = 'Buy' +directionMap[DIRECTION_SHORT] = 'Sell' +directionMapReverse = {v:k for k,v in directionMap.items()} + +# 价格类型映射 +priceTypeMap = {} +priceTypeMap[PRICETYPE_LIMITPRICE] = 'Limit' +priceTypeMap[PRICETYPE_MARKETPRICE] = 'Market' + + + +######################################################################## +class BitmexGateay(VtGateway): + """Bitfinex接口""" + + #---------------------------------------------------------------------- + def __init__(self, eventEngine, gatewayName=''): + """Constructor""" + super(BitmexGateay, self).__init__(eventEngine, gatewayName) + + self.restApi = RestApi(self) + self.wsApi = WebsocketApi(self) + + self.qryEnabled = False # 是否要启动循环查询 + + self.fileName = self.gatewayName + '_connect.json' + self.filePath = getJsonPath(self.fileName, __file__) + + #---------------------------------------------------------------------- + def connect(self): + """连接""" + try: + f = file(self.filePath) + except IOError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'读取连接配置出错,请检查' + self.onLog(log) + return + + # 解析json文件 + setting = json.load(f) + try: + apiKey = str(setting['apiKey']) + apiSecret = str(setting['apiSecret']) + sessionCount = int(setting['sessionCount']) + symbols = setting['symbols'] + except KeyError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'连接配置缺少字段,请检查' + self.onLog(log) + return + + # 创建行情和交易接口对象 + self.restApi.connect(apiKey, apiSecret, sessionCount) + self.wsApi.connect(apiKey, apiSecret, symbols) + + # 初始化并启动查询 + #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() + self.wsApi.close() + + #---------------------------------------------------------------------- + def initQuery(self): + """初始化连续查询""" + if self.qryEnabled: + # 需要循环的查询函数列表 + self.qryFunctionList = [self.queryAccount] + + self.qryCount = 0 # 查询触发倒计时 + self.qryTrigger = 1 # 查询触发点 + self.qryNextFunction = 0 # 上次运行的查询函数索引 + + self.startQuery() + + #---------------------------------------------------------------------- + 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 + + #---------------------------------------------------------------------- + def startQuery(self): + """启动连续查询""" + self.eventEngine.register(EVENT_TIMER, self.query) + + #---------------------------------------------------------------------- + def setQryEnabled(self, qryEnabled): + """设置是否要启动循环查询""" + self.qryEnabled = qryEnabled + + +######################################################################## +class RestApi(BitmexRestApi): + """REST API实现""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(RestApi, self).__init__() + + self.gateway = gateway # gateway对象 + self.gatewayName = gateway.gatewayName # gateway对象名称 + + self.orderId = 1000000 + self.date = int(datetime.now().strftime('%y%m%d%H%M%S')) * self.orderId + + #---------------------------------------------------------------------- + def connect(self, apiKey, apiSecret, sessionCount): + """连接服务器""" + self.init(apiKey, apiSecret) + self.start(sessionCount) + + self.writeLog(u'REST API启动成功') + + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """""" + self.orderId += 1 + orderId = self.date + self.orderId + vtOrderID = '.'.join([self.gatewayName, str(orderId)]) + + req = { + 'symbol': orderReq.symbol, + 'side': directionMap[orderReq.direction], + 'ordType': priceTypeMap[orderReq.priceType], + 'price': orderReq.price, + 'orderQty': orderReq.volume, + 'clOrdID': str(orderId) + } + self.addReq('POST', '/order', self.onSendOrder, postdict=req) + + return vtOrderID + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """""" + orderID = cancelOrderReq.orderID + if orderID.isdigit(): + req = {'clOrdID': orderID} + else: + req = {'orderID': orderID} + + self.addReq('DELETE', '/order', self.onCancelOrder, params=req) + + #---------------------------------------------------------------------- + def onSendOrder(self, data, reqid): + """""" + pass + + #---------------------------------------------------------------------- + def onCancelOrder(self, data, reqid): + """""" + pass + + #---------------------------------------------------------------------- + def onError(self, code, error): + """""" + e = VtErrorData() + e.errorID = code + e.errorID = error + self.gateway.onError(e) + + +######################################################################## +class WebsocketApi(BitmexWebsocketApi): + """""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(WebsocketApi, self).__init__() + + self.gateway = gateway + self.gatewayName = gateway.gatewayName + + self.apiKey = '' + self.apiSecret = '' + + self.callbackDict = { + 'trade': self.onTick, + 'orderBook10': self.onDepth, + 'execution': self.onTrade, + 'order': self.onOrder, + 'position': self.onPosition, + 'margin': self.onAccount, + 'instrument': self.onContract + } + + self.tickDict = {} + self.accountDict = {} + self.orderDict = {} + self.tradeSet = set() + + #---------------------------------------------------------------------- + def connect(self, apiKey, apiSecret, symbols): + """""" + self.apiKey = apiKey + self.apiSecret = apiSecret + + for symbol in symbols: + tick = VtTickData() + tick.gatewayName = self.gatewayName + tick.symbol = symbol + tick.exchange = EXCHANGE_BITMEX + tick.vtSymbol = '.'.join([tick.symbol, tick.exchange]) + self.tickDict[symbol] = tick + + self.start() + + #---------------------------------------------------------------------- + def onConnect(self): + """连接回调""" + self.writeLog(u'Websocket API连接成功') + self.authenticate() + + #---------------------------------------------------------------------- + def onData(self, data): + """数据回调""" + if 'request' in data: + req = data['request'] + success = data['success'] + + if success: + if req['op'] == 'authKey': + self.writeLog(u'Websocket API验证授权成功') + self.subscribe() + + elif 'table' in data: + name = data['table'] + callback = self.callbackDict[name] + + if isinstance(data['data'], list): + for d in data['data']: + callback(d) + else: + callback(data['data']) + + #if data['action'] == 'update' and data['table'] != 'instrument': + #callback(data['data']) + #elif data['action'] == 'partial': + #for d in data['data']: + #callback(d) + + + #---------------------------------------------------------------------- + def onError(self, msg): + """错误回调""" + self.writeLog(msg) + + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + #---------------------------------------------------------------------- + def authenticate(self): + """""" + expires = int(time.time()) + method = 'GET' + path = '/realtime' + msg = method + path + str(expires) + signature = hmac.new(self.apiSecret, msg, digestmod=hashlib.sha256).hexdigest() + + req = { + 'op': 'authKey', + 'args': [self.apiKey, expires, signature] + } + self.sendReq(req) + + #---------------------------------------------------------------------- + def subscribe(self): + """""" + req = { + 'op': 'subscribe', + 'args': ['instrument', 'trade', 'orderBook10', 'execution', 'order', 'position', 'margin'] + } + self.sendReq(req) + + #---------------------------------------------------------------------- + def onTick(self, d): + """""" + symbol = d['symbol'] + + tick = self.tickDict.get(symbol, None) + if not tick: + return + + tick.lastPrice = d['price'] + + date, time = str(d['timestamp']).split('T') + tick.date = date.replace('-', '') + tick.time = time.replace('Z', '') + + self.gateway.onTick(tick) + + #---------------------------------------------------------------------- + def onDepth(self, d): + """""" + symbol = d['symbol'] + tick = self.tickDict.get(symbol, None) + if not tick: + return + + for n, buf in enumerate(d['bids'][:5]): + price, volume = buf + tick.__setattr__('bidPrice%s' %(n+1), price) + tick.__setattr__('bidVolume%s' %(n+1), volume) + + for n, buf in enumerate(d['asks'][:5]): + price, volume = buf + tick.__setattr__('askPrice%s' %(n+1), price) + tick.__setattr__('askVolume%s' %(n+1), volume) + + date, time = str(d['timestamp']).split('T') + tick.date = date.replace('-', '') + tick.time = time.replace('Z', '') + + self.gateway.onTick(tick) + + #---------------------------------------------------------------------- + def onTrade(self, d): + """""" + if not d['lastQty']: + return + + tradeID = d['execID'] + if tradeID in self.tradeSet: + return + self.tradeSet.add(tradeID) + + trade = VtTradeData() + trade.gatewayName = self.gatewayName + + trade.symbol = d['symbol'] + trade.exchange = EXCHANGE_BITMEX + trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) + if d['clOrdID']: + orderID = d['clOrdID'] + else: + orderID = d['orderID'] + trade.orderID = orderID + trade.vtOrderID = '.'.join([trade.gatewayName, trade.orderID]) + + + trade.tradeID = tradeID + trade.vtTradeID = '.'.join([trade.gatewayName, trade.tradeID]) + + trade.direction = directionMapReverse[d['side']] + trade.price = d['lastPx'] + trade.volume = d['lastQty'] + trade.tradeTime = d['timestamp'][0:10].replace('-', '') + + self.gateway.onTrade(trade) + + #---------------------------------------------------------------------- + def onOrder(self, d): + """""" + if 'ordStatus' not in d: + return + + sysID = d['orderID'] + if sysID in self.orderDict: + order = self.orderDict[sysID] + else: + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.symbol = d['symbol'] + order.exchange = EXCHANGE_BITMEX + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + if d['clOrdID']: + orderID = d['clOrdID'] + else: + orderID = sysID + order.orderID = orderID + order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) + + order.direction = directionMapReverse[d['side']] + + if d['price']: + order.price = d['price'] + + order.totalVolume = d['orderQty'] + order.orderTime = d['timestamp'][0:10].replace('-', '') + + self.orderDict[sysID] = order + + order.tradedVolume = d.get('cumQty', order.tradedVolume) + order.status = statusMapReverse.get(d['ordStatus'], STATUS_UNKNOWN) + + self.gateway.onOrder(order) + + #---------------------------------------------------------------------- + def onPosition(self, d): + """""" + pos = VtPositionData() + pos.gatewayName = self.gatewayName + + pos.symbol = d['symbol'] + pos.exchange = EXCHANGE_BITMEX + pos.vtSymbol = '.'.join([pos.symbol, pos.exchange]) + + pos.direction = DIRECTION_NET + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) + pos.position = d['currentQty'] + pos.frozen = 0 # 期货没有冻结概念,会直接反向开仓 + + self.gateway.onPosition(pos) + + #---------------------------------------------------------------------- + def onAccount(self, d): + """""" + accoundID = str(d['account']) + + if accoundID in self.accountDict: + account = self.accountDict[accoundID] + else: + account = VtAccountData() + account.gatewayName = self.gatewayName + + account.accountID = accoundID + account.vtAccountID = '.'.join([account.gatewayName, account.accountID]) + + self.accountDict[accoundID] = account + + account.balance = d.get('marginBalance', account.balance) + account.available = d.get('availableMargin', account.available) + account.closeProfit = d.get('realisedPnl', account.closeProfit) + account.positionProfit = d.get('unrealisedPnl', account.positionProfit) + + self.gateway.onAccount(account) + + #---------------------------------------------------------------------- + def onContract(self, d): + """""" + if 'tickSize' not in d: + return + + contract = VtContractData() + contract.gatewayName = self.gatewayName + + contract.symbol = d['symbol'] + contract.exchange = EXCHANGE_BITMEX + contract.vtSymbol = '.'.join([contract.symbol, contract.exchange]) + contract.name = contract.vtSymbol + contract.productClass = PRODUCT_FUTURES + contract.priceTick = d['tickSize'] + contract.size = d['multiplier'] + + self.gateway.onContract(contract) + + +#---------------------------------------------------------------------- +def printDict(d): + """""" + print '-' * 30 + l = d.keys() + l.sort() + for k in l: + print k, d[k] + \ No newline at end of file diff --git a/vnpy/trader/language/chinese/constant.py b/vnpy/trader/language/chinese/constant.py index 0297f79a..e71970db 100644 --- a/vnpy/trader/language/chinese/constant.py +++ b/vnpy/trader/language/chinese/constant.py @@ -93,6 +93,7 @@ EXCHANGE_ZAIF = "ZAIF" # ZAIF日本比特币交易所 EXCHANGE_COINCHECK = "COINCHECK" # COINCHECK日本比特币交易所 EXCHANGE_BINANCE = "BINANCE" # 币安比特币交易所 EXCHANGE_BITFINEX = "BITFINEX" # Bitfinex比特币交易所 +EXCHANGE_BITMEX = 'BITMEX' # BitMEX比特币交易所 # 货币类型 CURRENCY_USD = 'USD' # 美元 diff --git a/vnpy/trader/language/english/constant.py b/vnpy/trader/language/english/constant.py index d62757e7..0676c8f5 100644 --- a/vnpy/trader/language/english/constant.py +++ b/vnpy/trader/language/english/constant.py @@ -89,6 +89,7 @@ EXCHANGE_ZAIF = "ZAIF" # ZAIF日本比特币交易所 EXCHANGE_COINCHECK = "COINCHECK" # COINCHECK日本比特币交易所 EXCHANGE_BINANCE = "BINANCE" # 币安比特币交易所 EXCHANGE_BITFINEX = "BITFINEX" # Bitfinex比特币交易所 +EXCHANGE_BITMEX = 'BITMEX' # BitMEX比特币交易所 # 货币类型 CURRENCY_USD = 'USD' # 美元