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.ローソク足データを取得する
とりあえず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.表形式に変換する
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.表を綺麗にする
表ができたので、行名(pandasではindexと言う)をopen_timeに変更、open_timeを日本時間の見やすい表記に変換、使わないデータを削除などを行います。
3-1.open_timeをdatetime形式に変換
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にセット
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.不要なデータを削除
僕の場合は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.データの形式を変換
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.まとめ
以下の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)