見出し画像

Pandas勉強記録 ①ローソク足データをまとめる

今回の使用文

1. pd.to_datetime
2.set_index
3. tz_localize
4. tz_convert
5. drop
6. astype

最近更新が全く無かったのは、仕事とbot開発で忙しいからです(ごめんなさい)

ここ1か月くらい、いろいろな指標を見つけてはバックテストをし、うまくいかないんだぜ!と嘆きながらbot開発をしているのですが、段々バックテストの効率が良くなってきました。
その理由がPandas!

pythonのデータ分析ライブラリであるpandasを頻繁に使っています。
もともとエクセルでデータをまとめたり、分析するのが好きだった僕は、pandasが楽しくて仕方ありません。
bot開発においても超便利&重要なモジュールだと思うので、勉強しつつ共有していこうと思います。

第1回となる今回は、基本中の基本であるローソク足データのまとめ方にしようと思います。

ローソク足データって、

1.open(close)_time
2.open
3.high
4.low
5.close
6.volume

大体こんな感じのデータの羅列になってますよね。
bybitで取得すると​

[{'close''35591',
 'high''35634.5',
 'interval''1',
 'low''35552.5',
 'open''35634.5',
 'open_time'1624233600,
 'symbol''BTCUSD',
 'turnover''17.56960294',
 'volume''625158'},
{'close''35565',
 'high''35591',
 'interval''1',
 'low''35554',
 'open''35591',
 'open_time'1624233660,
 'symbol''BTCUSD',
 'turnover''24.43114691',
 'volume''869039'},
{'close''35698',
 'high''35712.5',
 'interval''1',
 'low''35565',
 'open''35565',
 'open_time'1624233720,
 'symbol''BTCUSD',
 'turnover''39.28672232',
 'volume''1401459'}]

他にもいろいろデータ入ってたわ。。。
これじゃ見づらいので、↓のような表形式にします。

                              open     high      low    close     volume
open_time                                                               
2021-06-21 09:00:00+09:00  35634.5  35634.5  35552.5  35591.0   625158.0
2021-06-21 09:01:00+09:00  35591.0  35591.0  35554.0  35565.0   869039.0
2021-06-21 09:02:00+09:00  35565.0  35712.5  35565.0  35698.0  1401459.0
2021-06-21 09:03:00+09:00  35698.0  35732.5  35652.0  35667.5  6100246.0
2021-06-21 09:04:00+09:00  35667.5  35674.0  35552.0  35552.0   970578.0
                          ...      ...      ...      ...        ...
2021-06-22 08:15:00+09:00  31704.0  31713.5  31650.0  31659.5  1536238.0
2021-06-22 08:16:00+09:00  31659.5  31659.5  31552.5  31553.5   272027.0
2021-06-22 08:17:00+09:00  31553.5  31607.0  31553.5  31588.5   915330.0
2021-06-22 08:18:00+09:00  31588.5  31594.0  31571.5  31589.5   711770.0
2021-06-22 08:19:00+09:00  31589.5  31614.5  31589.5  31611.5   794391.0

[1400 rows x 5 columns]

各行にopen_timeごとのohlcが入っていて見やすいです。

1.ローソク足データを取得する

図1

とりあえずohlcデータを準備しましょう。

import pybybit
from pprint import pprint as print
from datetime import datetime

apis = []
bybit = pybybit.API(*apis, testnet = True)

symbol = "BTCUSD"
interval = 1
# ローソク足取得開始時刻
start     = '2021/06/21 09:00' 
# タイムスタンプに変換
get_start = int(datetime.strptime(start,"%Y/%m/%d %H:%M").timestamp())

ohlcv = bybit.rest.inverse.public_kline_list(
             symbol   = symbol,
             interval = interval,
             from_    = get_start,
             limit    = 5
             ).json()["result"]

print(ohlcv)

実行すると普通のローソク足データ( json形式 )が入手できます。

2.表形式に変換する

図1

json形式のohlcvを入手できたので、表形式に変換します。
ここでpandasを使います!

