diff --git a/vn.huobi/vnhuobi.py b/vn.huobi/vnhuobi.py index fd00a771..92ac65ba 100644 --- a/vn.huobi/vnhuobi.py +++ b/vn.huobi/vnhuobi.py @@ -185,7 +185,9 @@ class TradeApi(object): def exit(self): """退出""" self.active = False - self.reqThread.join() + + if self.reqThread.isAlive(): + self.reqThread.join() #---------------------------------------------------------------------- def getAccountInfo(self, market='cny'): diff --git a/vn.lhang/test.py b/vn.lhang/test.py index f59fd509..717cb2b2 100644 --- a/vn.lhang/test.py +++ b/vn.lhang/test.py @@ -6,13 +6,13 @@ from vnlhang import LhangApi if __name__ == '__main__': - apiKey = '259ad3a4-3e19-489e-935d-71b43ad65be8' - secretKey = '9A4D9094315681F62FB4C7FB6494FBD2' + apiKey = '' + secretKey = '' # 创建API对象并初始化 api = LhangApi() api.DEBUG = True - api.init(apiKey, secretKey) + api.init(apiKey, secretKey, 2) # 查询行情 api.getTicker('btc_cny') diff --git a/vn.trader/huobiGateway/vnhuobi.py b/vn.trader/huobiGateway/vnhuobi.py index fd00a771..92ac65ba 100644 --- a/vn.trader/huobiGateway/vnhuobi.py +++ b/vn.trader/huobiGateway/vnhuobi.py @@ -185,7 +185,9 @@ class TradeApi(object): def exit(self): """退出""" self.active = False - self.reqThread.join() + + if self.reqThread.isAlive(): + self.reqThread.join() #---------------------------------------------------------------------- def getAccountInfo(self, market='cny'): diff --git a/vn.trader/lhangGateway/LHANG_connect.json b/vn.trader/lhangGateway/LHANG_connect.json new file mode 100644 index 00000000..5df1ee29 --- /dev/null +++ b/vn.trader/lhangGateway/LHANG_connect.json @@ -0,0 +1,6 @@ +{ + "apiKey": "请在链行官网申请", + "secretKey": "请在链行官网申请", + "interval": 1, + "debug": false +} diff --git a/vn.trader/lhangGateway/__init__.py b/vn.trader/lhangGateway/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vn.trader/lhangGateway/lhangGateway.py b/vn.trader/lhangGateway/lhangGateway.py new file mode 100644 index 00000000..645faf4c --- /dev/null +++ b/vn.trader/lhangGateway/lhangGateway.py @@ -0,0 +1,528 @@ +# encoding: UTF-8 + +''' +vn.lhang的gateway接入 +''' + + +import os +import json +from datetime import datetime +from time import sleep + +import vnlhang +from vtGateway import * + + +SYMBOL_BTCCNY = 'BTCCNY' +SYMBOL_ZECCNY = 'ZECCNY' + +SYMBOL_MAP = {} +SYMBOL_MAP['btc_cny'] = SYMBOL_BTCCNY +SYMBOL_MAP['zec_cny'] = SYMBOL_ZECCNY +SYMBOL_MAP_REVERSE = {v: k for k, v in SYMBOL_MAP.items()} + + +DIRECTION_MAP = {} +DIRECTION_MAP['buy'] = DIRECTION_LONG +DIRECTION_MAP['sell'] = DIRECTION_SHORT + +STATUS_MAP = {} +STATUS_MAP[0] = STATUS_NOTTRADED +STATUS_MAP[1] = STATUS_PARTTRADED +STATUS_MAP[2] = STATUS_ALLTRADED +STATUS_MAP[4] = STATUS_UNKNOWN +STATUS_MAP[-1] = STATUS_CANCELLED + + +######################################################################## +class LhangGateway(VtGateway): + """链行接口""" + + #---------------------------------------------------------------------- + def __init__(self, eventEngine, gatewayName='LHANG'): + """Constructor""" + super(LhangGateway, self).__init__(eventEngine, gatewayName) + + self.api = LhangApi(self) + + #---------------------------------------------------------------------- + def connect(self): + """连接""" + # 载入json文件 + fileName = self.gatewayName + '_connect.json' + path = os.path.abspath(os.path.dirname(__file__)) + fileName = os.path.join(path, fileName) + + try: + f = file(fileName) + except IOError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'读取连接配置出错,请检查' + self.onLog(log) + return + + # 解析json文件 + setting = json.load(f) + try: + accessKey = str(setting['apiKey']) + secretKey = str(setting['secretKey']) + interval = setting['interval'] + debug = setting['debug'] + except KeyError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'连接配置缺少字段,请检查' + self.onLog(log) + return + + # 初始化接口 + self.api.connect(accessKey, secretKey, interval, debug) + self.writeLog(u'接口初始化成功') + + # 启动查询 + self.initQuery() + self.startQuery() + + #---------------------------------------------------------------------- + def writeLog(self, content): + """发出日志""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.onLog(log) + + #---------------------------------------------------------------------- + def subscribe(self, subscribeReq): + """订阅行情,自动订阅全部行情,无需实现""" + pass + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """发单""" + self.api.sendOrder(orderReq) + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """撤单""" + self.api.cancel(cancelOrderReq) + + #---------------------------------------------------------------------- + def qryAccount(self): + """查询账户资金""" + pass + + #---------------------------------------------------------------------- + def qryPosition(self): + """查询持仓""" + pass + + #---------------------------------------------------------------------- + def close(self): + """关闭""" + self.api.exit() + + #---------------------------------------------------------------------- + def initQuery(self): + """初始化连续查询""" + if self.qryEnabled: + self.qryFunctionList = [self.api.queryPrice, + self.api.queryWorkingOrders, + self.api.queryAccount] + self.startQuery() + + #---------------------------------------------------------------------- + def query(self, event): + """注册到事件处理引擎上的查询函数""" + for function in self.qryFunctionList: + function() + + #---------------------------------------------------------------------- + def startQuery(self): + """启动连续查询""" + self.eventEngine.register(EVENT_TIMER, self.query) + + #---------------------------------------------------------------------- + def setQryEnabled(self, qryEnabled): + """设置是否要启动循环查询""" + self.qryEnabled = qryEnabled + + +######################################################################## +class LhangApi(vnlhang.LhangApi): + """""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(LhangApi, self).__init__() + + self.gateway = gateway + self.gatewayName = gateway.gatewayName + + self.interval = 1 + + self.localID = 0 # 本地委托号 + self.localSystemDict = {} # key:localID, value:systemID + self.systemLocalDict = {} # key:systemID, value:localID + self.workingOrderDict = {} # key:localID, value:order + self.reqLocalDict = {} # key:reqID, value:localID + self.cancelDict = {} # key:localID, value:cancelOrderReq + + self.tradeID = 0 + + self.tickDict = {} # key:symbol, value:tick + + #---------------------------------------------------------------------- + def onError(self, error, req, reqID): + """错误推送""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorMsg = str(error) + err.errorTime = datetime.now().strftime('%H:%M:%S') + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onGetTicker(self, data, req, reqID): + """查询行情回调""" + ticker = data['ticker'] + params = req['params'] + symbol = SYMBOL_MAP[params['symbol']] + + if symbol not in self.tickDict: + tick = VtTickData() + tick.gatewayName = self.gatewayName + + tick.symbol = symbol + tick.exchange = EXCHANGE_LHANG + tick.vtSymbol = '.'.join([tick.symbol, tick.exchange]) + self.tickDict[symbol] = tick + else: + tick = self.tickDict[symbol] + + tick.highPrice = float(ticker['high']) + tick.lowPrice = float(ticker['low']) + tick.lastPrice = float(ticker['latest']) + tick.openPrice = tick.lastPrice - float(ticker['change']) + tick.volume = ticker['vol'] + + # ---------------------------------------------------------------------- + def onGetDepth(self, data, req, reqID): + """查询深度回调""" + params = req['params'] + symbol = SYMBOL_MAP[params['symbol']] + if symbol not in self.tickDict: + tick = VtTickData() + tick.gatewayName = self.gatewayName + + tick.symbol = symbol + tick.exchange = EXCHANGE_LHANG + tick.vtSymbol = '.'.join([tick.symbol, tick.exchange]) + self.tickDict[symbol] = tick + else: + tick = self.tickDict[symbol] + + tick.bidPrice1, tick.bidVolume1 = data['bids'][0] + tick.bidPrice2, tick.bidVolume2 = data['bids'][1] + tick.bidPrice3, tick.bidVolume3 = data['bids'][2] + tick.bidPrice4, tick.bidVolume4 = data['bids'][3] + tick.bidPrice5, tick.bidVolume5 = data['bids'][4] + + tick.askPrice1, tick.askVolume1 = data['asks'][0] + tick.askPrice2, tick.askVolume2 = data['asks'][1] + tick.askPrice3, tick.askVolume3 = data['asks'][2] + tick.askPrice4, tick.askVolume4 = data['asks'][3] + tick.askPrice5, tick.askVolume5 = data['asks'][4] + + now = datetime.now() + tick.time = now.strftime('%H:%M:%S') + tick.date = now.strftime('%Y%m%d') + + self.gateway.onTick(tick) + + # ---------------------------------------------------------------------- + def onGetTrades(self, data, req, reqID): + """查询历史成交""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetKline(self, data, req, reqID): + print data, reqID + + # ---------------------------------------------------------------------- + def onGetUserInfo(self, data, req, reqID): + """查询K线回报""" + d = data['info'] + account = VtAccountData() + account.gatewayName = self.gatewayName + account.accountID = self.gatewayName + account.vtAccountID = '.'.join([account.accountID, self.gatewayName]) + account.balance = d['asset']['net'] + self.gateway.onAccount(account) + + # 推送持仓数据 + posCny = VtPositionData() + posCny.gatewayName = self.gatewayName + posCny.symbol = 'CNY' + posCny.exchange = EXCHANGE_LHANG + posCny.vtSymbol = '.'.join([posCny.symbol, posCny.exchange]) + posCny.vtPositionName = posCny.vtSymbol + posCny.frozen = d['freeze']['cny'] + posCny.position = posCny.frozen + d['free']['cny'] + self.gateway.onPosition(posCny) + + posBtc = VtPositionData() + posBtc.gatewayName = self.gatewayName + posBtc.symbol = 'BTC' + posBtc.exchange = EXCHANGE_LHANG + posBtc.vtSymbol = '.'.join([posBtc.symbol, posBtc.exchange]) + posBtc.vtPositionName = posBtc.vtSymbol + posBtc.frozen = d['freeze']['btc'] + posBtc.position = posBtc.frozen + d['free']['btc'] + self.gateway.onPosition(posBtc) + + posZec = VtPositionData() + posZec.gatewayName = self.gatewayName + posZec.symbol = 'ZEC' + posZec.exchange = EXCHANGE_LHANG + posZec.vtSymbol = '.'.join([posZec.symbol, posZec.exchange]) + posZec.vtPositionName = posZec.vtSymbol + posZec.frozen = d['freeze']['zec'] + posZec.position = posZec.frozen + d['free']['zec'] + self.gateway.onPosition(posZec) + + # 查询历史委托 + self.queryOrders() + + # ---------------------------------------------------------------------- + def onCreateOrder(self, data, req, reqID): + """发单回调""" + localID = self.reqLocalDict[reqID] + systemID = data['id'] + self.localSystemDict[localID] = systemID + self.systemLocalDict[systemID] = localID + + # 撤单 + if localID in self.cancelDict: + req = self.cancelDict[localID] + self.cancel(req) + del self.cancelDict[localID] + + # 推送委托信息 + order = self.workingOrderDict[localID] + if data['result'] == 'success': + order.status = STATUS_NOTTRADED + self.gateway.onOrder(order) + + # ---------------------------------------------------------------------- + def onCancelOrder(self, data, req, reqID): + """撤单回调""" + if data['result'] == 'success': + systemID = req['params']['id'] + localID = self.systemLocalDict[systemID] + + order = self.workingOrderDict[localID] + order.status = STATUS_CANCELLED + + del self.workingOrderDict[localID] + self.gateway.onOrder(order) + + # ---------------------------------------------------------------------- + def onGetOrdersInfo(self, data, req, reqID): + """查询委托回报""" + if 'orders' in data: + for d in data['orders']: + systemID = d['order_id'] + localID = self.systemLocalDict[systemID] + order = self.workingOrderDict.get(localID, None) + if not order: + return + + # 记录最新成交的金额 + newTradeVolume = float(d['deal_amount']) - order.tradedVolume + if newTradeVolume: + trade = VtTradeData() + trade.gatewayName = self.gatewayName + trade.symbol = order.symbol + trade.vtSymbol = order.vtSymbol + + self.tradeID += 1 + trade.tradeID = str(self.tradeID) + trade.vtTradeID = '.'.join([trade.tradeID, trade.gatewayName]) + + trade.volume = newTradeVolume + trade.price = d['avg_price'] + trade.direction = order.direction + trade.offset = order.offset + trade.exchange = order.exchange + trade.tradeTime = datetime.now().strftime('%H:%M:%S') + + self.gateway.onTrade(trade) + + # 更新委托状态 + order.tradedVolume = float(d['deal_amount']) + order.status = STATUS_MAP.get(d['status'], STATUS_UNKNOWN) + + if newTradeVolume: + self.gateway.onOrder(order) + + if order.status == STATUS_ALLTRADED or order.status == STATUS_CANCELLED: + del self.workingOrderDict[order.orderID] + + # ---------------------------------------------------------------------- + def onGetOrdersInfoHistory(self, data, req, reqID): + """撤单回报""" + if 'orders' in data: + for d in data['orders']: + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.symbol = SYMBOL_MAP[data['symbol']] + order.exchange = EXCHANGE_LHANG + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + systemID = d['order_id'] + self.localID += 1 + localID = str(self.localID) + self.systemLocalDict[systemID] = localID + self.localSystemDict[localID] = systemID + order.orderID = localID + order.vtOrderID = '.'.join([order.orderID, order.gatewayName]) + + order.totalVolume = float(d['amount']) + order.tradedVolume = float(d['deal_amount']) + order.price = float(d['price']) + order.direction = DIRECTION_MAP[d['type']] + order.offset = OFFSET_NONE + order.orderTime = datetime.fromtimestamp(d['create_time'], '%H:%M:%S') + + # 委托状态 + if order.tradedVolume == 0: + order.status = STATUS_NOTTRADED + else: + order.status = STATUS_PARTTRADED + + # 缓存病推送 + self.workingOrderDict[localID] = order + self.gateway.onOrder(order) + + #---------------------------------------------------------------------- + def connect(self, apiKey, secretKey, interval, debug): + """初始化""" + self.interval = interval + self.DEBUG = debug + + self.init(apiKey, secretKey, self.interval) + + # 推送合约信息 + contract = VtContractData() + contract.gatewayName = self.gatewayName + contract.symbol = SYMBOL_BTCCNY + contract.exchange = EXCHANGE_LHANG + contract.vtSymbol = '.'.join([contract.symbol, contract.exchange]) + contract.name = u'人民币现货BTC' + contract.size = 1 + contract.priceTick = 0.01 + contract.productClass = PRODUCT_SPOT + self.gateway.onContract(contract) + + contract = VtContractData() + contract.gatewayName = self.gatewayName + contract.symbol = SYMBOL_ZECCNY + contract.exchange = EXCHANGE_LHANG + contract.vtSymbol = '.'.join([contract.symbol, contract.exchange]) + contract.name = u'人民币现货ZEC' + contract.size = 1 + contract.priceTick = 0.01 + contract.productClass = PRODUCT_SPOT + self.gateway.onContract(contract) + + #---------------------------------------------------------------------- + def sendOrder(self, req): + """发单""" + """发送委托""" + # 检查是否填入了价格,禁止市价委托 + if req.priceType != PRICETYPE_LIMITPRICE: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorMsg = u'链行接口仅支持限价单' + err.errorTime = datetime.now().strftime('%H:%M:%S') + self.gateway.onError(err) + return None + + # 发送限价委托 + s = SYMBOL_MAP_REVERSE[req.symbol] + + if req.direction == DIRECTION_LONG: + type_ = 'buy' + else: + type_ = 'sell' + + reqID = self.createOrder(s, type_, req.price, req.volume) + + self.localID += 1 + localID = str(self.localID) + self.reqLocalDict[reqID] = localID + + # 推送委托信息 + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.symbol = req.symbol + order.exchange = EXCHANGE_LHANG + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + order.orderID = localID + order.vtOrderID = '.'.join([order.orderID, order.gatewayName]) + + order.direction = req.direction + order.offset = OFFSET_UNKNOWN + order.price = req.price + order.volume = req.volume + order.orderTime = datetime.now().strftime('%H:%M:%S') + order.status = STATUS_UNKNOWN + + self.workingOrderDict[localID] = order + self.gateway.onOrder(order) + + # 返回委托号 + return order.vtOrderID + + #---------------------------------------------------------------------- + def cancel(self, req): + """撤单""" + localID = req.orderID + if localID in self.localSystemDict: + systemID = self.localSystemDict[localID] + s = SYMBOL_MAP_REVERSE[req.symbol] + self.cancelOrder(s, systemID) + else: + self.cancelDict[localID] = req + + #---------------------------------------------------------------------- + def queryOrders(self): + """查询委托""" + for s in SYMBOL_MAP.keys(): + self.getOrdersInfoHistory(s, '0', '1', '200') + + #---------------------------------------------------------------------- + def queryWorkingOrders(self): + """查询活动委托""" + for localID, order in self.workingOrderDict.items(): + if localID in self.localSystemDict: + systemID = self.localSystemDict[localID] + s = SYMBOL_MAP_REVERSE[order.symbol] + self.getOrdersInfo(s, systemID) + + #---------------------------------------------------------------------- + def queryPrice(self): + """查询行情""" + for s in SYMBOL_MAP.keys(): + self.getTicker(s) + self.getDepth(s, 5, 0) + + #---------------------------------------------------------------------- + def queryAccount(self): + """查询资金和资产""" + self.getUserInfo() \ No newline at end of file diff --git a/vn.trader/lhangGateway/vnlhang.py b/vn.trader/lhangGateway/vnlhang.py new file mode 100644 index 00000000..742a9184 --- /dev/null +++ b/vn.trader/lhangGateway/vnlhang.py @@ -0,0 +1,305 @@ +# encoding: utf-8 + +import urllib +import hashlib + +import requests +from Queue import Queue, Empty +from threading import Thread +from time import sleep + + + +LHANG_API_ROOT ="https://api.lhang.com/v1/" + +FUNCTION_TICKER = ('ticker.do', 'get') +FUNCTION_DEPTH = ('depth.do', 'get') +FUNCTION_TRADES = ('trades.do', 'get') +FUNCTION_KLINE = ('kline.do', 'get') + +FUNCTION_USERINFO = ('user_info.do', 'post') +FUNCTION_CREATEORDER = ('create_order.do', 'post') +FUNCTION_CANCELORDER = ('cancel_order.do', 'post') +FUNCTION_ORDERSINFO = ('orders_info.do', 'post') +FUNCTION_ORDERSINFOHISTORY = ('orders_info_history.do', 'post') + + +#---------------------------------------------------------------------- +def signature(params, secretKey): + """生成签名""" + params = sorted(params.iteritems(), key=lambda d:d[0], reverse=False) + params.append(('secret_key', secretKey)) + message = urllib.urlencode(params) + + m = hashlib.md5() + m.update(message) + m.digest() + + sig=m.hexdigest() + return sig + + +######################################################################## +class LhangApi(object): + """""" + DEBUG = True + + #---------------------------------------------------------------------- + def __init__(self): + """Constructor""" + self.apiKey = '' + self.secretKey = '' + + self.interval = 1 # 每次请求的间隔等待 + self.active = False # API工作状态 + self.reqID = 0 # 请求编号 + self.reqQueue = Queue() # 请求队列 + self.reqThread = Thread(target=self.processQueue) # 请求处理线程 + + #---------------------------------------------------------------------- + def init(self, apiKey, secretKey, interval): + """初始化""" + self.apiKey = apiKey + self.secretKey = secretKey + self.interval = interval + + self.active = True + self.reqThread.start() + + #---------------------------------------------------------------------- + def exit(self): + """退出""" + self.active = False + self.reqThread.join() + + #---------------------------------------------------------------------- + def processRequest(self, req): + """处理请求""" + # 读取方法和参数 + api, method = req['function'] + params = req['params'] + url = LHANG_API_ROOT + api + + # 在参数中增加必须的字段 + params['api_key'] = self.apiKey + + # 添加签名 + sign = signature(params, self.secretKey) + params['sign'] = sign + + # 发送请求 + payload = urllib.urlencode(params) + + r = requests.request(method, url, params=payload) + if r.status_code == 200: + data = r.json() + return data + else: + return None + + #---------------------------------------------------------------------- + def processQueue(self): + """处理请求队列中的请求""" + while self.active: + try: + req = self.reqQueue.get(block=True, timeout=1) # 获取请求的阻塞为一秒 + callback = req['callback'] + reqID = req['reqID'] + + data = self.processRequest(req) + + # 请求失败 + if data is None: + error = u'请求失败' + self.onError(error, req, reqID) + elif 'error_code' in data: + error = u'请求出错,错误代码:%s' % data['error_code'] + self.onError(error, req, reqID) + # 请求成功 + else: + if self.DEBUG: + print callback.__name__ + callback(data, req, reqID) + + # 流控等待 + sleep(self.interval) + + except Empty: + pass + + #---------------------------------------------------------------------- + def sendRequest(self, function, params, callback): + """发送请求""" + # 请求编号加1 + self.reqID += 1 + + # 生成请求字典并放入队列中 + req = {} + req['function'] = function + req['params'] = params + req['callback'] = callback + req['reqID'] = self.reqID + self.reqQueue.put(req) + + # 返回请求编号 + return self.reqID + + #---------------------------------------------------------------------- + def onError(self, error, req, reqID): + """错误推送""" + print error, req, reqID + + ############################################### + # 行情接口 + ############################################### + + #---------------------------------------------------------------------- + def getTicker(self, symbol): + """查询行情""" + function = FUNCTION_TICKER + params = {'symbol': symbol} + callback = self.onGetTicker + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def getDepth(self, symbol, size, merge): + """查询深度""" + function = FUNCTION_DEPTH + params = { + 'symbol': symbol, + 'size': size, + 'mege': merge + } + callback = self.onGetDepth + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def getTrades(self, symbol, size, time): + """查询历史成交""" + function = FUNCTION_TRADES + params = { + 'symbol': symbol, + 'size': size, + 'time': time + } + callback = self.onGetTrades + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def getKline(self, symbol, size, type_, time): + """查询K线""" + function = FUNCTION_TRADES + params = { + 'symbol': symbol, + 'size': size, + 'type': type_, + 'time': time + } + callback = self.onGetKline + return self.sendRequest(function, params, callback) + + #---------------------------------------------------------------------- + def onGetTicker(self, data, req, reqID): + """查询行情回调""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetDepth(self, data, req, reqID): + """查询深度回调""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetTrades(self, data, req, reqID): + """查询历史成交""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetKline(self, data, req, reqID): + """查询K线回报""" + print data, reqID + + ############################################### + # 交易接口 + ############################################### + + # ---------------------------------------------------------------------- + def getUserInfo(self): + """查询K线""" + function = FUNCTION_USERINFO + params = {} + callback = self.onGetUserInfo + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def createOrder(self, symbol, type_, price, amount): + """发送委托""" + function = FUNCTION_CREATEORDER + params = { + 'symbol': symbol, + 'type': type_, + 'price': price, + 'amount': amount + } + callback = self.onCreateOrder + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def cancelOrder(self, symbol, orderId): + """撤单""" + function = FUNCTION_CANCELORDER + params = { + 'symbol': symbol, + 'order_id': orderId + } + callback = self.onCancelOrder + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def getOrdersInfo(self, symbol, orderId): + """查询委托""" + function = FUNCTION_ORDERSINFO + params = { + 'symbol': symbol, + 'order_id': orderId + } + callback = self.onGetOrdersInfo + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def getOrdersInfoHistory(self, symbol, status, currentPage, pageLength): + """撤单""" + function = FUNCTION_ORDERSINFOHISTORY + params = { + 'symbol': symbol, + 'status': status, + 'current_page': currentPage, + 'page_length': pageLength + } + callback = self.onGetOrdersInfoHistory + return self.sendRequest(function, params, callback) + + # ---------------------------------------------------------------------- + def onGetUserInfo(self, data, req, reqID): + """查询K线回报""" + print data, reqID + + # ---------------------------------------------------------------------- + def onCreateOrder(self, data, req, reqID): + """委托回报""" + print data, reqID + + # ---------------------------------------------------------------------- + def onCancelOrder(self, data, req, reqID): + """撤单回报""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetOrdersInfo(self, data, req, reqID): + """查询委托回报""" + print data, reqID + + # ---------------------------------------------------------------------- + def onGetOrdersInfoHistory(self, data, req, reqID): + """撤单回报""" + print data, reqID + diff --git a/vn.trader/uiMainWindow.py b/vn.trader/uiMainWindow.py index 12545039..007fd8b1 100644 --- a/vn.trader/uiMainWindow.py +++ b/vn.trader/uiMainWindow.py @@ -82,6 +82,7 @@ class MainWindow(QtGui.QMainWindow): sysMenu.addSeparator() self.addConnectAction(sysMenu, 'OKCOIN') self.addConnectAction(sysMenu, 'HUOBI', u'火币') + self.addConnectAction(sysMenu, 'LHANG', u'链行') sysMenu.addSeparator() self.addConnectAction(sysMenu, 'Wind') diff --git a/vn.trader/vtConstant.py b/vn.trader/vtConstant.py index b1c0cf47..fc3efce7 100644 --- a/vn.trader/vtConstant.py +++ b/vn.trader/vtConstant.py @@ -75,6 +75,7 @@ EXCHANGE_ICE = 'ICE' # ICE交易所 EXCHANGE_OANDA = 'OANDA' # OANDA外汇做市商 EXCHANGE_OKCOIN = 'OKCOIN' # OKCOIN比特币交易所 EXCHANGE_HUOBI = 'HUOBI' # 火币比特币交易所 +EXCHANGE_LHANG = 'LHANG' # 链行比特币交易所 # 货币类型 CURRENCY_USD = 'USD' # 美元 diff --git a/vn.trader/vtEngine.py b/vn.trader/vtEngine.py index 5a0ea369..edcaabae 100644 --- a/vn.trader/vtEngine.py +++ b/vn.trader/vtEngine.py @@ -154,7 +154,14 @@ class MainEngine(object): except Exception, e: print e - #---------------------------------------------------------------------- + try: + from lhangGateway.lhangGateway import LhangGateway + self.addGateway(LhangGateway, 'LHANG') + self.gatewayDict['LHANG'].setQryEnabled(True) + except Exception, e: + print e + + #---------------------------------------------------------------------- def addGateway(self, gateway, gatewayName=None): """创建接口""" self.gatewayDict[gatewayName] = gateway(self.eventEngine, gatewayName)