diff --git a/vn.huobi/vnhuobi.py b/vn.huobi/vnhuobi.py index d81dfa27..4f5f865c 100644 --- a/vn.huobi/vnhuobi.py +++ b/vn.huobi/vnhuobi.py @@ -558,7 +558,7 @@ class DataApi(object): self.taskThread = Thread(target=self.run) # 处理任务的线程 #---------------------------------------------------------------------- - def init(self, interval, debug=True): + def init(self, interval): """初始化""" self.taskInterval = interval self.DEBUG = debug @@ -567,8 +567,8 @@ class DataApi(object): self.taskThread.start() #---------------------------------------------------------------------- - def stop(self): - """停止""" + def exit(self): + """退出""" self.active = False if self.taskThread.isAlive(): diff --git a/vn.trader/ctaAlgo/CTA_setting.json b/vn.trader/ctaAlgo/CTA_setting.json index a792abfa..a0eaa491 100644 --- a/vn.trader/ctaAlgo/CTA_setting.json +++ b/vn.trader/ctaAlgo/CTA_setting.json @@ -1,7 +1,13 @@ [ { "name": "double ema", - "className": "DoubleEmaDemo", - "vtSymbol": "IF1602" + "className": "EmaDemoStrategy", + "vtSymbol": "IF1702" + }, + + { + "name": "atr rsi", + "className": "AtrRsiStrategy", + "vtSymbol": "IC1702" } ] \ No newline at end of file diff --git a/vn.trader/ctaAlgo/ctaBacktesting.py b/vn.trader/ctaAlgo/ctaBacktesting.py index b7d85490..e4a1adaa 100644 --- a/vn.trader/ctaAlgo/ctaBacktesting.py +++ b/vn.trader/ctaAlgo/ctaBacktesting.py @@ -13,7 +13,7 @@ import multiprocessing import pymongo from ctaBase import * -from ctaSetting import * +from strategy import * from vtConstant import * from vtGateway import VtOrderData, VtTradeData @@ -881,6 +881,7 @@ def optimize(strategyClass, setting, targetName, engine = BacktestingEngine() engine.setBacktestingMode(mode) engine.setStartDate(startDate, initDays) + engine.setEndDate(endDate) engine.setSlippage(slippage) engine.setRate(rate) engine.setSize(size) diff --git a/vn.trader/ctaAlgo/ctaEngine.py b/vn.trader/ctaAlgo/ctaEngine.py index db28e24a..85e13eb2 100644 --- a/vn.trader/ctaAlgo/ctaEngine.py +++ b/vn.trader/ctaAlgo/ctaEngine.py @@ -23,7 +23,7 @@ from collections import OrderedDict from datetime import datetime, timedelta from ctaBase import * -from ctaSetting import STRATEGY_CLASS +from strategy import STRATEGY_CLASS from eventEngine import * from vtConstant import * from vtGateway import VtSubscribeReq, VtOrderReq, VtCancelOrderReq, VtLogData diff --git a/vn.trader/ctaAlgo/ctaHistoryData.py b/vn.trader/ctaAlgo/ctaHistoryData.py index d2d7b76c..aea28949 100644 --- a/vn.trader/ctaAlgo/ctaHistoryData.py +++ b/vn.trader/ctaAlgo/ctaHistoryData.py @@ -314,6 +314,55 @@ class HistoryDataEngine(object): +#---------------------------------------------------------------------- +def downloadEquityDailyBarts(self, symbol): + """ + 下载股票的日行情,symbol是股票代码 + """ + print u'开始下载%s日行情' %symbol + + # 查询数据库中已有数据的最后日期 + cl = self.dbClient[DAILY_DB_NAME][symbol] + cx = cl.find(sort=[('datetime', pymongo.DESCENDING)]) + if cx.count(): + last = cx[0] + else: + last = '' + # 开始下载数据 + import tushare as ts + + if last: + start = last['date'][:4]+'-'+last['date'][4:6]+'-'+last['date'][6:] + + data = ts.get_k_data(symbol,start) + + if not data.empty: + # 创建datetime索引 + self.dbClient[DAILY_DB_NAME][symbol].ensure_index([('datetime', pymongo.ASCENDING)], + unique=True) + + for index, d in data.iterrows(): + bar = CtaBarData() + bar.vtSymbol = symbol + bar.symbol = symbol + try: + bar.open = d.get('open') + bar.high = d.get('high') + bar.low = d.get('low') + bar.close = d.get('close') + bar.date = d.get('date').replace('-', '') + bar.time = '' + bar.datetime = datetime.strptime(bar.date, '%Y%m%d') + bar.volume = d.get('volume') + except KeyError: + print d + + flt = {'datetime': bar.datetime} + self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True) + + print u'%s下载完成' %symbol + else: + print u'找不到合约%s' %symbol #---------------------------------------------------------------------- def loadMcCsv(fileName, dbName, symbol): """将Multicharts导出的csv格式的历史数据插入到Mongo数据库中""" @@ -393,6 +442,7 @@ if __name__ == '__main__': #e = HistoryDataEngine() #sleep(1) #e.downloadEquityDailyBar('000001') + #e.downloadEquityDailyBarts('000001') # 这里将项目中包含的股指日内分钟线csv导入MongoDB,作者电脑耗时大约3分钟 loadMcCsv('IF0000_1min.csv', MINUTE_DB_NAME, 'IF0000') diff --git a/vn.trader/ctaAlgo/ctaSetting.py b/vn.trader/ctaAlgo/ctaSetting.py deleted file mode 100644 index 9115e9d2..00000000 --- a/vn.trader/ctaAlgo/ctaSetting.py +++ /dev/null @@ -1,14 +0,0 @@ -# encoding: UTF-8 - -''' -在本文件中引入所有希望在系统中使用的策略类 - -这个字典中保存了需要运行的策略的名称和策略类的映射关系, -用户的策略类写好后,先在该文件中引入,并设置好名称,然后 -在CTA_setting.json中写入具体每个策略对象的类和合约设置。 -''' - -from ctaDemo import DoubleEmaDemo - -STRATEGY_CLASS = {} -STRATEGY_CLASS['DoubleEmaDemo'] = DoubleEmaDemo \ No newline at end of file diff --git a/vn.trader/ctaAlgo/strategy/__init__.py b/vn.trader/ctaAlgo/strategy/__init__.py new file mode 100644 index 00000000..a452d5b1 --- /dev/null +++ b/vn.trader/ctaAlgo/strategy/__init__.py @@ -0,0 +1,31 @@ +# encoding: UTF-8 + +''' +动态载入所有的策略类 +''' + +import os +import importlib + +# 用来保存策略类的字典 +STRATEGY_CLASS = {} + +# 获取目录路径 +path = os.path.abspath(os.path.dirname(__file__)) + +# 遍历strategy目录下的文件 +for root, subdirs, files in os.walk(path): + for name in files: + # 只有文件名中包含strategy且非.pyc的文件,才是策略文件 + if 'strategy' in name and '.pyc' not in name: + # 模块名称需要上前缀 + moduleName = 'ctaAlgo.strategy.' + name.replace('.py', '') + + # 使用importlib动态载入模块 + module = importlib.import_module(moduleName) + + # 遍历模块下的对象,只有名称中包含'Strategy'的才是策略类 + for k in dir(module): + if 'Strategy' in k: + v = module.__getattribute__(k) + STRATEGY_CLASS[k] = v diff --git a/vn.trader/ctaAlgo/strategyAtrRsi.py b/vn.trader/ctaAlgo/strategy/strategyAtrRsi.py similarity index 100% rename from vn.trader/ctaAlgo/strategyAtrRsi.py rename to vn.trader/ctaAlgo/strategy/strategyAtrRsi.py diff --git a/vn.trader/ctaAlgo/ctaDemo.py b/vn.trader/ctaAlgo/strategy/strategyEmaDemo.py similarity index 97% rename from vn.trader/ctaAlgo/ctaDemo.py rename to vn.trader/ctaAlgo/strategy/strategyEmaDemo.py index 747be12a..024163f6 100644 --- a/vn.trader/ctaAlgo/ctaDemo.py +++ b/vn.trader/ctaAlgo/strategy/strategyEmaDemo.py @@ -17,9 +17,9 @@ from ctaTemplate import CtaTemplate ######################################################################## -class DoubleEmaDemo(CtaTemplate): +class EmaDemoStrategy(CtaTemplate): """双指数均线策略Demo""" - className = 'DoubleEmaDemo' + className = 'EmaDemoStrategy' author = u'用Python的交易员' # 策略参数 @@ -59,7 +59,7 @@ class DoubleEmaDemo(CtaTemplate): #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" - super(DoubleEmaDemo, self).__init__(ctaEngine, setting) + super(EmaDemoStrategy, self).__init__(ctaEngine, setting) # 注意策略类中的可变对象属性(通常是list和dict等),在策略初始化时需要重新创建, # 否则会出现多个策略实例之间数据共享的情况,有可能导致潜在的策略逻辑错误风险, @@ -188,10 +188,10 @@ class DoubleEmaDemo(CtaTemplate): ######################################################################################## -class OrderManagementDemo(CtaTemplate): +class OrderManagementDemoStrategy(CtaTemplate): """基于tick级别细粒度撤单追单测试demo""" - className = 'OrderManagementDemo' + className = 'OrderManagementDemoStrategy' author = u'用Python的交易员' # 策略参数 @@ -216,7 +216,7 @@ class OrderManagementDemo(CtaTemplate): #---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" - super(OrderManagementDemo, self).__init__(ctaEngine, setting) + super(OrderManagementDemoStrategy, self).__init__(ctaEngine, setting) self.lastOrder = None self.orderType = '' diff --git a/vn.trader/huobiGateway/HUOBI_connect.json b/vn.trader/huobiGateway/HUOBI_connect.json new file mode 100644 index 00000000..939ae0d8 --- /dev/null +++ b/vn.trader/huobiGateway/HUOBI_connect.json @@ -0,0 +1,6 @@ +{ + "accessKey": "3f669293-60e6dd7f-8e39c295-5aae5", + "secretKey": "7050aec8-43fc680d-06471837-57e38", + "interval": 0.5, + "market": "cny" +} \ No newline at end of file diff --git a/vn.trader/huobiGateway/__init__.py b/vn.trader/huobiGateway/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vn.trader/huobiGateway/huobiGateway.py b/vn.trader/huobiGateway/huobiGateway.py new file mode 100644 index 00000000..ad67c4fd --- /dev/null +++ b/vn.trader/huobiGateway/huobiGateway.py @@ -0,0 +1,347 @@ +# encoding: UTF-8 + +''' +vn.huobi的gateway接入 +''' + + +import os +import json +from datetime import datetime +from copy import copy +from threading import Condition +from Queue import Queue +from threading import Thread + +import vnhuobi +from vtGateway import * + + +######################################################################## +class HuobiGateway(VtGateway): + """火币接口""" + + #---------------------------------------------------------------------- + def __init__(self, eventEngine, gatewayName='HUOBI'): + """Constructor""" + super(HuobiGateway, self).__init__(eventEngine, gatewayName) + + self.market = 'cny' + + self.tradeApi = HuobiTradeApi(self) + self.dataApi = HuobiDataApi(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['accessKey']) + secretKey = str(setting['secretKey']) + interval = setting['interval'] + market = setting['market'] + except KeyError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'连接配置缺少字段,请检查' + self.onLog(log) + return + + # 初始化接口 + self.tradeApi.connect(accessKey, secretKey) + self.writeLog(u'交易接口初始化成功') + + self.dataApi.connect(interval) + 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): + """发单""" + pass + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """撤单""" + pass + + #---------------------------------------------------------------------- + def qryAccount(self): + """查询账户资金""" + pass + + #---------------------------------------------------------------------- + def qryPosition(self): + """查询持仓""" + pass + + #---------------------------------------------------------------------- + def close(self): + """关闭""" + self.tradeApi.exit() + self.dataApi.exit() + + #---------------------------------------------------------------------- + def initQuery(self): + """初始化连续查询""" + if self.qryEnabled: + # 需要循环的查询函数列表 + self.qryFunctionList = [self.qryAccount] + + self.qryCount = 0 # 查询触发倒计时 + self.qryTrigger = 2 # 查询触发点 + 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 HuobiTradeApi(vnhuobi.TradeApi): + """交易接口""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(HuobiTradeApi, self).__init__() + + self.gateway = gateway + self.gatewayName = gateway.gatewayName + + #---------------------------------------------------------------------- + def onError(self, error, reqID): + """错误推送""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorMsg = str(error) + err.errorTime = datetime.now().strftime('%H:%M:%S') + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onGetAccountInfo(self, data, reqID): + """查询账户回调""" + # 推送账户数据 + account = VtAccountData() + account.gatewayName = self.gatewayName + account.balance = data['net_asset'] + self.gateway.onAccount(account) + + # 推送持仓数据 + if self.market == 'cny': + posCny = VtPositionData() + posCny.gatewayName = self.gatewayName + posCny.position = data['available_cny_display'] + posCny.frozen = data['frozen_cny_display'] + self.gateway.onPosition(posCny) + + posLtc = VtPositionData() + posLtc.gatewayName = self.gatewayName + posLtc.position = data['available_ltc_display'] + posLtc.frozen = data['frozen_ltc_display'] + self.gateway.onPosition(posLtc) + else: + posUsd = VtPositionData() + posUsd.gatewayName = self.gatewayName + posUsd.position = data['available_usd_display'] + posUsd.frozen = data['frozen_usd_display'] + self.gateway.onPosition(posUsd) + + posBtc = VtPositionData() + posBtc.gatewayName = self.gatewayName + posBtc.position = data['available_btc_display'] + posBtc.frozen = data['frozen_btc_display'] + self.gateway.onPosition(posBtc) + + #---------------------------------------------------------------------- + def onGetOrders(self, data, reqID): + """查询委托回调""" + for d in data: + order = VtOrderData() + order.gatewayName = self.gatewayName + + order + + #---------------------------------------------------------------------- + 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 + + #---------------------------------------------------------------------- + def connect(self, accessKey, secretKey, market): + """连接服务器""" + self.market = market + + self.init(accessKey, secretKey) + + +######################################################################## +class HuobiDataApi(vnhuobi.DataApi): + """行情接口""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(HuobiDataApi, self).__init__() + + self.gateway = gateway + + #---------------------------------------------------------------------- + def onTick(self, data): + """实时成交推送""" + print data + + #---------------------------------------------------------------------- + def onQuote(self, data): + """实时报价推送""" + print data + + #---------------------------------------------------------------------- + def onDepth(self, data): + """实时深度推送""" + print data + + #---------------------------------------------------------------------- + def connect(self, interval): + """连接服务器""" + self.init(interval) + + + + + + + + diff --git a/vn.trader/huobiGateway/vnhuobi.py b/vn.trader/huobiGateway/vnhuobi.py new file mode 100644 index 00000000..4f5f865c --- /dev/null +++ b/vn.trader/huobiGateway/vnhuobi.py @@ -0,0 +1,650 @@ +# encoding: utf-8 + +import urllib +import hashlib + +import json +import requests +from time import time, sleep +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' + +SYMBOL_BTCCNY = 'BTC_CNY' +SYMBOL_LTCCNY = 'LTC_CNY' +SYMBOL_BTCUSD = 'BTC_USD' + +PERIOD_1MIN = '001' +PERIOD_5MIN = '005' +PERIOD_15MIN = '015' +PERIOD_30MIN = '030' +PERIOD_60MIN = '060' +PERIOD_DAILY = '100' +PERIOD_WEEKLY = '200' +PERIOD_MONTHLY = '300' +PERIOD_ANNUALLY = '400' + +# API相关定义 +HUOBI_TRADE_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_TRADE_API_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 + + +######################################################################## +class DataApi(object): + """行情接口""" + TICK_SYMBOL_URL = { + SYMBOL_BTCCNY: 'http://api.huobi.com/staticmarket/detail_btc_json.js', + SYMBOL_LTCCNY: 'http://api.huobi.com/staticmarket/detail_ltc_json.js', + SYMBOL_BTCUSD: 'http://api.huobi.com/usdmarket/detail_btc_json.js' + } + + QUOTE_SYMBOL_URL = { + SYMBOL_BTCCNY: 'http://api.huobi.com/staticmarket/ticker_btc_json.js', + SYMBOL_LTCCNY: 'http://api.huobi.com/staticmarket/ticker_ltc_json.js', + SYMBOL_BTCUSD: 'http://api.huobi.com/usdmarket/ticker_btc_json.js' + } + + DEPTH_SYMBOL_URL = { + SYMBOL_BTCCNY: 'http://api.huobi.com/staticmarket/depth_btc_json.js', + SYMBOL_LTCCNY: 'http://api.huobi.com/staticmarket/depth_ltc_json.js', + SYMBOL_BTCUSD: 'http://api.huobi.com/usdmarket/depth_btc_json.js' + } + + KLINE_SYMBOL_URL = { + SYMBOL_BTCCNY: 'http://api.huobi.com/staticmarket/btc_kline_[period]_json.js', + SYMBOL_LTCCNY: 'http://api.huobi.com/staticmarket/btc_kline_[period]_json.js', + SYMBOL_BTCUSD: 'http://api.huobi.com/usdmarket/btc_kline_[period]_json.js' + } + + DEBUG = True + + #---------------------------------------------------------------------- + def __init__(self): + """Constructor""" + self.active = False + + self.taskInterval = 0 # 每轮请求延时 + self.taskList = [] # 订阅的任务列表 + self.taskThread = Thread(target=self.run) # 处理任务的线程 + + #---------------------------------------------------------------------- + def init(self, interval): + """初始化""" + self.taskInterval = interval + self.DEBUG = debug + + self.active = True + self.taskThread.start() + + #---------------------------------------------------------------------- + def exit(self): + """退出""" + self.active = False + + if self.taskThread.isAlive(): + self.taskThread.join() + + #---------------------------------------------------------------------- + def run(self): + """连续运行""" + while self.active: + for url, callback in self.taskList: + try: + r = requests.get(url) + if r.status_code == 200: + data = r.json() + if self.DEBUG: + print callback.__name__ + callback(data) + except Exception, e: + print e + + sleep(self.taskInterval) + + #---------------------------------------------------------------------- + def subscribeTick(self, symbol): + """订阅实时成交数据""" + url = self.TICK_SYMBOL_URL[symbol] + task = (url, self.onTick) + self.taskList.append(task) + + #---------------------------------------------------------------------- + def subscribeQuote(self, symbol): + """订阅实时报价数据""" + url = self.QUOTE_SYMBOL_URL[symbol] + task = (url, self.onQuote) + self.taskList.append(task) + + #---------------------------------------------------------------------- + def subscribeDepth(self, symbol, level=0): + """订阅深度数据""" + url = self.DEPTH_SYMBOL_URL[symbol] + + if level: + url = url.replace('json', str(level)) + + task = (url, self.onDepth) + self.taskList.append(task) + + #---------------------------------------------------------------------- + def onTick(self, data): + """实时成交推送""" + print data + + #---------------------------------------------------------------------- + def onQuote(self, data): + """实时报价推送""" + print data + + #---------------------------------------------------------------------- + def onDepth(self, data): + """实时深度推送""" + print data + + #---------------------------------------------------------------------- + def getKline(self, symbol, period, length=0): + """查询K线数据""" + url = self.KLINE_SYMBOL_URL[symbol] + url = url.replace('[period]', period) + + if length: + url = url + '?length=' + str(length) + + try: + r = requests.get(url) + if r.status_code == 200: + data = r.json() + return data + except Exception, e: + print e + return None \ No newline at end of file diff --git a/vn.trader/okcoinGateway/okcoinGateway.py b/vn.trader/okcoinGateway/okcoinGateway.py index 917a070e..9e3509e7 100644 --- a/vn.trader/okcoinGateway/okcoinGateway.py +++ b/vn.trader/okcoinGateway/okcoinGateway.py @@ -4,8 +4,7 @@ vn.okcoin的gateway接入 注意: -1. 该接口尚处于测试阶段,用于实盘请谨慎 -2. 目前仅支持USD和CNY的现货交易,USD的期货合约交易暂不支持 +1. 前仅支持USD和CNY的现货交易,USD的期货合约交易暂不支持 '''