BitMEXの秒足を約定履歴から30秒で自動生成するプログラム✨
BitMEXという荒野を駆け抜けるBotterの皆さんこんにちは.
そんなBotterの皆さんは日々バックテストを重ねて,新しい戦略を構築していることと思います.
mmbotなどのバックテストには高い解像度の情報が必要で,皆さんそのようなことに頭を悩ませているでしょう.
ほとんどの高頻度Botterは秒足などに対してバックテストをしていると思いますが,なにせ秒足を用意するのは意外と面倒くさいものです.
約定履歴を収集するプログラムを書いても,24時間稼働させなければいけないため,管理コストがかかります.
というわけで今回の記事では,BitMEXに公開されてる約定履歴から特定のシンボル(XBTUSDなど)の任意の秒足を作るプログラムを公開します.
今回使うデータ供給元
意外と知られていませんが,BitMEXは日々の約定履歴を集めたファイルをここで公開しています. ですが,このデータは様々なシンボルでの約定が一緒くたにされているために,特定のシンボルだけを抽出する加工が必要になります.
今回のプログラムではその作業も行います.
プログラム
import gzip import pandas as pd from urllib import request #参考: https://qiita.com/yuukiclass/items/88e9ac6c5a3b5ab56cc4 def main(): date, symbol, sec= input('yyyymmdd symbol sec\n').split() date, sec = int(date), int(sec) baseurl = 'https://s3-eu-west-1.amazonaws.com/public.bitmex.com/data/trade/' print('Downloading...') filepath = '{}.csv.gz'.format(date) request.urlretrieve(baseurl + '{}.csv.gz'.format(date), filepath) print('Making candles...') df = unzip(filepath) df_ohlcv = makeCandles(df, symbol, sec,date) print('Done!') file_title = 'ohlc_bitmex-{}.csv'.format(date) df_ohlcv.to_csv(file_title) return def makeCandles(df, symbol, sec, date): # 参考: https://note.com/nagi7692/n/ne674d117d1b6?magazine_key=m0b2a506bf904 df = df.query('symbol == "{}"'.format(symbol)) df.drop(['tickDirection', 'trdMatchID', 'grossValue', 'homeNotional', 'foreignNotional'], axis=1, inplace=True) #86400本の秒足ができるように0秒に約定を入れる year = str(date)[:4] month = str(date)[4:6] day = str(date)[6:] side = df.iloc[0]['side'] price = df.iloc[0]['price'] ser = pd.Series(['{}-{}-{}D00:00:00.000000000'.format(year,month,day), symbol, side, 0,price], index=df.columns, name=0) df = df.append(ser) df = df.sort_index() df['timestamp'] = pd.to_datetime(df['timestamp'], format="%Y-%m-%dD%H:%M:%S.%f") df = df.rename(columns={'timestamp': 'exec_date'}) df = df.set_index('exec_date') df['buy_size'] = df['size'].where(df['side'] == 'Buy', 0) df['buy_flag'] = df['side'] == 'Buy' df['sell_size'] = df['size'].where(df['side'] == 'Sell', 0) df['sell_flag'] = df['side'] == 'Sell' df_ohlcv = df.resample('{}S'.format(sec)).agg({"price": "ohlc", "size": "sum", "buy_size": "sum", "buy_flag": "sum", "sell_size": "sum", "sell_flag": "sum", }) df_ohlcv.columns = ['open', 'high', 'low', 'close', 'volume', 'buy_vol', 'buy_num', 'sell_vol', 'sell_num'] df_ohlcv['buy_num'] = df_ohlcv['buy_num'].astype(int) df_ohlcv['sell_num'] = df_ohlcv['sell_num'].astype(int) df_ohlcv.ffill(inplace=True) return df_ohlcv def unzip(filepath): with gzip.open(filepath, 'rt') as f: df = pd.read_csv(f) return df if __name__ == "__main__": main()
使い方
Pythonなどでプログラムを開くと
yyyymmdd symbol sec
と出るので
20200301 XBTUSD 1
とすることで,2020年3月1日のXBTUSDの1秒足が生成されます.
最後に
なにかプログラムのエラーやわからないこと等ありましたら気軽にコメントお願いします.