import pybybit
from pprint import pprint as print
from datetime import datetime
import pandas as pd

apis = []
bybit = pybybit.API(*apis, testnet = True)

symbol = "BTCUSD"
interval = 1
# ローソク足取得開始時刻
start     = '2021/06/21 09:00' 
# タイムスタンプ変換
get_start = int(datetime.strptime(start,"%Y/%m/%d %H:%M").timestamp())

ohlcv = bybit.rest.inverse.public_kline_list(
             symbol   = symbol,
             interval = interval,
             from_    = get_start,
             limit = 5
             ).json()["result"]

df = pd.DataFrame(ohlcv)

print(df)

pandasモジュールをインポートし、23行目に入手したohlcvを表形式に変換する命令を追加しました。

pd.DataFrame(変換したいデータ)で表形式のデータを作ることができます。

   symbol interval   open_time  ...    close   volume      turnover
0  BTCUSD        1  1624233600  ...    35591   625158   17.56960294
1  BTCUSD        1  1624233660  ...    35565   869039   24.43114691
2  BTCUSD        1  1624233720  ...    35698  1401459   39.28672232
3  BTCUSD        1  1624233780  ...  35667.5  6100246  170.96374332
4  BTCUSD        1  1624233840  ...    35552   970578   27.25406336

[5 rows x 9 columns]

3.表を綺麗にする

図1

表ができたので、行名(pandasではindexと言う)をopen_timeに変更、open_timeを日本時間の見やすい表記に変換、使わないデータを削除などを行います。

3-1.open_timeをdatetime形式に変換

図2

df.open_time = pd.to_datetime(df.open_time*10**9)

まずはこの1行を追加します。
dfのopen_time列に、pd.to_datetimeでdfのopen_timeの値をdatetime形式に変換したものを入れています。

df.open_time*10**9でopen_timeを10の9乗しているのは、pd.to_datetimeでは、形式に変換する際に19桁の数字を必要とするからです。(bybitから帰ってくるopen_timeの値(UNIXTIME)は10桁)

これでopen_timeがdatetime形式になって見やすくなりましたが、世界標準時のままです。(日本より9時間遅い)
次に日本時間表記に変換してみましょう。

3-2.open_timeを日本時間に変換し、indexにセット

図2

df = df.set_index('open_time').tz_localize('UTC').tz_convert('Asia/Tokyo')

この行では、3回の処理を1行にまとめています。
分解すると。。。

df.open_time = df.open_time.tz_localize('UTC')
df.open_time = df.open_time.tz_convert('Asia/Tokyo')
df.set_index('open_time')

1行目:tz_localize('UTC')により、open_timeにUTC(世界標準時)のタイムゾーンを設定します。(この時間はUTCですよと宣言します)

2行目:.tz_convert('Asia/Tokyo')により、タイムゾーンを東京に変換します。

3行目:df.set_index('open_time')でindexにopen_timeをセットします。

これでindexが日本時間表記の日付になりました!

                           symbol interval  ...   volume      turnover
open_time                                   ...                       
2021-06-21 09:00:00+09:00  BTCUSD        1  ...   625158   17.56960294
2021-06-21 09:01:00+09:00  BTCUSD        1  ...   869039   24.43114691
2021-06-21 09:02:00+09:00  BTCUSD        1  ...  1401459   39.28672232
2021-06-21 09:03:00+09:00  BTCUSD        1  ...  6100246  170.96374332
2021-06-21 09:04:00+09:00  BTCUSD        1  ...   970578   27.25406336

[5 rows x 8 columns]

注意
1行目の時点で
df.open_time = df.open_time.tz_localize('Asia/Tokyo')にしてしまうと、+9:00されず、その時間が日本時間ということになってしまいます。
(bybitから帰ってくる時刻はUTCなのに、JSTと宣言してしまうことに)

なので、一度UTCであるという宣言をしてから、tz.convertで日本時間に変換する必要があります。

3-3.不要なデータを削除

