BitMexのWebSocketでBOT作成(1)
導入
こんにちは、NewTypeGorillaです。
なんで、こんな名前なのかというと、ゴリラだからです。
僕はどちらかというと、
・コードが書けるプログラマー
・FXや仮想通貨の知識は初心者レベル
という、典型的な「プログラマーからトレード市場に殴り込み」パターンです。
仕事上でBOTを作ることは多々ありますが、FXや仮想通貨のBOTは全く作ったことがありません。
そこで、トレードの世界でどこまで戦えるのかを書き記しておこうと思います。
なぜWebSocketを使うのか
今回はBitMexのWebSocketを使いたいと思います。
なぜREST APIではなくWebSocketなのかは、もうWeb上、note上に腐るほど出てるので今さら書く必要はあまりないかもしれませんが、一応書きます。
REST APIは、単なるリクエストとレスポンスです。
電話を思い浮かべていただくとわかりやすいかもしれません。
-- 電話ガチャ
A:「こんにちは。◯◯の情報をください(リクエスト)。」
B:「こんにちは。わかりました。はいこれです(レスポンス)。またね」
-- 電話ガチャ
これが一連の流れなのですが、これがもの凄い短時間に何回も続いたら、怒りますよね?
-- 電話ガチャ
A:「こんにちは。◯◯の情報をください。」
B:「こんにちは。わかりました。はいこれです。またね」
-- 電話ガチャ
-- 電話ガチャ
A:「こんにちは。◯◯の情報をください。」
B:「こんにちは。わかりました。はいこれです。またね」
-- 電話ガチャ
-- 電話ガチャ
A:「こんにちは。◯◯の情報をくだ...」
B:「いい加減うるせーな。こっちにも負担かかってんだぞ」
実際、BitMex側でもこのリクエスト数には制限を設けています。
REST API へのリクエストのレートは、1 分間あたり 60 リクエストに制限されています。 このカウンタは間断なく補充されます。 ログインしていない場合、レート制限は 1 分あたり 30 です。
そこで使うのが、WebSocketです。
WebSocketは、先ほどの電話を例にすると、電話をずーっと繋ぎっぱなししている状態を言います。
-- 電話ガチャ
A:「こんにちは。◯◯の情報をください。」
B:「こんにちは。わかりました。はいこれです。...」
....
A:「◯◯の情報をください。」
B:「はいこれです。」
....
A:「◯◯の情報をください。」
B:「はいこれです。」
....
これであれば、相手に負担もかからないですし、何より高速に返事が返ってきますよね。
実際にWebSocketで使ってみる
今回はPythonで実装します。
pipを使わずにベタに書いてWebSocketを実装する方法もあります(どこかに転がってる公式のサンプルソースコードをご覧ください)が、とてもとても面倒ですので、今回はpipを使います。
pip install bitmex-ws
次に、必要なものをもろもろ読み込みます。
from bitmex_websocket import BitMEXWebsocket
import logging
from time import sleep
出力するログを作るための関数を作成します。
今回は出力レベルをDEBUGに設定していますが、そこまで情報が必要ないのであれば、INFOなどでも大丈夫です。
def setup_logger():
# コンソールハンドラを作成し、レベルをdebugに設定。
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
# フォーマット作成
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
あとはメインの関数を作ります。
まずは、さきほど作ったログの関数を実行します。
次に、WebSocketに接続するためのオブジェクトをBitMEXWebsocketから作り出します。
今回はパーソナルな情報は取得しないで、一般的な情報のみなので、api_keyとapi_secretに関してはNoneにしています。
def run():
logger = setup_logger()
ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=None, api_secret=None)
準備は整ったので、半永久的に情報を取得するようにループさせます。
生成したwsオブジェクトに対して、「get_ticker」関数を叩いてやれば、Ticker情報が確認できます。
# 止めるまで半永久
while ws.ws.sock.connected:
logger.info("Ticker: {}".format(ws.get_ticker()))
最終的には、以下のようなコードになります。
from bitmex_websocket import BitMEXWebsocket
import logging
from time import sleep
# メイン
def run():
logger = setup_logger()
ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=None, api_secret=None)
# 止めるまで半永久
while ws.ws.sock.connected:
logger.info("Ticker: {}".format(ws.get_ticker()))
def setup_logger():
# コンソールハンドラを作成し、レベルをdebugに設定。
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
# フォーマット作成
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
logger.addHandler(ch)
return logger
if __name__ == "__main__":
run()
これを実行してみると、
いい感じでTicker情報を取得できました。
ちなみに中身はどんな情報かというと、
{'last': 7178.0, 'buy': 7178.0, 'sell': 7178.0, 'mid': 7178.0}
'last':最終価格
'buy':Bid価格
'sell':Ask価格
'mid':BidとAskの平均値
になります。