大量の為替過去データをFX APIから取得する方法(機械学習用)
こんばんは、新米データサイエンティスト(@algon_fx)です。明後日から海外でのお仕事のため、今週はいつにも増して本業が大忙しです。
以前からFX APIの使い方を本ブログでもまとめて来ました。ブログのアクセスを見てみると、比較的人気のコンテンツでして、多くの方からコメントやフィードバックを頂いています。
「Pythonを使ったOANDA API v1で知っておきたい10の基本操作」では、過去為替レートのデータの取得方法や簡単な注文方法などをまとめました。初めてFX APIを触る方は、上の記事から読んでみください。
ある程度、OANDA APIの使い方にも慣れて機械学習モデリングをゴリゴリ始めると、「もっと訓練データを拡張したいな!」という場面が出てくるかと思います。
現在日本で気軽に使えるFX APIはOANDA APIしかありません。ドキュメントなどしっかり揃っており、OANDA APIさまさまですが、所々で制約や扱いづらい面があるのも事実です。
特に過去為替レートを大量に取得するのに私は一手間掛かりました。OANDA APIでは1回のAPIリクエストで5000件までしか取得ができません。また日付を指定して過去為替レートを取得するのですが、週末はレートデータがない為エラーを吐きます。
これをうまく処理するのに小一時間ほどエラーと戦いました(笑)。ってことで、今日は大規模な為替の過去データをAPI経由で取得する方法をまとめました!
STEP1 OANDA FX APIについて
大規模な為替データを取得する方法ですがいくつかあります。海外のFX業者もAPIを提供しているところもありますが原則として取引は行えません。
色々と国内・海外のFX APIを試しましたが、OANDA FX APIがドキュメントも揃っており使いやすいです。
OANDA APIには2つのバージョン(v1とv20)があります。
日本以外の国では最新のv20が主流で旧式のv1はすでに使えなくなりました。ですが、なぜか日本国内ではv1のみしか使えません。どこかのタイミングでv20へ切り替えが行われますが、OANDAジャパンさんへ問い合わせましたが現状は未定とのことです。
OANDA APIを使う方法ですが、下記の通りです。私の時は口座開設申請から1〜2日でAPIキーが発行されて使えるようになりました。
①OANDAジャパンで口座開設(数分で終わります)
②取引コースを「プロコース」選択(最低初回入金額20万円以上)
③数日で口座開設が完了します(ログイン情報が送られてくる)
④管理画面でAPI申請をしてAPIキーを取得
FX機械学習をやるのであれば、FX APIはデータ取得からロジック実装まで必須のツールです。是非、この機械にOANDAジャパンで口座開設をしてみてください。
STEP2 環境とAPI接続
OANDAのAPIキーを取得した方は、続いてSTEP2に進みましょう。APIへの接続とデータ処理を行うために必要なライブラリをインポートしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# ライブラリのインポート import pandas as pd import numpy as np import matplotlib.pyplot as plt import oandapy import configparser import datetime from datetime import datetime, timedelta import pytz # PnadasとMatoplotlibの設定 pd.options.display.max_rows = 1000 pd.options.display.max_columns = 1000 %matplotlib inline |
多くの方の環境で「oandapy」と「pytz」は入っていないかと思います。oandapyですが、OANDA APIのPythonラッパーとなります。pytzはpythonのタイムゾーン関係の処理を行ってくれる便利なライブラリです。
両方ともpip経由でインストールが可能ですので、事前にインストールをしましょう。
ライブラリが無事に読み込めたら、次はAPI接続のための設定ファイルの読み込みを行いましょう。初めてOANDA APIを触る方は、APIの基本操作方法の記事を詳しくは参照してください。
1 2 3 4 5 6 7 |
# API接続のコンフィグを読み込み config = configparser.ConfigParser() config.read('../config/config_v1.txt') account_id = config['oanda']['account_id'] api_key = config['oanda']['api_key'] |
これでAPI接続の下準備が整いました。実際にAPIの呼び出しをしてみましょう。
1 2 3 4 |
# OANDA APIの呼び出し oanda = oandapy.API(environment="live", access_token=api_key) |
これでAPIへの接続が完了です。次のステップへ移る前に現在のドル円の価格をAPI経由で取得してみます。
1 2 3 4 5 |
# 今の時間をドル円レートを取得 res = oanda.get_prices(instruments="USD_JPY") res |
1 2 3 4 5 6 7 |
--出力 {'prices': [{'ask': 113.903, 'bid': 113.899, 'instrument': 'USD_JPY', 'time': '2018-11-13T13:55:08.391842Z'}]} |
大丈夫そうですね。では次のステップに移りましょう。
STEP3 大規模データを取得するための準備
今回は任意の期間のドル円の1分足をAPIから取得してPandasのデータフレーム形式へ落とし込む流れを行います。まずは「任意の期間」から設定していきましょう。
OANDA APIの時間ですがISO8601という形式が使われています。APIでは標準的な形式でUTCを基準として時間を表現する形式です。これが少し扱いづらいので厄介です。
APIから取得したレートの時間は全てUTC基準となります。ですので、データとして扱いやすいように日本時間への変換が必要です。まずはその関数を作ってあげましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# ISO8601から日本時間へ変換 def iso_jp(iso): date = None try: date = datetime.strptime(iso, '%Y-%m-%dT%H:%M:%S.%fZ') date = pytz.utc.localize(date).astimezone(pytz.timezone("Asia/Tokyo")) except ValueError: try: date = datetime.strptime(iso, '%Y-%m-%dT%H:%M:%S.%f%z') date = dt.astimezone(pytz.timezone("Asia/Tokyo")) except ValueError: pass return date.strftime('%Y/%m/%d %H:%M:%S') |
ちゃんとISO8601から日本時間へ変換されているのか確認してみましょう。改めてAPIから現在のレートを取得してiso_jpの関数を使ってみます。
1 2 3 4 5 |
# 今の時間を取得して時間を日本時間へ変換 res = oanda.get_prices(instruments="USD_JPY") iso_jp(res['prices'][0]['time']) |
1 2 3 4 |
--出力 '2018/11/13 23:05:36' |
上のコードの出力が今の時間になっていれば大丈夫です。
次はAPIリクエストを行うための「期間」を作りましょう。OANDA APIの1回のリクエストで取得できる最大数は5000レコードまでです。つまり、一度のリクエストで3日分の1分足を取得しようとすると上限に引っかかりエラーが発生します。
ですので、基本は5000件の最大取得制限を超えないように1日毎に1分足データをAPIから引き出す必要があるわけです。
加えてAPIにリクエストを投げた際に返すデータがないとエラーが発生します。1日毎にデータを取得しますので、当然期間からデータが存在しない週末を除外しなくてはいけません。これがドキュメントをみてもエラー詳細がのっておらず・・私が最初にやった時にハマりました。
ですので、最終日を指定して、1日毎日付をずらして、さらに週末を除外した日付のリストを作る必要があるのです。これの処理自体は簡単に行えるので書いちゃいましょう。
1 2 3 4 5 6 7 8 9 10 11 |
# 日付を1日毎ずらしてリストを作成 end = "2018-10-29T00:00:00.000000Z" end = datetime.strptime(end, '%Y-%m-%dT%H:%M:%S.%fZ') start = [] for i in range(300): end = end + timedelta(days=-1) weekday = end.weekday() if weekday < 5: start.append(end.isoformat()) |
ご覧の通りendには日付の最終日をISO8601形式で入力します。あとは1日ずつ引き算を行い、平日のみをリストに追加する流れです。上記のコードで300日分の日付を作成しています。念のため日付のデータサイズを確認してみましょう。
1 2 3 4 |
# 日付のデータサイズを確認 len(start) |
1 2 3 4 |
--出力 214 |
300日分と言いましたが、週末を除外しているので実際は300日より少ないのが正解です。この期間の処理が厄介でした。。この処理を書くのに30分以上戦いました(笑)
STEP4 大規模なドル円データを取得
いよいよ本題の処理です。OANDA APIに接続して大量の1分足データを取得してみましょう。下記のコードを見るとわかりますがinstには取得したい通貨ペアを記載します。今回はUSD_JPYとしています。
granはローソク足の長さです。M1は1分足です。10分足を取得したい場合はM10と変更するだけです。最後にlengthはどれくらい前に遡るかの日付を指定します。厳密にいうと週末は除外されてるのでぴったしの日付にはなりませんので注意しましょう。
では、やってみましょう!下記のコードですが、実行から完了まで数分程度かかりますのでご注意ください!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# ドル円1分足データを取得 inst = "USD_JPY" gran = "M1" data = pd.DataFrame([]) length = 100 for i in range(length): dic_api = oanda.get_history(instrument=inst, granularity=gran, start=start[i+1] + '.000000Z', end=start[i] + '.000000Z') temp = pd.DataFrame(dic_api['candles']) data = pd.concat([data, temp], axis=0).reset_index(drop=True) print(start[i+1], start[i]) |
1 2 3 4 5 6 7 8 9 10 |
--出力 2018-10-25T00:00:00 2018-10-26T00:00:00 2018-10-24T00:00:00 2018-10-25T00:00:00 ...中略... 2018-06-11T00:00:00 2018-06-12T00:00:00 2018-06-08T00:00:00 2018-06-11T00:00:00 |
上記の期間をみている限り、しっかり意図した期間で過去レートのデータを取得できているようです。また途中で飛んでいる日付を確認するとしっかり週末となっています。
では、APIから1分足のデータが何件取得できたのか確認してみましょう。
1 2 3 4 |
# 取得したデータのサイズを確認 data.shape |
1 2 3 4 |
--出力 (136179, 11) |
実に約13.6万件のドル円過去レートデータの取得ができました。機械学習を使ってFX予想をするのにデータが多いに越したことはありません。
STEP5 データの確認
最後に簡単に取得したデータの確認をしましょう。APIからのデータの時間(time)はISO8601形式ですので、まずは日本時間に変換してあげます。加えて確認しやすいように日付順にソートしてあげましょう。
1 2 3 4 5 6 |
# ISOから日本時間へ変更してdatatime型へ変換 data['time'] = data['time'].apply(lambda x: iso_jp(x)) data['time'] = pd.to_datetime(data['time']) data = data.sort_values(by='time') |
では、取得したデータを実際にみてみましょう。
1 2 3 4 |
# 10月5日〜6日のデータを表示 data[(data['time'] > '2018-10-05') & (data['time'] < '2018-10-06')].iloc[[0,1,2,873,874,875]] |
1 2 3 4 5 6 7 8 9 10 |
--出力 closeAsk closeBid complete highAsk highBid lowAsk lowBid openAsk openBid time volume 21670 113.740 113.727 True 113.742 113.729 113.716 113.704 113.721 113.706 2018-10-05 00:01:00 43 21671 113.750 113.737 True 113.757 113.743 113.742 113.729 113.742 113.729 2018-10-05 00:02:00 53 21672 113.757 113.745 True 113.761 113.748 113.744 113.732 113.747 113.734 2018-10-05 00:03:00 53 19816 113.906 113.895 True 113.916 113.903 113.904 113.892 113.912 113.897 2018-10-05 15:49:00 13 19817 113.904 113.892 True 113.909 113.896 113.902 113.889 113.909 113.896 2018-10-05 15:50:00 7 19818 113.920 113.908 True 113.922 113.909 113.901 113.889 113.901 113.889 2018-10-05 15:51:00 16 |
大丈夫そうですね!しっかり1分毎のドル円のデータが取得できているのが確認とれます。
まとめと次の課題
いかがでしたでしょうか?今回はOANDA FX APIを使って大規模なドル円の1分足のデータの取得の操作方法をまとめました。
機械学習はデータに始まり、データに終わります。訓練に使えるデータは多いに越したことはありません。日足や1時間足だと期間が長くてもデータの個数は限られますが、1分足や5秒足ともなると期間が長くなればなるほどデータは膨大に増えます。
この記事がFX機械学習トレーダーのお役に立てれば幸いです!
FXで機械学習を使うための初心者向けチュートリアルもまとめています!Pythonの初歩的な知識があれば実装が可能ですので、興味がある方は是非ご覧ください!
決定木を使ってFX予想をやってみる
FXトレードでロジスティック回帰を独自テクニカル指標として活用する方法
ブログ読んでいただきありがとうございます!Twitterでも色々と発信しているので、是非フォローお願いします!
*2018年11月19日 誤字脱字の訂正を行いました
ディスカッション
コメント一覧
いつも更新を楽しみにしています。
恐れ多くも記事中の誤字脱字の指摘をさせていただきたく存じます
OANDA APIの時間ですがISO8601という形式が使われています。から始まる段落の文末
れが少し扱いづらいので厄介です。
という一文において、文頭に「こ」が抜けているかとおもわれます。
また、その下の段落の「…データに間違えが内容に…」は「…データに間違いが無いように…」だと思われます
また、まとめにある「…データは大いに越したことは…」は「…データは多いに越したことは…」だと思われます
ぱおさん、ご指摘ありがとうございます!誤字脱字…恥ずかしい限りです…。修正いたしました!
週末を除外、のあたり、
pandas date_range freq
でぐぐると幸せになれるかも