
2-4."現在価格"の考察
本Noteでは、bitFlyer LightningでBTC-FX/JPYを対象にBotを稼動させている方向けにワイなりの「現在価格」とは一体何なんだろうか?という考察をご紹介します。
※例としてbitFlyerFXを使用しますが板取引が可能な取引所であれば考え方は展開できると思います。また、仮想通貨の取引を行っている方であればBotterでなくとも「アイツらこんなこと考えてんのか」と楽しんで頂けるのではないかと思います。
※2020/03/14時点の情報をもとに記載しています。
1.いまいくら?(3分)
それでは早速2020/03/14 17:44:26時点のBTC-FX/JPYが「いまいくら?」かを見てみましょう。お、さらっと2万幅のビットコしてますね。
この画面を見て、皆さんはBTC-FX/JPYは「いまいくら」だと思われるでしょうか。
回答① 581,020
回答② 580,871
回答③ 581,031
回答④ 580,886
回答⑤ 580,958
回答⑥ わからない。俺たちは雰囲気で仮想通貨を取引している。
「おいおい、いまいくらかの答えがなんでそんなにたくさんあるんだよ!」というツッコミや「なるほどその話ね」という声が聞こえてきますが、上記の何れの回答も正解だと思います。
それではもう少し詳しく見てみましょう。
この1画面の中に、現在価格といっても差し支えなさそうな値が①~⑤の5つありました。この5つはデータソースが異なります。
「いうても最小580,871で最大581,020、その差149円やん。」と思われるかもしれません。しかし、この差が明暗を分けるのです。
2.何故「いまいくら?」にこだわるのか(1分)
上記の「いまいくら?」の差149円。これが損益にどのような影響を与えるか、敢えて極端な例で示してみます。
取引のタイプに依りますが、1回のサイズが大きいほど、取引回数が多いほど、「いまいくら」の差が損益に与える影響が大きくなります。
有利な「いまいくら」を指値に使い続けた場合と、不利な「いまいくら」を指値を使い続けた場合の差は、スキャルピング・高頻度では日次・月次の明暗を分ける要因となります。
どうでしょう、「いまいくら」についてこだわりたくなってきませんか?
3.「いまいくら?」をどうやって知るのか(3分)
それでは次に「いまいくら?」をどうやって知るのかを考えてみましょう。
Botが「いまいくら?」かを知るためには、どこかからデータを取得する必要があります。
3-1.取引所から直接取得する
Botが直接取引所と通信してデータを取得するパターンです。単一取引所を対象とする場合はこれで十分です。
3-2.中継サービスから取得する
取引所からデータを収集している中継サービスからデータを取得するパターンです。単一取引所を対象とする場合はあまりメリットはありません。
しかし、下図のように複数の取引所を対象にする場合はどうでしょうか。
(1Botで複数取引所と通信する場合、弊Botはこの方式)
(取引所毎にBotを分けている場合)
このようにBotが直接各取引所と通信すると、各取引所毎に個別に処理を実装しなければならず、Wrapper Classでまとめるにしてもとても面倒くさいです。(通信方法、認証方法、データ構造、データ型等が異なる場合がある)
こういった場合に中継サービスを利用すると、Botから見た通信先は1か所になるので、データ取得処理の実装はある程度楽になります。
デメリットとしては以下の2点があげられます。
①中継サービスを経由する分、直接通信よりもデータ取得に時間を要する場合が多い。(経路によっては早くなる場合もある)
②中継サービスの負荷・稼動状況によってデータ取得が遅延、停止することがある。
次の2点は中継サービスの提供形態に依ります。
③中継サービスが各取引所への注文処理を提供していない場合は、直接各取引所と認証・通信しなければなりません。
④有償の場合があります。
良く知られている中継サービスとしては Cryptowatch があります。
3-3.その他
その他の方法は、公式に提供されていないものであったり、上記の方法に比べてデメリットの方が大きいものが多いと思います。本Noteでは触れません。
4.「いまいくら?」の種類(2分)
bitFlyer Lightning APIの場合、「いまくら?」を取得できるAPIは以下の3つがあります。
A.HTTP API の Public API
B.RealTime API (Socket.IO) Public Channels
C.RealTime API (JSON-RPC) Public Channels
この3つのAPIのそれぞれで実行できる操作・取得できる情報は下図の通りです。
この中で「いまいくら?」に関係するものをリストにしてみます。
①HTTP-APIか、RealTime APIか?
②RealTime APIであれば、Socket.IOか、JSON-RPCか?
③データの種類は板情報か、Tickerか、約定か?
が分かれ目です。
①HTTP-APIか、RealTime APIか?
HTTP-APIは、クライアントからのリクエストに対するレスポンスでデータを提供します。Botからサーバーに電話して「いまいくら?」って聞いたらサーバーが教えてくれて、1回聞いたら電話を切る感じです。
高頻度Botではデータを取得したい契機の都度リクエストを投げることは現実的ではなく、RealTime APIでデータが取得できない場合の補足手段として利用する程度だと思います。スイング、デイの注文頻度であればこちらでも問題はないと思います。
これに対しRealTime APIは、一度WebSocketの接続を確立すれば継続してデータが配信されます。Botからサーバーに電話して「いまいくらかが変わったら教えてね」と言っておけばあとは通話しっぱなしで、いまいくらかが変わる都度サーバーが教えてくれる感じです。
高頻度Botは後者を利用しているケースが多いと思います。
②RealTime APIであれば、Socket.IOか、JSON-RPCか?
どちらもWebSocketによるデータの双方向通信を実現する技術です。どちらが良い悪い、どちらが速い遅い等は、Botの実装や環境によって異なると思います。Twitterでのポロリや有料Noteを探すと「こっちの方が良いよ」という言及があるかもしれませんが、貴Botに合わせてどちらか又は両方を利用する等、試行錯誤して工夫するのが良いと思います。
③データの種類は板情報(差分)か、Tickerか、約定か?
この3種のうちどの値を利用するのが良いのかも、貴Botのストラテジーに依ると思います。
どの値が良い、悪いではなく、特徴について次の章で掘り下げてみたいと思います。
※bitFlyer Lightning のAPIは、公式のドキュメント、PlayGroundのサンプルコードが充実しています。ここまでの記載内容は全てそこで得られます。
5.それぞれの「いまいくら?」の特徴(10分)
この章では、「いまいくら?」の対象を板情報(差分)か、Tickerか、約定かに絞り込んで掘りさげます。
5-1.板情報(差分)
板情報の差分に含まれるデータは、mid_priceと、price・sizeで構成するbidとaskのリストです。bitFlyerのAPI仕様を確認してみましょう。
{
"mid_price": 35625,
"bids": [
{
"price": 33350,
"size": 1
}
],
"asks": []
}
JSON形式のデータですが、普通の生活をしているとこんな形のデータを見かけることはありません。もう少し人が見てもわかりやすく表現してみます。
5-1-1.更新した価格の板情報のみ配信される
この板情報の差分は、更新が発生した価格の板情報のみが配信されます。全板情報は板のスナップショットを取得するか、自Bot内で管理する板情報に差分を反映して自作しなければなりません。
5-1-2.個々の注文・キャンセルではなく現在のサイズが配信される
また、更新が発生した価格の板情報は、「サイズの増減」ではなく「現在のサイズ」が配信されます。「どの価格の板がどれだけ増減したか」ではなく「どの価格の板のサイズが現在どれだけになったか」です。つまり個々の指値注文とそのキャンセルはわかりません。
5-1-3.注文とその取消による更新と成行に板が食われた場合の更新がある
板の更新には、新規注文とその取消による更新と、成行によって板が食われた場合の更新があります。
5-1-4.時刻情報は含まれない
さらに板情報の差分には、時刻情報が含まれていません。このデータを受け取った時点では、どの時点の板情報の差分であるかはわかりません。
よって冒頭の2020/03/14 17:44:26時点のmid_priceを正確に知ることはできませんが、自Botが板情報の差分を受信した時刻がそれに近いと思われます。実際にログを見てみましょう。
2020/03/14 17:44:26.920に受信したmid_priceと、WEB画面で表示されているmid_priceが整数部分で一致していました。
「おいおい板情報の差分配信されすぎワロタ」と思われる方もいらっしゃると思います。実際板差分がどれくらい配信されているかを調べてみました。
2020/03/13 11:30~50(上げCBが発生した時間帯)
2020/03/15 06:00~20(特に大きな値動きがない場合)
大まかに配信数のトレンドがわかります。「ヨコヨコ時はこれくらい、鉄火場ではこれくらい、遅延発生時はこれくらい。」「1回の配信に含まれる板のリストの数はこれくらい」等と掘り下げて調べると、
・bitFlyerのServerServiceの仕様や制限値
・板差分を更新しているBotの生息数
等がわかるかもしれません。
また、一回の配信に含まれる更新された板のリストの価格幅とサイズを掘り下げて調べると
・生息しているBotがどの範囲にどういったサイズの注文を出しているか
がわかるかもしれません。
ちょっとワロタ板差分の配信があったので載せておきます。
2020/03/13の上げCBから取引が再開した直後の11:41:58の1秒間の配信です(再開は11:41:21付近)。これはあくまでmid_priceなので、実際の板がどのようになっていたかを追いかければ、鉄火場でトレード損益を獲得するBotのロジックが組めるかもしれません。(実際はロジックを組めても遅延との闘いに勝たねばならずそう簡単ではありません)
5-2.Ticker
Tickerとは「TickerTapeの略称で市場からの情報を受信・表示し続ける仕組み」とワイは理解しています。(Tickerとは?をwikiの記事やYoutubeで見るのも一興です)
Botから見ると「指定したシンボルの取引所での状態が一定間隔で配信されるもの」で、bitFlyerの場合は時刻、LTP(LastTradePrice)、BestBid・BestAskのPriceとSize、買板・売の合計Size、24時間の取引量等で構成されています。
{
"product_code": "BTC_JPY",
"timestamp": "2019-04-11T05:14:12.3739915Z",
"tick_id": 25965446,
"best_bid": 580006,
"best_ask": 580771,
"best_bid_size": 2.00000013,
"best_ask_size": 0.4,
"total_bid_depth": 1581.64414981,
"total_ask_depth": 1415.32079982,
"ltp": 580790,
"volume": 6703.96837634,
"volume_by_product": 6703.96837634
}
TickerのJSONデータ例です。これはわかりやすいデータ構造だと思います。
5-2-1.時刻情報が含まれる
TimeStampとBotが稼動する環境の時間差から、Ticker配信のレイテンシー(遅延)を計測することができます。
※正確なレイテンシーを計測するためにも、Botが稼動する環境の時刻を同期しておくことをお奨めします。(遅延に応じてどういった対処を採るべきかは本Noteでは触れません。)
5-2-2.配信頻度に制限がある
以下はAPIマニュアル→RealTimeAPI→Ticker部分の記載内容です。
価格が変動する都度LastTradePriceが配信されるわけではなく、配信頻度は制限されており、さらに頻度が不定期に変わることを確認しています。
5-2-3.LastTradePriceだけでなくBestAsk/Bidも含まれる
MMロジックやSFDロジックでは欠かせないBestAsk、BestBidが含まれます。
※但しTickerを受信した後、買い成行が入ればBestAskで約定し、売り成行が入ればBestBidで約定するのかというとそうではありません。(後述の処理所要時間参照)
では板差分と同様に配信頻度を確認してみましょう。
2020/03/13 11:30~50(上げCBが発生した時間帯)
2020/03/15 06:00~20(特に大きな値動きがない場合)
平時に比べて戦時のTicker配信数が倍増しています。
これではTicker「だけ」を利用している場合、Bot側では制御できないTicker配信の頻度によって、平時の処理時間に500msecの遅れが発生するようなもので、ロジックによっては戦えたものではありません。
Botの調子が良くなったり悪くなったりするが原因がわからない、という方はTicker配信頻度との相性を確認してみるのもアリだと思います。
5-3.約定
約定は、発生した約定のリストが配信されます。
[
{
"id": 39361,
"side": "SELL",
"price": 35100,
"size": 0.01,
"exec_date": "2015-07-07T10:44:33.547Z",
"buy_child_order_acceptance_id": "JRF20150707-014356-184990",
"sell_child_order_acceptance_id": "JRF20150707-104433-186048"
}
]
上記は約定履歴のJSONデータ例です。約定の「リスト」で配信されます。各項目の意味と、「リスト」のイメージは下図の通りです。
5-3-1.時刻情報が含まれる
Tickerと同じようにexec_dateとBotが稼動する環境の時間差から、約定配信のレイテンシー(遅延)を計測することができます。(一口に「遅延」といっても、Tickerの遅延、約定の遅延があり、他にも板乗りの遅延、キャンセルの遅延等、様々な遅延があります)
5-3-2.配信は「約定があったとき」
以下はAPIマニュアル→RealTimeAPI→約定部分の記載内容です。
「約定があったとき」といっても、約定1件毎に配信されるわけではなく、ある程度まとめて配信されます。
順を追って約定履歴がどのように配信されているかを確認してみましょう。
2020/03/13 11:30~50(上げCBが発生した時間帯)
戦時は秒間4~6回程度配信されています。また、約定が無ければ配信されないので、板差分・Tickerは配信されているのに約定は配信されない時間帯が存在します。
2020/03/15 06:00~20(特に大きな値動きがない場合)
平時でも秒間2-6回程度配信されています。
次に、1回の配信に含まれる約定の件数を確認してみます。
1回の配信に含まれる約定の件数は、いまのところ1件から24件の範囲に収まっているようです。
6.「いまいくら?」をより速く!(1分)
では「いまいくら」をより速く知るためにはどうしたらいいのでしょうか。
取引所で何らかの処理が発生し、データが配信され、Botが受信し、それを元に何らかのアクションを取引所に返すまでの所要時間を分解してみます。
このうち、①②はBot側では制御することはできませんので、その状態を知り、状態に応じた対応を採るしかありません。
③⑤は、Botが動作する環境に依存します。単一取引所を対象とし、その取引所から配信されるデータだけを利用している場合は、対象の取引所と最も速く通信できるVPSを採用する他、強Botterは様々な工夫を凝らしているようです。
単一の取引所との通信が速くても、複数取引所のデータを参照している場合は、ある特定の取引所との通信の影響がBot全体に及んでしまう可能性もあります。
④はロジックとコーディングの腕の見せ所です。
「このVPSが正解!」とか「このAPIのこのデータが正解!」というものは無く、それぞれのBotのそれぞれのLogicに合わせて工夫を凝らすしかないと思います。
(どの部分でどれくらい時間を要するのが一般的か、どういった方法でどれくらい改善の余地があるのかは本Noteの考察対象を外れるので触れません。)
7.結局「いまいくら」やねん!(2分)
散々回りくどく考察してきましたが、結局あるタイミングで「いまいくら」かは、ワイは正直わかりません。
「いまいくら」かの答えは取引所の処理中にあり、それを貴Botや弊Botが受け取った時点では既に過去の情報であり、受け取るタイミングもそれぞれ異なります。
そしてこの「いまいくら」かという情報は取引所×取引ペアの数だけあり、それぞれが複雑に絡みあっています。
こうなるともう「いまいくら」とは一体なんなのかわからなくなってきます。そう、俺たちは雰囲気で仮想通貨を取引しているのです。
ここまで読んで頂いてこれでは申し訳ないので、データを見ていく中でこんな性質があるっぽいことがわかったよ、ということを少し記しておきます。
7-1.板差分、Ticker、約定を時系列で並べてみる
前述のワロタ板差分の1.5秒に配信された板差分、Ticker、約定を時系列で並べてみると、
・板差分の中央値は注文の受付と約定処理によって頻繁に変化し、最も配信頻度が高い
・TickerのLPTはある時点の約定の最終価格で配信される
・約定はTickerよりも配信頻度が高いがBestAsk/BestBidは無いため、約定を元に指値を決めると思わぬスプレッドで不利なポジションを持ってしまう可能性がある
というようなことが見えてくると思います。それぞれ一長一短があります。
7-2.1回の約定の中に含まれるデータを調べてみる
また、約定は1回の配信の中に複数のデータが含まれます。具体例を挙げると、上図の最後の約定の配信には以下の11件が含まれています。
この配信では、テイカーのsideがSELLであり、売りの成行注文による約定であることがわかります。また、sell_child_order_acceptance_idが同一であることから、1件の売り成り行きに対して、11件の板が食われたという事がわかります。同一のsell_child_order_acceptance_idのsizeを合計すると10BTCとなり、3/13の上げCBの取引再開後に、Slipage409円で10玉投げ売りしてゴチしたんだな裏山などということがわかります。
上記の11件を見ると「1回の約定の配信に含まれるデータは、1つのテイカー注文に対応するものなのか?」という疑問が沸きます。
「11件の配信」の前の「3件の配信」を確認したところ、1つのテイカー注文に対応する範囲ではありませんでした。
いまのところ、約定の配信がどの単位で行われるかの答えには辿り着いていません。
約定は複数件のデータがまとまって配信されますが、最終取引価格は最後の1件なので、途中のデータの価格で都度処理を行ったりなんらかのアクションを起こすと、最後のデータの価格ではそうじゃなかった!みたいになっちゃうかもしれません。
また、ある1つのデータを「いまいくら」の解として採用するのではなく、一定期間の出来高に応じた加重平均価格(VWAP)や、時間加重型平均価格(TWAP)の考え方を用いてみたり、ロジックに合わせて前回のNoteで記載した以下の値を用いてみるのもありかもしれません。
・終値(close):ある期間の終値
・始値(open):ある期間の始値
・高値(high):ある期間の高値
・安値(low) :ある期間の安値
・高値安値平均(hl2):(高値+安値)/ 2
・高値安値終値平均(hlc3):(高値+安値+終値)/ 3
・始値高値安値終値平均(ohlc4):(始値+高値+安値+終値)/ 4
8.俺たちはどうしたらいいのか(1分)
このように板差分、Ticker、約定を見ていると、物質の基本的単位は粒子ではなく弦であるという超弦理論と「いまいくら」に通じるものがあるような気さえしてきます。
「いまいくら」の他でもBotを開発していく上でぶつかる問題には、これが正解という王道はなく、取り巻く環境もめまぐるしく移り変わります。
もし貴方が「Botで楽して稼ぎたい」のであれば「Botはやめた方が良い」ということを申し上げておきます。
「退場」するか「卒業」するか、「日々情報を収集し、データを取り、解析し、改善し、革新し、検証し、諦めずに、開発を続ける」しかないのです。
ワイは養分Botterなりに、
・今日の弊Botは期待値を上げたか?
・今日の弊Botは試行回数を確保したか?
・今日の弊Botは新しいチャレンジをしたか?
・今日のワイは諦めなかったか?
を自問し精進していきたいと思います。
(そんなシリアスに考えなくても、ワイは気楽に趣味でやってるだけやで、ってのもアリだと思います!)