diff --git a/vn.huobi/README.md b/vn.huobi/README.md new file mode 100644 index 00000000..8ebafe71 --- /dev/null +++ b/vn.huobi/README.md @@ -0,0 +1,18 @@ +# vn.huobi + +### 简介 + +火币的比特币交易接口,基于Rest API(交易)和Websocket API(行情)开发,实现了官方提供API的全部功能。 + +### 特点 +相比较于[火币官方](http://github.com/huobiapi/API_Docs/)给出的Python API实现,vn.huobi的一些特点: + +1. 面向对象的API设计,接近CTP API的结构,对于国内用户而言更容易上手 + +2. 参考CTP API的设计,主动函数调用的结果通过异步(回调函数)的方式推送到程序中,适用于开发稳定可靠的实盘交易程序 + +### API版本 +日期:2015-12-02 + +链接:[http://github.com/huobiapi/API_Docs/wiki](http://github.com/huobiapi/API_Docs/wiki) + diff --git a/vn.huobi/test.py b/vn.huobi/test.py new file mode 100644 index 00000000..c75dc950 --- /dev/null +++ b/vn.huobi/test.py @@ -0,0 +1,37 @@ +# encoding: utf-8 + +from vnhuobi import * + + +if __name__ == '__main__': + accessKey = '' + secretKey = '' + + # 创建API对象并初始化 + api = TradeApi() + api.DEBUG = True + api.init(accessKey, secretKey) + + # 查询账户,测试通过 + api.getAccountInfo() + + # 查询委托,测试通过 + #api.getOrders() + + # 买入,测试通过 + #api.buy(7100, 0.0095) + + # 卖出,测试通过 + #api.sell(7120, 0.0095) + + # 撤单,测试通过 + #api.cancelOrder(3915047376L) + + # 查询杠杆额度,测试通过 + #api.getLoanAvailable() + + # 查询杠杆列表,测试通过 + #api.getLoans() + + # 阻塞 + input() diff --git a/vn.huobi/vnhuobi.py b/vn.huobi/vnhuobi.py new file mode 100644 index 00000000..eddafc68 --- /dev/null +++ b/vn.huobi/vnhuobi.py @@ -0,0 +1,503 @@ +# encoding: utf-8 + +import urllib +import hashlib + +import json +import requests +from time import time +from Queue import Queue, Empty +from threading import Thread + +# 常量定义 +COINTYPE_BTC = 1 +COINTYPE_LTC = 2 + +ACCOUNTTYPE_CNY = 1 +ACCOUNTTYPE_USD = 2 + +LOANTYPE_CNY = 1 +LOANTYPE_BTC = 2 +LOANTYPE_LTC = 3 +LOANTYPE_USD = 4 + +MARKETTYPE_CNY = 'cny' +MARKETTYPE_USD = 'usd' + +# API相关定义 +HUOBI_SERVICE_API="https://api.huobi.com/apiv3" + +FUNCTIONCODE_GETACCOUNTINFO = 'get_account_info' +FUNCTIONCODE_GETORDERS = 'get_orders' +FUNCTIONCODE_ORDERINFO = 'order_info' +FUNCTIONCODE_BUY = 'buy' +FUNCTIONCODE_SELL = 'sell' +FUNCTIONCODE_BUYMARKET = 'buy_market' +FUNCTIONCODE_SELLMARKET = 'sell_market' +FUNCTIONCODE_CANCELORDER = 'cancel_order' +FUNCTIONCODE_GETNEWDEALORDERS = 'get_new_deal_orders' +FUNCTIONCODE_GETORDERIDBYTRADEID = 'get_order_id_by_trade_id' +FUNCTIONCODE_WITHDRAWCOIN = 'withdraw_coin' +FUNCTIONCODE_CANCELWITHDRAWCOIN = 'cancel_withdraw_coin' +FUNCTIONCODE_GETWITHDRAWCOINRESULT = 'get_withdraw_coin_result' +FUNCTIONCODE_TRANSFER = 'transfer' +FUNCTIONCODE_LOAN = 'loan' +FUNCTIONCODE_REPAYMENT = 'repayment' +FUNCTIONCODE_GETLOANAVAILABLE = 'get_loan_available' +FUNCTIONCODE_GETLOANS = 'get_loans' + + +#---------------------------------------------------------------------- +def signature(params): + """生成签名""" + params = sorted(params.iteritems(), key=lambda d:d[0], reverse=False) + message = urllib.urlencode(params) + + m = hashlib.md5() + m.update(message) + m.digest() + + sig=m.hexdigest() + return sig + + +######################################################################## +class TradeApi(object): + """""" + DEBUG = True + + #---------------------------------------------------------------------- + def __init__(self): + """Constructor""" + self.accessKey = '' + self.secretKey = '' + + self.active = False # API工作状态 + self.reqID = 0 # 请求编号 + self.reqQueue = Queue() # 请求队列 + self.reqThread = Thread(target=self.processQueue) # 请求处理线程 + + #---------------------------------------------------------------------- + def processRequest(self, req): + """处理请求""" + # 读取方法和参数 + method = req['method'] + params = req['params'] + optional = req['optional'] + + # 在参数中增加必须的字段 + params['created'] = long(time()) + params['access_key'] = self.accessKey + params['secret_key'] = self.secretKey + params['method'] = method + + # 添加签名 + sign = signature(params) + params['sign'] = sign + del params['secret_key'] + + # 添加选填参数 + if optional: + params.update(optional) + + # 发送请求 + payload = urllib.urlencode(params) + + r = requests.post(HUOBI_SERVICE_API, 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 'code' in data and 'message' in data: + error = u'错误信息:%s' %data['message'] + self.onError(error, reqID) + # 请求成功 + else: + if self.DEBUG: + print callback.__name__ + callback(data, reqID) + + except Empty: + pass + + #---------------------------------------------------------------------- + def sendRequest(self, method, params, callback, optional=None): + """发送请求""" + # 请求编号加1 + self.reqID += 1 + + # 生成请求字典并放入队列中 + req = {} + req['method'] = method + req['params'] = params + req['callback'] = callback + req['optional'] = optional + req['reqID'] = self.reqID + self.reqQueue.put(req) + + # 返回请求编号 + return self.reqID + + #################################################### + ## 主动函数 + #################################################### + + #---------------------------------------------------------------------- + def init(self, accessKey, secretKey): + """初始化""" + self.accessKey = accessKey + self.secretKey = secretKey + + self.active = True + self.reqThread.start() + + #---------------------------------------------------------------------- + def exit(self): + """退出""" + self.active = False + self.reqThread.join() + + #---------------------------------------------------------------------- + def getAccountInfo(self, market='cny'): + """查询账户""" + method = FUNCTIONCODE_GETACCOUNTINFO + params = {} + callback = self.onGetAccountInfo + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def getOrders(self, coinType=COINTYPE_BTC, market='cny'): + """查询委托""" + method = FUNCTIONCODE_GETORDERS + params = {'coin_type': coinType} + callback = self.onGetOrders + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def orderInfo(self, id_, coinType=COINTYPE_BTC, market='cny'): + """获取委托详情""" + method = FUNCTIONCODE_ORDERINFO + params = { + 'coin_type': coinType, + 'id': id_ + } + callback = self.onOrderInfo + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def buy(self, price, amount, coinType=COINTYPE_BTC, + tradePassword='', tradeId = '', market='cny'): + """委托买入""" + method = FUNCTIONCODE_BUY + params = { + 'coin_type': coinType, + 'price': price, + 'amount': amount + } + callback = self.onBuy + optional = { + 'trade_password': tradePassword, + 'trade_id': tradeId, + 'market': market + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def sell(self, price, amount, coinType=COINTYPE_BTC, + tradePassword='', tradeId = '', market='cny'): + """委托卖出""" + method = FUNCTIONCODE_SELL + params = { + 'coin_type': coinType, + 'price': price, + 'amount': amount + } + callback = self.onSell + optional = { + 'trade_password': tradePassword, + 'trade_id': tradeId, + 'market': market + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def buyMarket(self, amount, coinType=COINTYPE_BTC, + tradePassword='', tradeId = '', market='cny'): + """市价买入""" + method = FUNCTIONCODE_BUYMARKET + params = { + 'coin_type': coinType, + 'amount': amount + } + callback = self.onBuyMarket + optional = { + 'trade_password': tradePassword, + 'trade_id': tradeId, + 'market': market + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def sellMarket(self, amount, coinType=COINTYPE_BTC, + tradePassword='', tradeId = '', market='cny'): + """市价卖出""" + method = FUNCTIONCODE_SELLMARKET + params = { + 'coin_type': coinType, + 'amount': amount + } + callback = self.onSellMarket + optional = { + 'trade_password': tradePassword, + 'trade_id': tradeId, + 'market': market + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def cancelOrder(self, id_, coinType=COINTYPE_BTC, market='cny'): + """撤销委托""" + method = FUNCTIONCODE_CANCELORDER + params = { + 'coin_type': coinType, + 'id': id_ + } + callback = self.onCancelOrder + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def getNewDealOrders(self, market='cny'): + """查询最新10条成交""" + method = FUNCTIONCODE_GETNEWDEALORDERS + params = {} + callback = self.onGetNewDealOrders + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def getOrderIdByTradeId(self, tradeId, coinType=COINTYPE_BTC, + market='cny'): + """通过成交编号查询委托编号""" + method = FUNCTIONCODE_GETORDERIDBYTRADEID + params = { + 'coin_type': coinType, + 'trade_id': tradeId + } + callback = self.onGetOrderIdByTradeId + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def withdrawCoin(self, withdrawAddress, withdrawAmount, + coinType=COINTYPE_BTC, tradePassword='', + market='cny', withdrawFee=0.0001): + """提币""" + method = FUNCTIONCODE_WITHDRAWCOIN + params = { + 'coin_type': coinType, + 'withdraw_address': withdrawAddress, + 'withdraw_amount': withdrawAmount + } + callback = self.onWithdrawCoin + optional = { + 'market': market, + 'withdraw_fee': withdrawFee + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def cancelWithdrawCoin(self, id_, market='cny'): + """取消提币""" + method = FUNCTIONCODE_CANCELWITHDRAWCOIN + params = {'withdraw_coin_id': id_} + callback = self.onCancelWithdrawCoin + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def onGetWithdrawCoinResult(self, id_, market='cny'): + """查询提币结果""" + method = FUNCTIONCODE_GETWITHDRAWCOINRESULT + params = {'withdraw_coin_id': id_} + callback = self.onGetWithdrawCoinResult + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def transfer(self, amountFrom, amountTo, amount, + coinType=COINTYPE_BTC ): + """账户内转账""" + method = FUNCTIONCODE_TRANSFER + params = { + 'amount_from': amountFrom, + 'amount_to': amountTo, + 'amount': amount, + 'coin_type': coinType + } + callback = self.onTransfer + optional = {} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def loan(self, amount, loan_type=LOANTYPE_CNY, + market=MARKETTYPE_CNY): + """申请杠杆""" + method = FUNCTIONCODE_LOAN + params = { + 'amount': amount, + 'loan_type': loan_type + } + callback = self.onLoan + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def repayment(self, id_, amount, repayAll=0, + market=MARKETTYPE_CNY): + """归还杠杆""" + method = FUNCTIONCODE_REPAYMENT + params = { + 'loan_id': id_, + 'amount': amount + } + callback = self.onRepayment + optional = { + 'repay_all': repayAll, + 'market': market + } + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def getLoanAvailable(self, market='cny'): + """查询杠杆额度""" + method = FUNCTIONCODE_GETLOANAVAILABLE + params = {} + callback = self.onLoanAvailable + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #---------------------------------------------------------------------- + def getLoans(self, market='cny'): + """查询杠杆列表""" + method = FUNCTIONCODE_GETLOANS + params = {} + callback = self.onGetLoans + optional = {'market': market} + return self.sendRequest(method, params, callback, optional) + + #################################################### + ## 回调函数 + #################################################### + + #---------------------------------------------------------------------- + def onError(self, error, reqID): + """错误推送""" + print error, reqID + + #---------------------------------------------------------------------- + def onGetAccountInfo(self, data, reqID): + """查询账户回调""" + print data + + #---------------------------------------------------------------------- + def onGetOrders(self, data, reqID): + """查询委托回调""" + print data + + #---------------------------------------------------------------------- + def onOrderInfo(self, data, reqID): + """委托详情回调""" + print data + + #---------------------------------------------------------------------- + def onBuy(self, data, reqID): + """买入回调""" + print data + + #---------------------------------------------------------------------- + def onSell(self, data, reqID): + """卖出回调""" + print data + + #---------------------------------------------------------------------- + def onBuyMarket(self, data, reqID): + """市价买入回调""" + print data + + #---------------------------------------------------------------------- + def onSellMarket(self, data, reqID): + """市价卖出回调""" + print data + + #---------------------------------------------------------------------- + def onCancelOrder(self, data, reqID): + """撤单回调""" + print data + + #---------------------------------------------------------------------- + def onGetNewDealOrders(self, data, reqID): + """查询最新成交回调""" + print data + + #---------------------------------------------------------------------- + def onGetOrderIdByTradeId(self, data, reqID): + """通过成交编号查询委托编号回调""" + print data + + #---------------------------------------------------------------------- + def onWithdrawCoin(self, data, reqID): + """提币回调""" + print data + + #---------------------------------------------------------------------- + def onCancelWithdrawCoin(self, data, reqID): + """取消提币回调""" + print data + + #---------------------------------------------------------------------- + def onGetWithdrawCoinResult(self, data, reqID): + """查询提币结果回调""" + print data + + #---------------------------------------------------------------------- + def onTransfer(self, data, reqID): + """转账回调""" + print data + + #---------------------------------------------------------------------- + def onLoan(self, data, reqID): + """申请杠杆回调""" + print data + + #---------------------------------------------------------------------- + def onRepayment(self, data, reqID): + """归还杠杆回调""" + print data + + #---------------------------------------------------------------------- + def onLoanAvailable(self, data, reqID): + """查询杠杆额度回调""" + print data + + #---------------------------------------------------------------------- + def onGetLoans(self, data, reqID): + """查询杠杆列表""" + print data \ No newline at end of file diff --git a/vn.trader/ctaAlgo/ctaBacktesting.py b/vn.trader/ctaAlgo/ctaBacktesting.py index 95e042d6..b7d85490 100644 --- a/vn.trader/ctaAlgo/ctaBacktesting.py +++ b/vn.trader/ctaAlgo/ctaBacktesting.py @@ -120,7 +120,7 @@ class BacktestingEngine(object): #---------------------------------------------------------------------- def loadHistoryData(self): """载入历史数据""" - host, port = loadMongoSetting() + host, port, logging = loadMongoSetting() self.dbClient = pymongo.MongoClient(host, port) collection = self.dbClient[self.dbName][self.symbol] @@ -658,8 +658,8 @@ class BacktestingEngine(object): self.output(u'平均每笔佣金:\t%s' %formatNumber(d['totalCommission']/d['totalResult'])) self.output(u'胜率\t\t%s%%' %formatNumber(d['winningRate'])) - self.output(u'平均每笔盈利\t%s' %formatNumber(d['averageWinning'])) - self.output(u'平均每笔亏损\t%s' %formatNumber(d['averageLosing'])) + self.output(u'盈利交易平均值\t%s' %formatNumber(d['averageWinning'])) + self.output(u'亏损交易平均值\t%s' %formatNumber(d['averageLosing'])) self.output(u'盈亏比:\t%s' %formatNumber(d['profitLossRatio'])) # 绘图 diff --git a/vn.trader/ctaAlgo/ctaHistoryData.py b/vn.trader/ctaAlgo/ctaHistoryData.py index 5039adee..4d7376e8 100644 --- a/vn.trader/ctaAlgo/ctaHistoryData.py +++ b/vn.trader/ctaAlgo/ctaHistoryData.py @@ -33,7 +33,7 @@ class HistoryDataEngine(object): #---------------------------------------------------------------------- def __init__(self): """Constructor""" - host, port = loadMongoSetting() + host, port, logging = loadMongoSetting() self.dbClient = pymongo.MongoClient(host, port) self.datayesClient = DatayesClient() @@ -322,7 +322,7 @@ def loadMcCsv(fileName, dbName, symbol): print u'开始读取CSV文件%s中的数据插入到%s的%s中' %(fileName, dbName, symbol) # 锁定集合,并创建索引 - host, port = loadMongoSetting() + host, port, logging = loadMongoSetting() client = pymongo.MongoClient(host, port) collection = client[dbName][symbol] diff --git a/vn.trader/ctaAlgo/tools/multiTimeFrame/ctaBacktestMultiTF.py b/vn.trader/ctaAlgo/tools/multiTimeFrame/ctaBacktestMultiTF.py index cc5c2579..f9cc0c0d 100644 --- a/vn.trader/ctaAlgo/tools/multiTimeFrame/ctaBacktestMultiTF.py +++ b/vn.trader/ctaAlgo/tools/multiTimeFrame/ctaBacktestMultiTF.py @@ -72,7 +72,7 @@ class BacktestEngineMultiTF(BacktestingEngine): """载入历史数据""" """load historical data""" - host, port = loadMongoSetting() + host, port, logging = loadMongoSetting() self.dbClient = pymongo.MongoClient(host, port) collection = self.dbClient[self.dbName][self.symbol]