新興仮想通貨取引所BaseFEXのwebsocketあれこれ
bot戦士の皆さんこんにちは、JAVELER(@javeleeer)です。
暗号通貨bot界隈がbitflyer社レバレッジAPI制限とスナフキンさん(@snufkin0866)主催のliquidbot大会の話題で持ちきりの中、僕はというとBaseFEXという海外の新興取引所のbot開発に没頭()しておりました。
まだ開設間もない取引所ということもあり、いわゆるAPIで自動売買してみた系の記事は日本語はおろか英文でもほとんどヒットせず、REST APIラッパーも落ちておらずで結構面倒でした。
国内でもヨーロピアンさん初め界隈のインフルエンサーがBaseFEXを推し始めていることもあり、将来的にbitmexのようなスケールをしてくれたらいいなあと淡い期待を抱いております。
取引所の概要や手数料体系などについては丁寧にまとめられているアフィ記事がたくさんありますので、本記事では割愛します。
もはやどこに需要があるのか分かりませんが、今回はBaseFEXのwebsocketを調査した結果を備忘録がてら共有しておきます。
公式ドキュメント
channnel
wss://ws.basefex.com/depth@BTCUSD # 板情報
wss://ws.basefex.com/trades@BTCUSD # 約定履歴
wss://ws.basefex.com/candlesticks/1MIN@BTCUSD # OHLCV
BTCUSD以外の通貨ペアでの接続はテストしていないので受信できるか分かりません。
websocket接続
公式ドキュメントにasyncioで非同期接続するpythonサンプルコードの記載があります。モジュールのインポートとコピペで繋がります。
因みに、bitflyerに飼い慣らされたbotterにはお馴染みのwebsocket_clientでも接続できます。
以下のコードで接続を確認済みです。
※channel指定はできないようです。
import json import websocket from time import sleep from logging import getLogger,INFO,StreamHandler logger = getLogger(__name__) handler = StreamHandler() handler.setLevel(INFO) logger.setLevel(INFO) logger.addHandler(handler) class RealtimeAPI(object): def __init__(self, url): self.url = url #Define Websocket self.ws = websocket.WebSocketApp(self.url,header=None,on_open=self.on_open, on_message=self.on_message, on_error=self.on_error, on_close=self.on_close) websocket.enableTrace(True) def run(self): #ws has loop. To break this press ctrl + c to occur Keyboard Interruption Exception. self.ws.run_forever() logger.info('Web Socket process ended.') # when we get message def on_message(self, ws, message): output = json.loads(message) logger.info(output) # when error occurs def on_error(self, ws, error): logger.error(error) # when websocket closed. def on_close(self, ws): logger.info('disconnected streaming server') # when websocket opened. def on_open(self, ws): logger.info('connected streaming server') output_json = json.dumps( {'method' : 'subscribe'} ) ws.send(output_json) if __name__ == '__main__': url = 'wss://ws.basefex.com/depth@BTCUSD' #url = 'wss://ws.basefex.com/trades@BTCUSD' basefex_ws = RealtimeAPI(url=url) basefex_ws.run()
/depth@BTCUSD #板情報
# 差分message { "bids":{ "5307":12305 }, "lastPrice":5315.5, "from":20139013, "bestPrices":{ "ask":5315.5, "bid":5315 }, "asks":{}, "to":20139013 }
- snapshotと差分の混在
- snapshotは初回受信時、それ以降はランダム間隔で配信。
- dict配列は価格順にソートされてない
- 差分配信は1メッセージにつき板1件の更新
- 消えた板はsizeが0 ( 'bids'{'5445.5':0} )
- lastPrice,bestPriceは必ず付いてくる
- from to 時刻フォーマットが謎
snapshot配信頻度
画像はsnapshotを受信したtimestampをターミナル上で表示したものです。
初回の受信から13分、その後22分間隔が空いたりと、長時間snapshot配信が途絶える可能性を考慮しておく必要があります。
snapshot配列
bid/ask同数ではなく中央値からn件。
4/20のアップデート以降、snapshotの件数が若干増えたようで最大100件前後送られてくることもあります。(アップデート以前は確認した限り86件か88件に固定されていました)
呼値0.5ドル刻みの板で最小上下40ドル幅程の板情報しか送られてこないという訳です。
REST APIにも板情報を取得するエンドポイントは存在しない為、他取引所の様に全板情報を手元で再現する事はできません。
それから、from/toの時刻フォーマットが謎です。
下一桁ms、下二桁sec形式で加算されているようですが起点が不明な為、遅延の計測ができません。
ドキュメントのサンプルには"from":547055とあるのでサービスリリース時点から加算しているのかもしれません(最新のfromを日数に換算すると24日に相当するのでそれっぽい) 。
/trades@BTCUSD # 約定履歴
# trades message
[ { 'id': '5a8f9ea4-b1c0-0000-0001-0000013343bf', 'symbol': 'BTCUSD', 'price': 5315, 'size': 3993, 'matchedAt': 1555826381511, 'side': 'BUY' }
]
- 初回受信時に直近300件の約定情報がまとめて配信される
- 以降、基本約定1件につき1メッセージ(たまに2〜3件まとめて配信される)
配信遅延
約定配信はtimestampがunixtimeなので遅延の計測が可能です。
計測期間 : 2019/04/21 18:43~20:14
約定件数 951件
最大遅延 4.689 sec
最小遅延 0.011sec
平均遅延 0.547597 sec
ローカルPC時刻との差分のため、環境によって多少誤差はあると思います。
平常時は概ね0.5秒以内に配信されていて1秒を超えることは稀です。
途中2~5秒間の遅延は、bitflyer BTCFX/JPYの10分足で5000円幅変動したタイミングでした(indexでplotしていますが時系列順)。
10秒を超える遅延が数時間に渡って続くこともある国内取引所と比較すると早い方でしょうか。
但し、90分間で951件と約定件数が圧倒的に少ないため、今後ユーザーが増えると影響が出てくる可能性はあります。
/candlesticks/min@BTCUSD
時間足を指定してohlcvを取得。
自分は約定履歴から自炊してるので使う機会は無いですが1分、5分、15分で試したところ、問題無く取得できました。
まとめ
板情報はあまり使い物にならない、約定情報は結構信用できる。
で、儲かりそうなの?という話ですが、BitMEXよりは攻略難易度低そうだが国内取引所程は甘くないといった感じに捉えています。
出来高に対して約定件数が少なすぎるので色々と勘ぐってしまいますが、見かけ上の出来高では既に国内取引所Liquidの出来高を上回る日もありますし、たまにスプレッドも開きます(オーダー通るとは言ってない)。
昨日から少枚数でmmbotを放流しています、何かしら成果があれば経過をツイートしていこうと思います。
REST APIに関してもラッピングの過程でいくつか気付いたことがあるので、需要があれば記事にするかもしれません。
最後に、この記事が役に立ったと感じた方はチャンネル登録、あっ間違えたアフィリエイトリンク踏んで口座開設してくださいませ。
最後までお読みいただき、ありがとうございました。