bitflyerの完全なティックデータを取得する


はじめに

久しぶりにbitflyer lightningにログインした。
仮想通貨は大盛りあがりを見せたあの”2017年”以降、保持し続けているのだが、トレードはしていない。
lightnigの最終取引額の目まぐるしい変化を見て、"可能性"を感じてしまい、久しぶりにトレードをしたくなった。

再開

以前は裁量取引をしていたが、2度とやろうとは思わない。その精神的な負荷に耐えられるメンタルを持たないためだ。
従って自動売買システムを構築する必要がある。
そこでまず必要になるのはトレードロジックの判断基準となるデータである。

API

APIとは簡単に述べると、URLを叩くと特定のデータ(最新のBTCの値など)にアクセスできる、特定の命令(BTCの買い注文など)を実行できるインターフェースである。大体の仮想通貨取引所にはこのAPIが用意されている。
当然bitflyer lightningにも用意されている。
https://lightning.bitflyer.com/docs?lang=ja

ドキュメントによると"FX_BTC_JPY"の最新の値を取得するには以下を実行することである。
https://api.bitflyer.com//v1/getticker?product_code=FX_BTC_JPY
※上記をクリックすることで最新"FX_BTC_JPY"の値を取得できる。

実行制限の壁

macから早速以下を実行した。

while true; do curl https://api.bitflyer.com//v1/getticker?product_code=FX_BTC_JPY | jq . ; done

以下のようにJSON形式で値が返ってくる。

{
  "product_code": "FX_BTC_JPY",
  "timestamp": "2020-01-09T11:40:18.027",
  "tick_id": 340221409,
  "best_bid": 873088,
  "best_ask": 873160,
  "best_bid_size": 0.01325506,
  "best_ask_size": 0.026,
  "total_bid_depth": 7516.42989333,
  "total_ask_depth": 6798.27220924,
  "ltp": 873160,
  "volume": 196692.50042163,
  "volume_by_product": 196682.81646233
}

しかし、しばらくするとエラー

{
  "status": -1,
  "error_message": "Over API limit per period, per IP address",
  "data": null
}

→ドキュメントを読むと同一IPからのAPI呼び出しは1分間辺りxxxまでというふうに制限がある。このためである。1回/sだとエラーにならなかった。

実行制限の壁の超え方(妄想)

AWSを利用してパブリックIPを変えながら、複数のLambdaからAPIを実行し、結果をSQS等で結合し、DynamoDBに格納する。格納する際に時間でソートする。構築するには手間とコストが掛かる。
→以下にあるように全くの見当違いだとわかる。

実行制限の壁の超え方(採用案)

連続的なティックデータを取得しようとして苦労したのだが、ドキュメントを見ると約定履歴を取得するAPIがある。約定履歴とはティックデータをもれなく含む集合である。これを使えば解決する!!!
早速実行してみた。

curl https://api.bitflyer.com/v1/getexecutionsproduct_code=FX_BTC_JPY&count=10

結果

[{"id":1510454721,"side":"BUY","price":904727.0,"size":0.02,"exec_date":"2020-01-11T00:29:56.813","buy_child_order_acceptance_id":"JRF20200111-002956-217585","sell_child_order_acceptance_id":"JRF20200111-002955-073037"},{"id":1510454720,"side":"BUY","price":904727.0,"size":0.01,"exec_date":"2020-01-11T00:29:56.797","buy_child_order_acceptance_id":"JRF20200111-002956-109098","sell_child_order_acceptance_id":"JRF20200111-002955-073037"},{"id":1510454719,"side":"BUY","price":904727.0,"size":0.01,"exec_date":"2020-01-11T00:29:56.797","buy_child_order_acceptance_id":"JRF20200111-002956-995485","sell_child_order_acceptance_id":"JRF20200111-002955-073037"},{"id":1510454718,"side":"BUY","price":904708.0,"size":0.62,"exec_date":"2020-01-11T00:29:56.797","buy_child_order_acceptance_id":"JRF20200111-002956-109097","sell_child_order_acceptance_id":"JRF20200111-002954-142777"},{"id":1510454717,"side":"BUY","price":904707.0,"size":0.383,"exec_date":"2020-01-11T00:29:56.797","buy_child_order_acceptance_id":"JRF20200111-002956-109097","sell_child_order_acceptance_id":"JRF20200111-002955-217572"},{"id":1510454716,"side":"BUY","price":904686.0,"size":0.091,"exec_date":"2020-01-11T00:29:56.797","buy_child_order_acceptance_id":"JRF20200111-002956-109097","sell_child_order_acceptance_id":"JRF20200111-002956-073060"},{"id":1510454715,"side":"BUY","price":904686.0,"size":0.01,"exec_date":"2020-01-11T00:29:56.783","buy_child_order_acceptance_id":"JRF20200111-002956-458844","sell_child_order_acceptance_id":"JRF20200111-002956-073060"},{"id":1510454714,"side":"BUY","price":904686.0,"size":0.01,"exec_date":"2020-01-11T00:29:56.607","buy_child_order_acceptance_id":"JRF20200111-002956-152005","sell_child_order_acceptance_id":"JRF20200111-002956-073060"},{"id":1510454713,"side":"BUY","price":904707.0,"size":0.01,"exec_date":"2020-01-11T00:29:56.577","buy_child_order_acceptance_id":"JRF20200111-002956-458842","sell_child_order_acceptance_id":"JRF20200111-002955-217572"},{"id":1510454712,"side":"BUY","price":904707.0,"size":0.04,"exec_date":"2020-01-11T00:29:56.547","buy_child_order_acceptance_id":"JRF20200111-002956-217578","sell_child_order_acceptance_id":"JRF20200111-002955-217572"}]

→countで件数を指定できる。今回は10件とした。最大500件のようだ。

pythonによる可視化

plottest.ipynb

import requests
import json 
import matplotlib.pyplot as plt
%matplotlib inline

response = requests.get("https://api.bitflyer.com/v1/getexecutions?product_code=FX_BTC_JPY&count=100")
res_json = json.loads(response.text)

res_price_list = []
for res in res_json :
    res_price_list.append(res['price'])

plt.plot(res_price_list)

→curlを使う代わりにrequestを使う。
→requestのレスポンスを.textでテキストのみ抽出し、json.loadでlist型に変換する。
→取得する約定回数は100回とした。

結果


貴方の環境(jupyter notebook)でも実行してみてほしい。
実行するたびに表示されるグラフは完全に変わるはずだ。これはbitflyer lightningでの取引が活発なおかげである。
複数回生成された多くのグラフにも共通したところがある。
それは過去100回程度の約定履歴の中では比較的顕著なトレンドは発生せず、むしろ反復運動のような動きをしていることである。
これをトレードロジックに組み込めないだろうかと思う。