見出し画像

BybitAPIでローソク足データを取得する

勉強記録⑰のリファインです。
なんと、この関数を使っているとの声を頂いたので、せっかくなので修正することにしました。

⑰を修正してもよかったけど、成長を感じたいので別の記事にしましたッ

◆コード

図1

# -*- coding: utf-8 -*-
"""
Created on Thu May  6 22:40:08 2021

@author: Mamu
"""
from tqdm import tqdm
from datetime import datetime,timedelta,timezone
import pybybit
import pandas as pd
import json
#--------------------設定項目--------------------
apis = [
'API',
'シークレット'
]
bybit = pybybit.API(*apis, testnet = True)

symbol           = "BTCUSD"
chart_min        = 1   # 時間軸(1 3 5 15 30 60 120 240 360 720 "D" "W" "M" )
get_start        = '2019/06/01 09:00' # ローソク足取得開始時刻

#--------------------関数--------------------
#====================価格データ取得===================
def get_price(chart_min,start):
   get_start = int(datetime.strptime(start,'%Y/%m/%d %H:%M').timestamp()) # タイムスタンプ変換
   price = []
   #200*n本のローソク足を取得して、price[]に入れる
   for o in tqdm(range(30), desc="{}分足データ取得中".format(chart_min)): # ()内の回数だけデータを取得

       #pybybitでローソク足取得
       data = bybit.rest.inverse.public_kline_list(
             symbol   = symbol,
             interval = chart_min,
             from_    = get_start
             ).json()

       #priceに取得したデータを入れる
       #bybitから帰ってくるデータがstr型なので、float型に変換してから格納する
       for i in data["result"]:
           price.append({
               "open_time" :i["open_time"],
               "open"      :float(i["open"]),
               "high"      :float(i["high"]),
               "low"       :float(i["low"]),
               "close"     :float(i["close"]),
               "volume"    :float(i["volume"])
               })

       #200本x足の長さ分だけタイムスタンプを進める
       if chart_min == "D" :
           get_start += 200*60*1440

       elif chart_min == "W" :
           get_start += 200*60*10080

       else:
           get_start += 200*60*chart_min

   return price

#====================DF作成===================
def cleate_table(data):
   df = pd.DataFrame(data)

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

   # dfのopen_timeを日本時間にして表示(UTCのままでいい場合は不要)
   df['open_time'] = (df['open_time'].apply(lambda x : datetime.fromtimestamp(x, tz_jst).strftime('%Y/%m/%d %H:%M')))

   print(df)

   return df

#====================ファイル出力===================
def output_file( data,df ):
   # 表をCSVで出力
   df.to_csv("./{0}min-{1}-{2}.csv".format(chart_min,data[0]["open_time"],data[-1]["open_time"]))

   # ローソク足をjsonファイルで出力
   file = open("./{0}min-{1}-{2}.json".format(chart_min,data[0]["open_time"],data[-1]["open_time"]),"w",encoding="utf-8")
   json.dump(data,file,indent=4)

#--------------------メイン処理--------------------
data = get_price(chart_min,get_start)
df = cleate_table(data)
# output_file( data,df )

◆解説

図1

3つの関数を作っています。
いつものごとくPybybitを使います。

・get_price(chart_min,start)

図2

#====================価格データ取得===================
def get_price(chart_min,start):
   get_start = int(datetime.strptime(start,'%Y/%m/%d %H:%M').timestamp()) # タイムスタンプ変換
   price = []
   #200*n本のローソク足を取得して、price[]に入れる
   for o in tqdm(range(30), desc="{}分足データ取得中".format(chart_min)): # ()内の回数だけデータを取得

       #pybybitでローソク足取得
       data = bybit.rest.inverse.public_kline_list(
             symbol   = symbol,
             interval = chart_min,
             from_    = get_start
             ).json()

       #priceに取得したデータを入れる
       #bybitから帰ってくるデータがstr型なので、float型に変換してから格納する
       for i in data["result"]:
           price.append({
               "open_time" :i["open_time"],
               "open"      :float(i["open"]),
               "high"      :float(i["high"]),
               "low"       :float(i["low"]),
               "close"     :float(i["close"]),
               "volume"    :float(i["volume"])
               })

       #200本x足の長さ分だけタイムスタンプを進める
       if chart_min == "D" :
           get_start += 200*60*1440

       elif chart_min == "W" :
           get_start += 200*60*10080

       else:
           get_start += 200*60*chart_min

   return price

指定した回数だけBybitへのローソク足取得リクエストを送る関数です。
BybitののAPIでは、ローソク足は1回のリクエストで最大200本しかデータを返してくれないので、何度もリクエストを送ることで多くのデータを取得します。

