見出し画像

仮想通貨bot 勉強記録⑰

~Bybitのローソク足を大量に取得する~

※2021/05/10
以下の記事にて、本記事のコードを修正しました。

◆前回までのあらすじ

図1

画像5

試作版の赤三兵・黒三兵botでバックテストができるようになりました。

◆バックテスト用の過去データを集める

図1

Bybitのローソク足取得リクエストって、1回のリクエストで200本しかデータをくれないんですよね~。なので、1回で大量のローソク足を取得できるコードを作ってみました。

書いたコードはこちら

from datetime import datetime,timedelta,timezone
from rich import print as pp
import pybybit
import pandas as pd

"""------------------------"""
apis = [
  'プライベートキー',
  'シークレットキー'
  ]
bybit = pybybit.API(*apis, testnet=True)
"""------------------------"""
#世界協定時から日本標準時を算出
tz_jst = timezone(timedelta(hours=+9), name='JST')

#取得するローソク足の長さ
min = 60 #60分足

#取得開始時刻の設定
from_t = {
   "year"   : int(2021), #年
   "month"  : int(3),    #月
   "day"    : int(31),   #日
   "hour"   : int(00),   #時
   "minute" : int(00)    #分
   }

#取得開始時刻のタイムスタンプ(**from_t)は辞書データを展開してる
t = int(datetime(**from_t).timestamp())

#現在時刻のタイムスタンプ(int型)
now = int(datetime.now().timestamp())

#データを格納する変数
klines = []

#tがnowより小さければ実行
while t < now:

   #pybybitでローソク足取得
   k = bybit.rest.inverse.public_kline_list(
          symbol = "BTCUSD",
          interval= min,
          from_ =t
          ).json()

   #klinesにデータを入れる
   klines += k["result"]
   pp(k["result"])
   #足の長さ分だけタイムスタンプを進める
   t += 200*60*min

#表にするデータ
df = pd.DataFrame(klines)
#表の中のopen_timeの表示を見やすくする
df['open_time'] = (df['open_time'].apply(lambda x : datetime.fromtimestamp(x, tz_jst).strftime('%Y/%m/%d %H:%M')))
df

・解説

図2

いつも通りコメントアウトで全部書いてます(良心的!!)
------------------------ーーーーーーーーーー

#世界協定時から日本標準時を算出
tz_jst = timezone(timedelta(hours=+9), name='JST')

後で日本時間を表示したいので、世界協定時に9時間プラスして日本標準時を出しておきます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#取得開始時刻の設定
from_t = {
   "year"   : int(2021), #年
   "month"  : int(3),    #月
   "day"    : int(31),   #日
   "hour"   : int(00),   #時
   "minute" : int(00)    #分
   }

ローソク足を取得する開始時刻を設定します。
例として2021/3/31 00:00を指定してます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#取得するローソク足の長さ
min = 60 #60分足

minは取得するローソク足の長さです。いじり方はBybitの仕様書を確認してください!今回は1分足で取得しますが、日足だと"D"を指定する必要があります。

画像12

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#取得開始時刻のタイムスタンプ(**from_t)は辞書データを展開してる
t = int(datetime(**from_t).timestamp())

ここ!イケメンコードです(?)
from_tの辞書データをすべて展開してdatetime()に渡しています。
datetimeについての参考記事↓

辞書データを展開して渡すやり方についての参考記事↓

展開に関しては、勉強記録⑥まちゅけんさんに教えてもらいました(ありがとうございます!)
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#現在時刻のタイムスタンプ(int型)
now = int(datetime.now().timestamp())

#データを格納する変数
klines = []

現在時刻と取得したローソク足データを格納するための変数を用意してます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#tがnowより小さければ実行
while t < now:

   #pybybitでローソク足取得
   k = bybit.rest.inverse.public_kline_list(
          symbol = "BTCUSD",
          interval= min,
          from_ =t
          ).json()

   #klinesにデータを入れる
   klines += k["result"]
   pp(k["result"])
   #取得した足の長さ分だけタイムスタンプを進める
   t += 200*60*min

t<nowなので、tがnowより小さい限り実行し続けます。

まず変数:kにBybitからローソク足を取得したら、klines += k["result"]で変数:klinesのリストにぶち込みます。このとき、ローソク足200本分のデータをklinesに入れます。

そしたら、pp(k["result"])でちゃんと取得できているか確認します。

そこまで終わったら、t += 200*60*minでタイムスタンプの数値を取得したローソク足の分だけ進めます。

イメージはこんな感じです↓

画像13


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#表にするデータ
df = pd.DataFrame(klines)
#表の中のopen_timeの表示を見やすくする
df['open_time'] = (df['open_time'].apply(lambda x : datetime.fromtimestamp(x, tz_jst).strftime('%Y/%m/%d %H:%M')))
df

最後が初登場のpandasです。
klinesに格納した大量のローソク足データを、いい感じの表にしてくれます。

変数:dfにpd.DataFrame(klines)でklines内のデータリストを格納します。
dfに入れた['open_time']の表示を変えます。
 (df['open_time'].apply(lambda x : datetime.fromtimestamp(x, tz_jst).strftime('%Y/%m/%d %H:%M')))