図2

僕の場合はohlcのデータのみ残すようにしています。

symbol:BTCUSD ⇒ 知っとるがな
interval:1    ⇒ 知っとるがな
volume:      ⇒ 使わない
turnover:    ⇒ なにそれ

ということで、この4列を削除します。

df.drop(["symbol","interval","volume","turnover"],axis = 1,inplace = True)

df.drop:削除する という意味です。
axis = 1:列の中から"symbol"や"volume"を探してね という意味です。
inplace = True:dropしたdfを正とするよ という意味です。

inplaceだけ分かりづらいんですが、Falseにするとオリジナルのdfからは削除されません。試してみてくださいな。

これで表がすっきりしました。

                              open     high      low    close
open_time                                                    
2021-06-21 09:00:00+09:00  35634.5  35634.5  35552.5    35591
2021-06-21 09:01:00+09:00    35591    35591    35554    35565
2021-06-21 09:02:00+09:00    35565  35712.5    35565    35698
2021-06-21 09:03:00+09:00    35698  35732.5    35652  35667.5
2021-06-21 09:04:00+09:00  35667.5    35674    35552    35552

3-4.データの形式を変換

図2

pandas_dataframeというのは、列同士で演算ができます。
例えばすべての行でhigh - lowを行いたかったら、

df["high - low"] = df.high - df.low

上記の1行で、新しくhigh - lowの列を作ることができるんですが。。。
このdfで新たな列を作ろうとしても以下のエラーが出ます。

TypeError: unsupported operand type(s) for -: 'str' and 'str'

まぁ読めばわかるんですが、文字列型同士の演算はできないよというエラーですね。bybitがstr型でデータを送ってくるからです(# ゚Д゚)
これを回避するために全てfloat型に変換しましょう。

df = df.astype('float')

これでOKです。すべての要素をfloat型に変換しました。
無事列同士の計算もできるようになりました。

                              open     high      low    close  high - low
open_time                                                                
2021-06-21 09:00:00+09:00  35634.5  35634.5  35552.5  35591.0        82.0
2021-06-21 09:01:00+09:00  35591.0  35591.0  35554.0  35565.0        37.0
2021-06-21 09:02:00+09:00  35565.0  35712.5  35565.0  35698.0       147.5
2021-06-21 09:03:00+09:00  35698.0  35732.5  35652.0  35667.5        80.5
2021-06-21 09:04:00+09:00  35667.5  35674.0  35552.0  35552.0       122.0

4.まとめ

図1

以下の5行でohlcをスッキリした表形式に変換することができました。

df = pd.DataFrame(ohlcv)
df.open_time = pd.to_datetime(df.open_time*10**9)
df = df.set_index('open_time').tz_localize('UTC').tz_convert('Asia/Tokyo')
df.drop(["symbol","interval","volume","turnover"],axis = 1,inplace=True)
df = df.astype('float')

これでローソク足を使った計算はなんでもできます。しかも簡単で速い!

今回はここまで!
最後に全コードを載せて終わりにします。

import pybybit
from pprint import pprint as print
from datetime import datetime
import pandas as pd

apis = []
bybit = pybybit.API(*apis, testnet = True)

symbol = "BTCUSD"
interval = 1
# ローソク足取得開始時刻
start     = '2021/06/21 09:00' 
# タイムスタンプ変換
get_start = int(datetime.strptime(start,"%Y/%m/%d %H:%M").timestamp())

ohlcv = bybit.rest.inverse.public_kline_list(
   symbol   = symbol,
   interval = interval,
   from_    = get_start,
   limit    = 5
   ).json()["result"]

df = pd.DataFrame(ohlcv)
df.open_time = pd.to_datetime(df.open_time*10**9)
df = df.set_index('open_time').tz_localize('UTC').tz_convert('Asia/Tokyo')
df.drop(["symbol","interval","volume","turnover"],axis = 1,inplace=True)
df = df.astype('float')

print(df)

いいなと思ったら応援しよう!