更新bitmex data

This commit is contained in:
msincenselee 2018-12-15 13:58:18 +08:00
parent f5ef4708b7
commit 28a1beabbc
2 changed files with 254 additions and 0 deletions

View File

View File

@ -0,0 +1,254 @@
# encoding: UTF-8
# 从bitmex下载数据
from datetime import datetime, timezone,timedelta
from time import time
import sys
import requests
import execjs
import traceback
import hashlib
import hmac
from urllib.parse import urlencode
from collections import OrderedDict
from vnpy.trader.app.ctaStrategy.ctaBase import CtaBarData, CtaTickData
period_list = ['1min','5min','1day','1hour']
class BitmexData(object):
# ----------------------------------------------------------------------
def __init__(self, strategy=None,apiKey=None,apiSecret=None):
"""
构造函数
:param strategy: 上层策略主要用与使用strategy.writeCtaLog
"""
self.strategy = strategy
self.apiKey = apiKey
self.apiSecret = apiSecret
# 设置HTTP请求的尝试次数建立连接session
self.session = requests.session()
self.session.keep_alive = False
# ----------------------------------------------------------------------
def generateSignature(self, method, path, expires, params=None, body=None):
"""生成签名"""
# 对params在HTTP报文路径中以请求字段方式序列化
if params:
query = urlencode(sorted(params.items()))
path = path + '?' + query
if body is None:
body = ''
msg = method + '/api/v1' + path + str(expires) + body
signature = hmac.new(self.apiSecret.encode('utf-8'), msg.encode('utf-8'),
digestmod=hashlib.sha256).hexdigest()
return signature
def writeLog(self,content):
if self.strategy and hasattr(self.strategy,'writeCtaLog'):
self.strategy.writeCtaLog(content)
else:
print(content)
def writeError(self,content):
if self.strategy:
self.strategy.writeCtaError(content)
else:
print(content,file=sys.stderr)
def get_bars(self, symbol, period, callback, bar_is_completed=False,bar_freq=1, start_dt=None):
"""
返回k线数据
symbol合约
period: 周期: 1min,3min,5min,15min,30min,1day,3day,1hour,2hour,4hour,6hour,12hour
"""
ret_bars = []
if period not in period_list:
self.strategy.writeCtaError('{} not in {}'.format(period,period_list))
return False,ret_bars
period = period.replace('min','m').replace('hour','h').replace('day','d')
count = 750
if start_dt is None:
if period=='1d':
start_dt = datetime.utcnow() - timedelta(days=count-1)
elif period=='1h':
print(u'utc now():{}'.format(datetime.utcnow()))
start_dt = datetime.utcnow() - timedelta(hours=count-1)
print(u'start_dt():{}'.format(start_dt))
elif period == '5m':
start_dt = datetime.utcnow() - timedelta(minutes=(count-1) * 5)
else:
start_dt = datetime.utcnow() - timedelta(minutes=count-1)
path = '/trade/bucketed'
url = u'https://www.bitmex.com/api/v1'+path
params = {'binSize':period,'partial':True,'symbol':symbol,'startTime':start_dt.strftime('%Y-%m-%d %H:%M'),'count':count}
params = OrderedDict(sorted(params.items()))
expires = int(time() + 5)
rq = requests.Request(url=url)
p = rq.prepare()
header = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'api-expires': str(expires),
'api-key':self.apiKey,
'api-signature': self.generateSignature('GET', path, expires, params, body=p.body)
}
print(header)
session = requests.Session()
resp = session.request('GET', url, headers=header, params=params,data=None)
self.writeLog('{}开始下载:{} {}数据.开始时间:{} URL:{}'.format(datetime.now(), symbol, period,start_dt,url))
bars = None
code = resp.status_code
bars = resp.json()
if code != 200:
self.strategy.writeCtaError('get_bars {},{}'.format(code, bars))
return False, ret_bars
bar_len = len(bars)
self.writeLog(u'共下载:{}'.format(bar_len))
for i, bar in enumerate(bars):
add_bar = CtaBarData()
try:
add_bar.vtSymbol = symbol
add_bar.symbol = symbol
utc_str_time = bar.get('timestamp').replace('T',' ').replace('Z','')
utc_datetime = datetime.strptime(utc_str_time,'%Y-%m-%d %H:%M:%S.%f')
add_bar.datetime = utc_datetime + timedelta(hours=8)
# 时区得调整 +8
if period == '1h':
add_bar.datetime = add_bar.datetime - timedelta(hours=1)
elif period == '5m':
add_bar.datetime = add_bar.datetime - timedelta(minutes=5)
elif period == '1m':
add_bar.datetime = add_bar.datetime - timedelta(minutes=1)
# bitmex是以bar得结束时间作为bar得datetimevnpy是以bar得开始时间作为datetime
add_bar.date = add_bar.datetime.strftime('%Y-%m-%d')
add_bar.time = add_bar.datetime.strftime('%H:%M:%S')
add_bar.tradingDay = add_bar.date
add_bar.open = float(bar.get('open', 0.0))
add_bar.high = float(bar.get('high', 0.0))
add_bar.low = float(bar.get('low', 0.0))
add_bar.close = float(bar.get('close', 0.0))
add_bar.volume = float(bar.get('volume', 0.0))
ret_bars.append(add_bar)
except Exception as ex:
self.strategy.writeCtaError('error when convert bar:{},ex:{},t:{}'.format(bar, str(ex), traceback.format_exc()))
return False,ret_bars
if start_dt is not None and add_bar.datetime < start_dt:
continue
if callback is not None:
# 最后一个bar可能是不完整的强制修改
if i == bar_len -1 and bar_is_completed:
# 根据秒数算的话,要+1例如13:31,freq=31第31根bar
freq = int((datetime.now() - add_bar.datetime).total_seconds()/60)+1
callback(add_bar,False,freq)
else:
callback(add_bar, bar_is_completed, bar_freq)
return True,ret_bars
def download_bars(self, symbol, period, size_=None, start_dt=None):
"""
返回k线数据
symbol合约
period: 周期: 1min,3min,5min,15min,30min,1day,3day,1hour,2hour,4hour,6hour,12hour
"""
ret_bars = []
url = u'https://www.okex.com/api/v1/kline.do?symbol={}&type={}'.format(symbol, period)
if isinstance(size_,int):
url = url + u'&size={}'.format(size_)
if start_dt is not None and isinstance(start_dt,datetime):
url = url + u'&since={}'.format(int(start_dt.timestamp()*1000))
self.writeLog('{}开始下载:{} {}数据.URL:{}'.format(datetime.now(), symbol, period,url))
content = None
try:
content = self.session.get(url).content.decode('gbk')
except Exception as ex:
self.writeError('exception in get:{},{},{}'.format(url,str(ex), traceback.format_exc()))
return ret_bars
bars = execjs.eval(content)
if not isinstance(bars,list):
self.writeError('返回数据不是list:{}'.format(content))
return ret_bars
for i, bar in enumerate(bars):
if len(bar) < 5:
self.writeError('error when get bar:{}'.format(bar))
return ret_bars
if i == 0:
continue
add_bar = {}
try:
bar_datetime= datetime.fromtimestamp(bar[0] / 1000)
add_bar['datetime'] = bar_datetime.strftime('%Y-%m-%d %H:%M:%S')
add_bar['date'] = bar_datetime.strftime('%Y-%m-%d')
add_bar['time'] = bar_datetime.strftime('%H:%M:%S')
add_bar['open'] = float(bar[1])
add_bar['high'] = float(bar[2])
add_bar['low'] = float(bar[3])
add_bar['close'] = float(bar[4])
add_bar['volume'] = float(bar[5])
except Exception as ex:
self.writeError('error when convert bar:{},ex:{},t:{}'.format(bar, str(ex), traceback.format_exc()))
ret_bars.append(add_bar)
return ret_bars
class TestStrategy(object):
def __init__(self):
self.minDiff = 1
self.shortSymbol = 'btc'
self.vtSymbol = 'btc'
self.TMinuteInterval = 1
def addBar(self,bar,bar_is_completed, bar_freq):
print(u'tradingDay:{},dt:{},{} o:{},h:{},l:{},c:{},v:{}'.format(bar.tradingDay, bar.datetime,bar.vtSymbol, bar.open, bar.high,
bar.low, bar.close, bar.volume))
def onBar(self, bar):
print(u'tradingDay:{},dt:{},{} o:{},h:{},l:{},c:{},v:{}'.format(bar.tradingDay,bar.datetime,bar.vtSymbol, bar.open, bar.high, bar.low, bar.close, bar.volume))
def writeCtaLog(self, content):
print(content)
def writeCtaError(self, content):
print(content)
if __name__ == '__main__':
t = TestStrategy()
# 这里要用生产系统的API不要用testnet的API, 生产和testnet的行情不一样的。
API_KEY = 'xx'
API_SECRET = 'xxx-xxx-xx'
bitmex_data = BitmexData(t,API_KEY,API_SECRET)
#bitmex_data.get_bars(symbol='XBTUSD',period='1hour',callback=t.addBar,bar_is_completed=True,bar_freq=60)
bitmex_data.get_bars(symbol='XBTUSD',period='5min',callback=t.addBar,bar_is_completed=True,bar_freq=60)