また、Bybitから帰ってくるデータは大体str型です、、、なんでやねん
そのため、使いやすいように取得の際にfloat型に変換しています。

また、tqdmというライブラリでデータの取得状況を確認できるようにしました。いい感じです!

・cleate_table(data)

図2

#====================DF作成===================
def cleate_table(data):
   df = pd.DataFrame(data)

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

   # dfのopen_timeを日本時間にして表示(UTCのままでいい場合は不要)
   df['open_time'] = (df['open_time'].apply(lambda x : datetime.fromtimestamp(x, tz_jst).strftime('%Y/%m/%d %H:%M')))

   print(df)

   return df

PandasDataFrameを作る関数です。
取得したローソク足データをDataFrameにします。

DataFrameではopen_timeをタイムスタンプから日本時間表示に変更していますが、いらなければコメントアウトしてください。

・output_file( data,df )

図2

#====================ファイル出力===================
def output_file( data,df ):
   # 表をCSVで出力
   df.to_csv("./{0}min-{1}-{2}.csv".format(chart_min,data[0]["open_time"],data[-1]["open_time"]))

   # ローソク足をjsonファイルで出力
   file = open("./{0}min-{1}-{2}.json".format(chart_min,data[0]["open_time"],data[-1]["open_time"]),"w",encoding="utf-8")
   json.dump(data,file,indent=4)

作成したDFをcsv形式、ローソク足データをjson形式にして出力する関数です。出力先を変更したい場合は、"./{0}min-{1}-{2}.csv"の部分に出力先の絶対パスを入れれば変更できます。
(./の部分が実行ファイルと同じ場所を指しています。)

◆実行結果

図1

GIF貼りたかった。。。
実行中にバーがどんどん伸びていって楽しいです。

runfile('C:/Pydoc/get_price.py', wdir='C:/Pydoc')
1分足データ取得中: 100%|██████████| 30/30 [00:09<00:00,  3.01it/s]

            open_time    open    high     low   close    volume
0     2019/06/01 09:00  8550.0  8555.5  8544.5  8545.5   92286.0
1     2019/06/01 09:01  8545.5  8564.0  8545.0  8558.0  229509.0
2     2019/06/01 09:02  8558.0  8567.0  8557.0  8567.0   88257.0
3     2019/06/01 09:03  8567.0  8567.0  8558.0  8564.5  138781.0
4     2019/06/01 09:04  8564.5  8564.5  8558.5  8558.5   78892.0
              ...     ...     ...     ...     ...       ...
5995  2019/06/05 12:55  7798.0  7798.0  7796.5  7796.5  354058.0
5996  2019/06/05 12:56  7796.5  7797.0  7792.0  7792.5   71034.0
5997  2019/06/05 12:57  7792.5  7792.5  7786.0  7786.0   56066.0
5998  2019/06/05 12:58  7786.0  7792.0  7785.5  7791.5  152173.0
5999  2019/06/05 12:59  7791.5  7796.5  7791.5  7794.5   90425.0

[6000 rows x 6 columns]

デフォルトではリクエスト回数を30にしているので、6,000個のデータを取得できます。

リクエスト回数を300にすれば、60,000個のデータを取得できます(時間かかります)

runfile('C:/Pydoc/get_price.py', wdir='C:/Pydoc')
1分足データ取得中: 100%|██████████| 300/300 [01:48<00:00,  2.77it/s]

             open_time     open     high      low    close    volume
0      2019/06/01 09:00   8550.0   8555.5   8544.5   8545.5   92286.0
1      2019/06/01 09:01   8545.5   8564.0   8545.0   8558.0  229509.0
2      2019/06/01 09:02   8558.0   8567.0   8557.0   8567.0   88257.0
3      2019/06/01 09:03   8567.0   8567.0   8558.0   8564.5  138781.0
4      2019/06/01 09:04   8564.5   8564.5   8558.5   8558.5   78892.0
               ...      ...      ...      ...      ...       ...
59995  2019/07/13 00:55  11537.0  11542.5  11537.0  11542.5   26883.0
59996  2019/07/13 00:56  11542.5  11562.0  11542.5  11562.0   30061.0
59997  2019/07/13 00:57  11562.0  11567.5  11551.0  11551.0   71350.0
59998  2019/07/13 00:58  11551.0  11551.5  11545.0  11545.0  170529.0
59999  2019/07/13 00:59  11545.0  11545.0  11528.5  11529.5   44854.0

[60000 rows x 6 columns]

おわり


画像7


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