見出し画像

bitmexの足データをDBに保存するモジュール

このへっぽこレベルで需要あるのか不明ですが、同等のものが自分では見つけられなかったので公開してみます。本体はnodejsですが、データはDBに入れているので大抵の言語はつかえるはずです。自分はnodejsとpython3.5(たまに)で使っています。python3.5での使用例も記載しておきます。

github bitmex_market

※データなどを確認してから使ってください。何が起きても責任は負えません。バグはできる限り直すので教えてください。

機能

・h2足などAPIでサポートされてない足は計算します。
・確定された足のみ取得できます。
・socketからの情報を主に使い、現在時刻から足りてないデータがある場合や抜けが出ている場合rest apiから補完します。
・mongodbに足データを保存しプッシュ通信はredisのpubsubを使います。
・key, secretは今のところ使用できません。
・指定日時からヒストリカルデータを取得し保存します。
・bitmexからの情報取得とDBからの情報取得は個別にも同時にも実装できます。
・ブチブチ切れるsocketは永遠reconnectします。

リアルタイムtickはまだ実装していません。

事前にインストールが必要なもの

mongodb 
データ保存用 ユーザーは作っておいてください。
以下で統一して書いています。
user : test_user
password : test_password
db : test_db

redis 
pubsub用 push通信がいらないならいりません。認証付きで記載しています。
password : test_redis_password
で統一して書いてます。

node.js   
LTS : long term supportバージョンを通常使います

インストール

npm install sakiyamajp/bitmex_market#master

