OANDA API 解説編 第4回 ろうそく足を取得してみた (2)
今回はOANDA APIで取得したろうそく足をpandasのDataFrameに変換する方法を試してみました。
1. リストを使ってDataFrameに変換する
まずは単純に配列を使ってDataFrameに変換する方法を試してみました。
一番簡単なのはレートの部分だけを取り出すことなのでまずはこれから。
ろうそく足のフォーマットは、
{ "instrument": "USD_JPY", "granularity": "M5", "candles": [ { "complete": true, "volume": 127, "time": "2020-07-28T16:35:00.000000000Z", "mid": { "o": "105.086", "h": "105.086", "l": "105.063", "c": "105.076" } },
なので、レートの部分だけを考えれば"mid"以下の部分を取り出せばよいことになりますので、"candles"の部分をループさせて"mid"のところをリストに追加します。
# 必要なモジュールの読み込み import requests import json import pandas as pd 👈追加 # 口座情報の設定 (口座の開設の仕方はググってね) API_Token = '********************************-********************************' API_AccountID = '999-999-99999999-999' # URLの設定 (デモ口座用非ストリーミングURL) API_URL = "https://api-fxpractice.oanda.com" # 通貨ペア INSTRUMENT = "USD_JPY" # <ろうそく足取得用URLの変数の設定> # /v3/instruments/{Account ID}/candles url = API_URL + "/v3/instruments/%s/candles?count=5&price=M&granularity=M5" % INSTRUMENT # ヘッダー情報の変数の設定 headers = { "Authorization" : "Bearer " + API_Token } # サーバーへの要求 response = requests.get(url, headers=headers) # 処理結果の編集 Response_Body = response.json() # # ------------------------------------ 👈ここから #DataFrameへ変換 list=[] for row in Response_Body['candles']: list.append(row['mid']) df = pd.DataFrame(list) # ------------------------------------ 👈ここまで # print(df)
出力結果
o h l c 0 104.968 104.971 104.948 104.948 1 104.950 104.952 104.910 104.912 2 104.911 104.947 104.911 104.946 3 104.948 104.952 104.916 104.920 4 104.926 104.926 104.919 104.919 5 104.924 104.960 104.924 104.945 6 104.950 104.956 104.950 104.956 7 104.960 104.960 104.946 104.946 8 104.950 104.950 104.926 104.928 9 104.942 104.959 104.935 104.951
せっかくですからforループを使わずにリスト内包表記を使って一行で表現してみます。
df = pd.DataFrame(row['mid'] for row in Response_Body['candles'])
次に、やはりレートの部分だけをとりだしてもわかりずらいので、その他のあったら便利な部分も全部変換したいと思います。
list=[] for row in Response_Body['candles']: list.append([Response_Body['instrument'], Response_Body['granularity'], row['complete'], row['volume'], row['time'], row['mid']['o'], row['mid']['h'], row['mid']['l'], row['mid']['c']]) print(df)
同様にリスト内包表記で表現すると
df = pd.DataFrame([Response_Body['instrument'], Response_Body['granularity'], row['complete'], row['volume'], row['time'], row['mid']['o'], row['mid']['h'],row['mid']['l'], row['mid']['c']] for row in Response_Body['candles'])
一行にはなりますが、どちらの方法にせよ値を抽出する部分が長くなってしまいますね。
0 1 2 3 4 5 6 7 8 0 USD_JPY M5 True 53 2020-07-29T22:00:00.000000000Z 104.934 104.939 104.910 104.928 1 USD_JPY M5 True 40 2020-07-29T22:05:00.000000000Z 104.926 104.948 104.921 104.944 2 USD_JPY M5 True 46 2020-07-29T22:10:00.000000000Z 104.946 104.958 104.946 104.957 3 USD_JPY M5 True 61 2020-07-29T22:15:00.000000000Z 104.958 104.960 104.956 104.959 4 USD_JPY M5 True 58 2020-07-29T22:20:00.000000000Z 104.958 104.961 104.956 104.957 5 USD_JPY M5 True 44 2020-07-29T22:25:00.000000000Z 104.956 104.962 104.950 104.957 6 USD_JPY M5 True 37 2020-07-29T22:30:00.000000000Z 104.959 104.977 104.958 104.977 7 USD_JPY M5 True 47 2020-07-29T22:35:00.000000000Z 104.975 104.976 104.962 104.963 8 USD_JPY M5 True 40 2020-07-29T22:40:00.000000000Z 104.962 104.963 104.950 104.954 9 USD_JPY M5 False 6 2020-07-29T22:45:00.000000000Z 104.952 104.953 104.946 104.946
必要な値がすべて表示されましたが、ヘッダー部分が番号に置き換わってしまいました。
というわけなので、必要であればcolumnsでヘッダーに名前をつけてあげましょう。
df.columns = ['pair', 'ashi', 'complete', 'volume', 'time_UTC', 'open', 'high', 'low', 'close']
pair ashi complete volume time_UTC open high low close 0 USD_JPY M5 True 53 2020-07-29T22:00:00.000000000Z 104.934 104.939 104.910 104.928 1 USD_JPY M5 True 40 2020-07-29T22:05:00.000000000Z 104.926 104.948 104.921 104.944 2 USD_JPY M5 True 46 2020-07-29T22:10:00.000000000Z 104.946 104.958 104.946 104.957 3 USD_JPY M5 True 61 2020-07-29T22:15:00.000000000Z 104.958 104.960 104.956 104.959 4 USD_JPY M5 True 58 2020-07-29T22:20:00.000000000Z 104.958 104.961 104.956 104.957 5 USD_JPY M5 True 44 2020-07-29T22:25:00.000000000Z 104.956 104.962 104.950 104.957 6 USD_JPY M5 True 37 2020-07-29T22:30:00.000000000Z 104.959 104.977 104.958 104.977 7 USD_JPY M5 True 47 2020-07-29T22:35:00.000000000Z 104.975 104.976 104.962 104.963 8 USD_JPY M5 True 40 2020-07-29T22:40:00.000000000Z 104.962 104.963 104.950 104.954 9 USD_JPY M5 False 7 2020-07-29T22:45:00.000000000Z 104.952 104.953 104.946 104.947
これで見やすくなりました。
2. json_normalizeを使ってDataFrameに変換する
変換したい項目が増えてくるとだらだらと長くなるのでどうにかならないかと思って調べたところ、pandasにはjson_normailizeという便利な関数があることがわかりましたので、これを使った方法で変換してみました。参考にしたサイトはこちら
まずは同様に簡単そうなレートの部分だけを変換してみたいと思います。 1.のpythonコードのDataFrameへの変換部分を以下の命令に置き換えると
df = pd.json_normalize(Response_Body['candles'])
簡単に変換できた上にVolumeなども同時に変換できました!(^^)!
complete volume time mid.o mid.h mid.l mid.c 0 True 123 2020-07-30T23:50:00.000000000Z 104.696 104.698 104.662 104.668 1 True 224 2020-07-30T23:55:00.000000000Z 104.668 104.689 104.666 104.688 2 True 798 2020-07-31T00:00:00.000000000Z 104.689 104.700 104.554 104.596 3 True 404 2020-07-31T00:05:00.000000000Z 104.598 104.618 104.566 104.608 4 True 442 2020-07-31T00:10:00.000000000Z 104.606 104.606 104.528 104.542 5 True 316 2020-07-31T00:15:00.000000000Z 104.544 104.562 104.510 104.532 6 True 329 2020-07-31T00:20:00.000000000Z 104.530 104.575 104.522 104.572 7 True 426 2020-07-31T00:25:00.000000000Z 104.574 104.600 104.530 104.558 8 True 459 2020-07-31T00:30:00.000000000Z 104.560 104.598 104.522 104.528 9 False 83 2020-07-31T00:35:00.000000000Z 104.526 104.547 104.522 104.547
ここまでくると通貨ペアや足についても一度に変換したくなります。 (固定値なので列を追加しても同じ事なのですが・・・)
df = pd.json_normalize(Response_Body, record_path='candles', meta=['instrument', 'granularity'], sep='_')
上のような命令に変更すれば、
complete volume time mid_o mid_h mid_l mid_c instrument granularity 0 True 378 2020-07-31T00:40:00.000000000Z 104.592 104.594 104.516 104.529 USD_JPY M5 1 True 459 2020-07-31T00:45:00.000000000Z 104.530 104.571 104.478 104.550 USD_JPY M5 2 True 788 2020-07-31T00:50:00.000000000Z 104.549 104.606 104.506 104.578 USD_JPY M5 3 True 514 2020-07-31T00:55:00.000000000Z 104.580 104.584 104.522 104.552 USD_JPY M5 4 True 334 2020-07-31T01:00:00.000000000Z 104.554 104.580 104.550 104.558 USD_JPY M5 5 True 249 2020-07-31T01:05:00.000000000Z 104.559 104.592 104.540 104.540 USD_JPY M5 6 True 180 2020-07-31T01:10:00.000000000Z 104.539 104.545 104.499 104.500 USD_JPY M5 7 True 293 2020-07-31T01:15:00.000000000Z 104.501 104.509 104.466 104.468 USD_JPY M5 8 True 295 2020-07-31T01:20:00.000000000Z 104.470 104.496 104.458 104.462 USD_JPY M5 9 False 29 2020-07-31T01:25:00.000000000Z 104.460 104.463 104.456 104.460 USD_JPY M5
たった一行ですべてのろうそく足の情報を変換することができます。json_normalize万歳\(^o^)/
3. DataFrame内の時刻を変換してみる
最後にOANDA APIで取得したろうそく足の時間のフォーマットそのままでは見にくいので、これをいろいろな形に変更してみたいと思います。
時刻をUTC時間帯から任意の時間帯に変換したい場合は変換したい列をdatetime形式に変換したあとtz_convert関数で時間帯を変更してあげるとよいみたいです。 下の例では"time_JST"という新しい列を追加して、そこに日本時間がセットされるようにします。
df['time_JST'] = pd.to_datetime(df['time']).dt.tz_convert('Asia/Tokyo')
complete volume time mid_o mid_h mid_l mid_c instrument granularity time_JST 0 True 559 2020-07-31T16:50:00.000000000Z 105.886 105.916 105.874 105.874 USD_JPY M5 2020-08-01 01:50:00+09:00 1 True 577 2020-07-31T16:55:00.000000000Z 105.876 105.896 105.833 105.837 USD_JPY M5 2020-08-01 01:55:00+09:00 2 True 325 2020-07-31T17:00:00.000000000Z 105.835 105.857 105.825 105.830 USD_JPY M5 2020-08-01 02:00:00+09:00
列の最後に日本時間に変換された新しい”time_JST"列が追加されました。
ちなみに指定できる時間帯の引数一覧はここにありますので、必要に応じて指定してあげてください。
さらにもっとフォーマットしたい人は.dt.strftime()を加える事によってより自分の見やすい形に編集できます。
df['time_JST'] = pd.to_datetime(df['time']).dt.tz_convert('Japan').dt.strftime('%Y-%m-%d %H:%M %Z')
であれば、こんな感じになります。
complete volume time mid_o mid_h mid_l mid_c instrument granularity time_JST 0 True 68 2020-07-31T20:10:00.000000000Z 105.856 105.891 105.856 105.886 USD_JPY M5 2020-08-01 05:10 JST 1 True 71 2020-07-31T20:15:00.000000000Z 105.885 105.906 105.864 105.906 USD_JPY M5 2020-08-01 05:15 JST 2 True 50 2020-07-31T20:20:00.000000000Z 105.905 105.905 105.882 105.899 USD_JPY M5 2020-08-01 05:20 JST
列の順番も並べ変えて不要な列も落としたい場合は、loc, iloc, []を使えば自由に編集できます。
ilocを使った例として、
df = df.iloc[:,[7,8,9,0,1,3,4,5,6]]
のように好きな順序で不要な列のindexを除けば完成です。
instrument granularity time_JST complete volume mid_o mid_h mid_l mid_c 0 USD_JPY M5 2020-08-01 05:10 JST True 68 105.856 105.891 105.856 105.886 1 USD_JPY M5 2020-08-01 05:15 JST True 71 105.885 105.906 105.864 105.906 2 USD_JPY M5 2020-08-01 05:20 JST True 50 105.905 105.905 105.882 105.899
まとめ
pandasを使うとデータの加工がとても簡単になりますね。
というわけですので、次回はろうそく足のデータをどのようにシンプルな形でグラフ化できるか考えてみたいと思います。