BTC-FX/JPY(BitFlyer)の全期間1時間足OHLCVをCryptCompareから収集する

Taiyoです。

システムトレードに取り組むにあたって、過去の取引データは重要です。
バックテストにはもちろん、アノマリーやアルファを探すのに、取引所のOHLCVは欠かせません。

今回はCryptCompareからデータを取得することに成功したので、情報をまとめます。

なお、取得するデータの前提は
- 取引所はBitFlyer
- BTC-FX
- 1時間足
として記事を書いていますが、少し読み替えれば他のパラメータでの取得にも応用がきくはずです。

※ 無料範囲で説明は完結しています。もし記事がお役に立ちそうでしたら投げ銭と思ってサポートいただけると幸いです。サポートいただけた場合のお礼として、有料エリアには記事で説明したpythonのソースコード全体を公開しています(コピペで実行できるはずです)。

成功:CryptCompareから取得

 CryptCompare のREST APIを使います。今回の用途ではアカウントの作成も不要でした。公式ドキュメントはこちら
1. pythonでの実装例
requestsパッケージがインストールされている前提で、以下の実装でOHLCVをjsonフォーマットのテキストが取得できます。


def requests_to_cryptocompare(toTs = -1):
   return requests.get('https://min-api.cryptocompare.com/data/v2/histohour', params={
       'fsym': "BTC",     # 仮想通貨のシンボル
       'tsym': "JPY",     # ペアの通貨のシンボル
       'limit': 2000,     # レコードの取得数、最大2000
       'e': "bitFlyerFX", # 取引所
       'toTs': toTs       # 取得したいデータの基準となるタイムスタンプ(unixtime)
       })

req = requests_to_cryptocompare()
print(req.text)​

各パラメータについて
fsym : 仮想通貨のシンボルです。今回はビットコインなのでBTCです。
tsym: ペアになっている通貨のシンボルです。今回はJPYです。
limit: 取得するデータ数です。最大値は2000で、それ以上大きな値は2000として処理されます。
toTs: 取得する期間の最新時刻を表すunixtimeです。指定した時刻から昇順に時系列データが返ります。-1を与えると、取得する期間は現在時刻からの直近になるようです。
例えば、 2020/01/12 22:00:00 までのデータを取得したい欲しい場合は以下のように呼び出せばOKです。

requests_to_cryptocompare(1578834000)
print(req.text)

2. レスポンス
さて、APIを叩くと、次のようなjsonが返ります

'{"Response":"Success",
  "Message":"","HasWarning":false,"Type":100,"RateLimit":{},
  "Data":{"Aggregated":false,"TimeFrom":1571634000,"TimeTo":1578834000,
  "Data":[{"time":1571634000,
  "close":912005,"high":913589,"low":909691,"open":910114,
  "volumefrom":2220.21,"volumeto":2024040638.16,
  "conversionType":"force_direct","conversionSymbol":""},...以下、同様のDataレコードが続く

2つある"Data"のうちの後者がOHLCVのリストです。(わかりにくいですが、"Data"をキーとした辞書データの中に、更に"Data"をキーとしてOHLCVのリストが格納されています)
timeは取引時刻を表すタイムスタンプ(unixtime)
close, high, low, open はそれぞれtsym(今回はJPY)での取引価格
volumefromはfsymに対応する通貨単位での取引量
volumetoはtsymに対応する通貨単位での取引量です
リストはタイムスタンプで降順です。新しい時刻のデータほど、後ろに詰められています。

3. 全件取得するには...
一度のリクエストで取得できるのは2000件までなので、それ以上のデータが必要な場合は複数回リクエストを投げる必要があります。
レスポンスにはレコードのタイムスタンプが含まれているので、一番古いタイムスタンプ未満の値を次のリクエストのtoTSに入れ、再度リクエストを投げるようなループを書けばOKです。
なお、小さすぎる(昔すぎる)timestampをtoTSに入れても直接エラーにはならず、フェールセーフなデータが返ってくるようです。その時はcloseなどの各データが0になるようなので、ループの終了条件に使えそうです。

以下は実装です。
(jsonパッケージが必要です。)

# 各データの保存先
open_list = []
close_list = []
high_list = []
low_list = []
volume_from_list = []
volume_to_list = []
datetime_list = []
next_unixtime = -1

#タイムスタンプをさかのぼりながらデータを取得し、リストに詰めていく
while b:
       req = requests_to_cryptocompare(next_unixtime)
       js = json.loads(req.text)
       # データは日付が古い方から新しい方に向けて格納される
       # 期間をさかのぼりながら取得する手順と組み合わせるため、逆順にして新しいデータ→古いデータの順に入れていく
       data_list = js["Data"]["Data"]
       data_list.reverse()
       for data in data_list:
           if data["close"] == 0: # 期間外でデータが存在しない場合はエラーなどではなく、0が入るらしい
               b = False
               break
           unixtime = data["time"]
           dt = datetime.fromtimestamp(unixtime)
           datetime_list.append(dt)
           volume_from_list.append(data["volumefrom"]) # この場合はBTC単位の取引量ら
           volume_to_list.append(data["volumeto"]) # 同Yenでの取引量
           open_list.append(data["open"])
           close_list.append(data["close"])
           low_list.append(data["low"])
           high_list.append(data["high"])
           next_unixtime = unixtime - 1
       print(datetime.fromtimestamp(data_list[0]["time"]) ," to " , datetime.fromtimestamp(data_list[-1]["time"]))
       sleep(0.2)

この実装例では、取得したデータは降順(新しい日付のデータ→古い日付のデータ)となります。

うまく行かなかった方法

うまく行かなかったパターンとその理由も参考までに。
1. BitFlyerの公式APIからの取得 (失敗:取得可能な期間が短い)
→ 普通に考えればこれが一番筋が良さそうでしたが...。
公式ドキュメントに従えば、

https://api.bitflyer.com/v1/getexecutions
https://api.bitflyer.com/v1/executions

のいずれかのREST APIで取得できそうです。しかし、実際に試してみたところ、残念ながら同APIでは直近一ヶ月までのデータしか取得できませんでした。公式ページによれば、2018 年 12 月 19 日移行、そういった制限が入ったようです。残念。

2. CryptWatchのAPIから入手 (失敗:取得可能な期間が短い)
→ アカウントを作成して、公式のドキュメント の手順に従ってREST API。以下のように叩いてみました、が...

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?after=1557170000&periods=3600

取得できたデータは一番古くても 2019/5/17 08:00 (unixtime = 1557183600) でした。それ以前は取得できないのか、有料プランでサポートされるのかのどちらかのようなのですが...明言されている場所が見つからず、断念しました。Webではもっと古いデータを同じ方法で取得している人もいたようなので、公式同様に直近の一定期間に制限されている可能性が高いかと思います。(正確な情報求む)

3. Investing.comから取得 (失敗FXは未対応 & 日足限定)

→ 気軽にcsvで取得できるサイトとしておすすめされているようだったのですが、残念ながらBTC/JPYはあってもFXはデータが見つからず、かつデータが一番短いスパンでも日足でした。

--- 以下、有料エリアに動作確認済みのpythonのコード全体を載せています。 ---

ここから先は

2,212字

¥ 100

この記事が気に入ったらチップで応援してみませんか?