これで日本標準時に直して、見やすいよう表記を変えています。

最後にdfで表の表示を指示してます。

解説終わり!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

このコードはPandasを使います。AnacondaPromptではなく、JupyterNotebookで動かしてみてください。

・JupyterNotebookの動かし方

Windowsボタンから、Anaconda3のフォルダを展開し、Jupyter Notebookを選択します。

画像7

そうすると、ブラウザが開いて↓こんな感じの画面になります。

画像8

赤印⇒青印の順にクリックします。

次の画面に行ったら、先ほどのコードをコピペして、▶Runをクリックします。

画像9

下の方にスクロールすると、、、

画像10

いい感じの表ができました。
これがやりたかった。実は表自体は不要です()

でも僕と同じような初心者はおぉ~!ってなると思います。

◆取得したデータを.json形式で保存する

図1

今回の本命コードです!
取得したデータをjson形式に保存して、いつでも呼び出せるようにします。
これにより、大量のデータでバックテストを行うことができるようになります。

from datetime import datetime
import pybybit
import json

"""------------------------"""
apis = [
  'プライベートキー',
  'シークレットキー'
  ]
bybit = pybybit.API(*apis, testnet=True)
"""------------------------"""
#取得するローソク足の長さ
min = 1 #1分足

#取得開始時刻の設定
from_t = {
   "year"   : int(2021), #年
   "month"  : int(3),    #月
   "day"    : int(31),   #日
   "hour"   : int(00),   #時
   "minute" : int(00)    #分
   }
  
#取得開始時刻のタイムスタンプ(**from_t)は辞書データを展開してる
t = int(datetime(**from_t).timestamp())

#現在時刻のタイムスタンプ(int型)
now = int(datetime.now().timestamp())

#データを格納する変数
klines = []

#tがnowより小さければ実行
while t < now:

   #pybybitでローソク足取得
   k = bybit.rest.inverse.public_kline_list(
          symbol = "BTCUSD",
          interval= min,
          from_ =t
          ).json()

   #klinesに取得したデータを入れる
   klines += k["result"]
   #200本x足の長さ分だけタイムスタンプを進める
   t += 200*60*min

#ファイルに書き込む
file = open("./{0}-{1}-price.json".format(klines[0]["open_time"],klines[-1]["open_time"]),"w",encoding="utf-8")
json.dump(klines,file,indent=4)

・解説

図2

さっきのコードと同じです。
取得データの画面出力をやめて(pp(k["result"])の削除)、json形式のファイルに保存するようにしてます。(画面表示させると待機時間がめっちゃ長くなります)

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
最初にjsonモジュールをインポートしてます。

import json

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

#ファイルに書き込む
file = open("./{0}-{1}-price.json".format(klines[0]["open_time"],klines[-1]["open_time"]),"w",encoding="utf-8")
json.dump(klines,file,indent=4)

まず保存仕様を指定します。
保存先はopen("./{0}-{1}-price.js~./の部分で、実行ファイルがあるフォルダと同じところに保存する指定をしています。

ファイル名は{0}-{1}-price.jsonです。{0}は.format(klines[0]["open_time"],klines[-1]["open_time"])klines[0]["open_time"]の部分、{1}はklines[-1]["open_time"]の部分を指定してます。
要は最初と最後のローソク足の時刻です。

"w",encoding="utf-8"はファイルの保存形式を指定しています。意味等は以下記事参照。

解説終わり!

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

・実行

図2

このコードを実行すると、、、※backdata.pyという名前で保存してます。

画像16

jsonファイルが保存されました!
中身を見てみます。

画像16

ちゃんと大量のデータが取得できています。やったぜ!
これでバックテストが捗るはず。

◆コードのカスタマイズについて

図1

取得開始時刻、取得終了時刻を指定することもできます

#取得開始時刻の設定
start = {
   "year"   : int(2021), #年
   "month"  : int(3),    #月
   "day"    : int(31),   #日
   "hour"   : int(00),   #時
   "minute" : int(00)    #分
   }
  
start = int(datetime(**start).timestamp())

#取得終了時刻の設定
end = {
   "year"   : int(2021), #年
   "month"  : int(4),    #月
   "day"    : int(1),    #日
   "hour"   : int(00),   #時
   "minute" : int(00)    #分
   }
  
end = int(datetime(**end).timestamp())

時刻の設定をして

#tがnowより小さければ実行
while start < end:

  #pybybitでローソク足取得
  k = bybit.rest.inverse.public_kline_list(
         symbol = "BTCUSD",
         interval= min,
         from_ = start
         ).json()

  #klinesに取得したデータを入れる
  klines += k["result"]
  #200本x足の長さ分だけタイムスタンプを進める
  start += 200*60*min

while文を修正すれば、任意の期間のデータを取得できます。
説明親切すぎますね(自画自賛)

今回はここまで。

プログラミング楽しい!

画像16


この記事が気に入ったらサポートをしてみませんか?