BTCMEXが公式に用意しているPython用WebSocketコネクタがなんかおかしい?話
仮想通貨取引所であるBTCMEX*1用のbotを開発している際に使おうとしていた WebSocketコネクタが,なにかおかしい様なので記事にしてみました.
目次:
おかしい?こと
無限にwaiting
そのままコピペして公式コネクタを使おうとすると,182行目の __wait_for_symbol関数で待ったまま一生を過ごしてしまいます.
というのも, __wait_for_symbol関数は"instrument" , "trade", "quote"トピックのデータが来るまで待ち続けますが,そもそも"quote"トピックはサブスクライブされていないためデータが送られてくることはありません.
実際にトピックをサブスクライブする部分の処理を見ると, サブスクライブしているトピックは"instrument", "order", "ordeBookL2", "trade", "liquidation"のみで "quote"トピックはサブスクライブされてないことがわかります.
172行目を変更して"quote"を追加することで無限ループから開放されます.
KeyError: "instrument"
ときには KeyError: "quote"
として現れることもあります.
標準出力に出てくるのが鬱陶しいですが,出るのは最初の数回のみなので今回は無視することにします.
Partialが来る前にUpdateなどが来ることによって発生します.
open_orders関数が機能しない
そのままです. 機能してくれません.
新規orderに関するデータがupdateトピックを通して送られてきますが,当然同じorderIDを持つ注文に関するデータはないため,updateするものが見つからずバグってしまいます.
(245行目でreturn してしまう)
そこで,updateでデータが送られてきた場合にも,トピックが"order"の場合いい感じにデータを挿入するようにしてみます.
242行目から249行目を以下のように変更します
for updateData in message['data']: item = findItemByKeys(self.keys[table], self.data[table], updateData) if not item: if table == "order": self.data[table] += message["data"] # insert order data self.keys[table] = ["orderID"] # self.keys["order"] should be ["orderID"] return # No item found to update. Could happen before push item.update(updateData)
これによって,正しくorderの情報を更新/保持 するようになりました!
キャンセルされたOrderのデータも持っているのが気に食わない
これは宗教かもしれないですが,open_orders("null")を呼んでいるのにopenでないorderのデータが来るのはおかしい気がします.
254行目のremoveする条件が甘いです. サイズが0になる以外にも orderがRejectされたりCancelされる場合があるはずです.
254行目を
if table == 'order' and (not order_leaves_quantity(item) or not item["ordStatus"] in ("New", "PartiallyFilled")):
とすると,本当にOpenでないデータが帰ってくることはなくなります.
これで大部分の人の希望が叶ったのではないでしょうか?
おわりに
あとは各自自由に煮るなり焼くなり好きにしてください.
私の場合はopen_ordersのprefixがNoneの場合はopen_orderを全て返すように変更してみました
これで僕にとっての”いいかんじ”なwebsocketコネクタを作ることができました!
*1:巷ではパチMEXとも呼ばれている