なんか恐れ多くてnpmにはだしてません :(

nodejs データ収集

import Markets from 'bitmex_market';
(async () => {
	let markets = await Markets({
		// bitmexからデータを取得するかどうか
		// default : false,
		subscribe : true,
		// mongodbにつなぐ文字列
		mongo : 'mongodb://test_user:test_password@127.0.0.1:27017/test_db',
		// redisの接続設定
		redis : {
			host : '127.0.0.1',
			port : 6379,
			password : 'test_redis_password'
		},
		// 取得するマーケット
	        // 数が多いとAPIのリクエスト数制限により起動が遅くなります。
		// default : ['XBTUSD']
		markets : [
			'BCHM18',
			'XBTUSD',
			'ETHM18',
			'LTCM18',
			'ADAM18',
			'XRPM18'
		],
		// 追加で計算してほしい足
		// apiはm1,m5,h1,d1しかないのでそれ以外を書きます。
		// 上記の足から計算できるものである必要があります。
		// default : {},
		timeframes : {
			"m2" : 2 * 60 * 1000,// { name : ms }
			"m15" : 15 * 60 * 1000,// { name : ms }
			'm30' : 30 * 60 * 1000,// { name : ms }
			'h2' : 2 * 60 * 60 * 1000,// { name : ms }
			'h4' : 4 * 60 * 60 * 1000,// { name : ms }
			'h8' : 8 * 60 * 60 * 1000,// { name : ms }
			'h12' : 12 * 60 * 60 * 1000,// { name : ms }
		},
		// ヒストリカルデータの取得開始日時
		// Z は UTCのマークです。
		history : '2018-04-01T00:00:00.000Z',
	        // DBをチェックする間隔 リクエストはデータが欠けているときしか
	        // 送りません。
	//	polling : 20000 // ms default 20000,
	        // ログをだすかどうか。
	//	verbose : true // default true
	});
})();

最初にヒストリカルデータを落とすので、起動に時間かかります。

このまま使うこともできます。asyncの中で使ってください。

// リアルタイムに XRPM18 一分足をもらう場合
markets.XRPM18.m1.on((candle,market,timeframe) => {
	console.log(candle,market,timeframe);   
        /* こんな感じ
		{ time: '2018-06-04T07:57:00.000Z',
		  volume: 25632,
		  close: 0.0000891,
		  low: 0.00008905,
		  high: 0.00008912,
		  open: 0.00008913 } 'XRPM18' 'm1'
        */
});

// リアルタイムに XBTUSD 日足をもらう場合
markets.XBTUSD.d1.on((candle,market,timeframe) => {
	console.log(candle,market,timeframe);
})

// 最新の1分足3本分がほしい場合
let candles = await markets.XRPM18.m1.load(3);
console.log(candles)

/*
[ { time: 2018-06-04T07:55:00.000Z,
    volume: 0,
    close: 0.00008913,
    low: 0.00008913,
    high: 0.00008913,
    open: 0.00008913 },
  { time: 2018-06-04T07:56:00.000Z,
    volume: 0,
    close: 0.00008913,
    low: 0.00008913,
    high: 0.00008913,
    open: 0.00008913 },
  { time: 2018-06-04T07:57:00.000Z,
    volume: 25632,
    close: 0.0000891,
    low: 0.00008905,
    high: 0.00008912,
    open: 0.00008913 } ]
*/

// 2018/5/1/までの日足2本分がほしい場合
candles = await markets.XBTUSD.d1.load(2,new Date('2018/05/01Z'));
console.log(candles)

/*
[ { time: 2018-04-30T00:00:00.000Z,
    volume: 2370798272,
    close: 9250,
    low: 9123,
    high: 9457,
    open: 9400.5 },
  { time: 2018-05-01T00:00:00.000Z,
    volume: 2581286454,
    close: 9066,
    low: 8800.5,
    high: 9253.5,
    open: 9250 } ]
*/

nodejs DBからのみ情報取得する場合

import Markets from 'bitmex_market';
(async () => {
	let markets = await Markets({
		mongo : "mongodb://test_user:test_password@127.0.0.1:27017/test_db",
		redis : {
			host : "127.0.0.1",
			port : 6379,
			password : "test_redis_password"
		},
	});
})();

後は使い方同じです。
markets.XRPM18.m1などはmongoose modelです。

markets.XRPM18.m1.count({},(err,count) => {
    console.log(count);
});

などすべての基本的な操作がやりたければできます。

python3.5 mongodbから情報取得する場合

nodejsと同じぐらいのラッパー作りたかったのですが、まだすっごい簡易的です。

githubから丸ごとダウンロードして

from bitmex_market.Markets import Markets

するだけです。

from bitmex_market.Markets import Markets

markets = Markets(mongo = "mongodb://test_user:test_password@127.0.0.1:27017/test_db")

# 最新の XBTUSD の1分足が3本ほしい場合
cursor = markets.XBTUSD.m1.load(3)
list(cursor)
```
[{'close': 7692,
  'high': 7692,
  'low': 7691,
  'open': 7691.5,
  'time': datetime.datetime(2018, 6, 4, 4, 27),
  'volume': 423231},
 {'close': 7691.5,
  'high': 7693.5,
  'low': 7691,
  'open': 7693.5,
  'time': datetime.datetime(2018, 6, 4, 4, 26),
  'volume': 1055994},
 {'close': 7693.5,
  'high': 7694,
  'low': 7693.5,
  'open': 7693.5,
  'time': datetime.datetime(2018, 6, 4, 4, 25),
  'volume': 390303}]
```
# 2018/4/30までの XBTUSD の1分足が3本ほしい場合
cursor = markets.XBTUSD.m1.load(3,datetime.datetime(2018,4,30,0,0))
list(cursor)
```
[{'close': 9409.5,
  'high': 9410,
  'low': 9400.5,
  'open': 9400.5,
  'time': datetime.datetime(2018, 4, 30, 0, 0),
  'volume': 1442437},
 {'close': 9400.5,
  'high': 9400.5,
  'low': 9392,
  'open': 9392,
  'time': datetime.datetime(2018, 4, 29, 23, 59),
  'volume': 720995},
 {'close': 9392,
  'high': 9404.5,
  'low': 9392,
  'open': 9404.5,
  'time': datetime.datetime(2018, 4, 29, 23, 58),
  'volume': 1317493}]
```

cursorはpymongoのcursorです。

python3.5 redisからリアルタイムに情報取得する場合 (redis直見です)

import redis
import json

client = redis.StrictRedis(host='localhost', port=6379, password='test_redis_password')
pubsub = client.pubsub()
channel = b'XBTUSD_m1'
pubsub.subscribe(channel)

for item in pubsub.listen():
    if item['channel'] == channel and item['type'] == 'message' :
        data = item.get('data')
        data = data.decode('utf-8')
        data = json.loads(data)
        print(data)

# {'high': 7545, 'open': 7544.5, 'time': '2018-05-31T10:26:00.000Z', 'low': 7544, 'close': 7544.5, 'volume': 222789}
# {'high': 7545, 'open': 7544.5, 'time': '2018-05-31T10:27:00.000Z', 'low': 7543, 'close': 7543, 'volume': 861217}
# {'high': 7542.5, 'open': 7543, 'time': '2018-05-31T10:28:00.000Z', 'low': 7542, 'close': 7542, 'volume': 306987}
# {'high': 7543.5, 'open': 7542, 'time': '2018-05-31T10:29:00.000Z', 'low': 7542, 'close': 7543.5, 'volume': 395195}
# {'high': 7543.5, 'open': 7543.5, 'time': '2018-05-31T10:30:00.000Z', 'low': 7543, 'close': 7543.5, 'volume': 377342}

だいたいこんな感じです。僕にはそこそこ複雑なシステマチックなものやリアルタイムのイベントドリブンな処理はpythonではやりにくいです orz

おまけでpythonでbitmex 1時間足の相関をみておく。

jupyter notebook使ってます。

import datetime
import pandas as pd
from bitmex_market.Markets import Markets

markets = Markets(mongo = "mongodb://test_user:test_password@127.0.0.1:27017/test_db")

market_names = markets.__dict__.keys()

all = pd.DataFrame()
for name in market_names:
    market = getattr(markets,name)
    cursor = market.h1.load(720,datetime.datetime(2018,5,1,0,0))
    df = pd.DataFrame(list(cursor))
    all[name] = df.close;
    all["time"] = df.time
all.set_index('time',inplace = True)
corr = all.corr()
corr

import seaborn as sns
sns.heatmap(corr, 
        xticklabels=corr.columns,
        yticklabels=corr.columns)

おやあ LTCだけ別物なの?

さいご

自分は上記のものを使ってデータ収集のみをサーバー1か所で行い、botやbacktestはすべてDBから参照しています。APIのリクエスト制限がちょっと楽になりました。もちろん手元の1台のwindowsでも動きます。


この記事が気に入ったらサポートをしてみませんか?