【Python】OANDA APIを使ってFX(為替)データを取得

FX投資
https://fxwalker.com/fx-co/oanda/
この記事は約14分で読めます。

PythonとOANDA APIを使ってFX(為替)データを取得

副収入を得るためにFXを始めたりすると、最終的にたどり着くところは、FXの自動売買かなと思います。すでに用意された自動売買のアルゴリズムも存在しますが、自分でデータを分析して、そのアルゴリズムを元に自動売買させたいという願望も出てくると思います。

さらには、昨今流行りのディープラーニングを用いて過去データを学習させて自動売買なんてこともやりたくなると思います。ディープラーニングを用いようと思うとpythonが使いたいということにもなります。

OANDAのpython APIはv1とv20の2つが存在するのですが、v1は自動売買をしようとしたときに両建てができないので、v20にしたほうが良いと思います。
ただ、最近までOANDA JAPANはv1しか使用できなかったため、v20の日本語の解説がけっこう少ないというのがやや難点ではあります。私のブログが多少でも役に立てばと思います。

OANDAへの登録は以下のリンクから登録可能です。

OANDA APIによるFX(為替)データ取得コード

モジュールのインポート

まずはモジュールのインポートです。
from oandapyV20.contrib.factories import InstrumentsCandlesFactoryの部分がoandapyV20の過去データを取得するためのモジュールになります。

from oandapyV20 import API
from oandapyV20.contrib.factories import InstrumentsCandlesFactory
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
import tqdm

パラメータの設定

token = 'xxxxxx'
instrument = "USD_JPY"
granularity = "H4"
start_day = datetime(2019, 1, 1)
end_day = datetime(2019, 5, 1)
start = datetime.strftime(start_day, '%Y-%m-%dT%H:%M:%SZ')
end = datetime.strftime(end_day, '%Y-%m-%dT%H:%M:%SZ')

params = {
        "from": start,
        "to": end,
        "granularity": granularity
        }

‘xxxxxx’の部分に、自分で取得したOANDAのtokenを書きます。
instrumentには通貨ペア、granularityにローソク足の種類を設定します。
start_day, end_dayに取得したいデータの開始日と終了日を設定するようにします。
start_day, end_dayはdatetime関数で、APIが使える文字列の形式に変換します。
(最初から’%Y-%m-%dT%H:%M:%SZ’の形式で文字列を書いても良いです。ここでは、あとで引き算などしたいと思ったので、このようにしています。)

oandapyV20のmethodを使ってFX(為替)データを取得

client = API(access_token=token)
res = []            
for r in InstrumentsCandlesFactory(instrument=instrument,params=params):
    client.request(r)
    res.extend(r.response.get('candles'))

先程設定したtokenを引数にいれ、APIというmethodでclientインスタンスを作ります。
あとは、上記のようにfor文の形式で書くことで、resリストにどんどん結果を取得することができます。取得したresリストを表示すると以下のように4時間毎のデータが辞書形式で入っていることがわかります。

[{'complete': True,
  'mid': {'c': '109.598', 'h': '109.726', 'l': '109.533', 'o': '109.590'},
  'time': '2019-01-01T22:00:00.000000000Z',
  'volume': 2616},
 {'complete': True,
  'mid': {'c': '109.304', 'h': '109.613', 'l': '109.299', 'o': '109.600'},
  'time': '2019-01-02T02:00:00.000000000Z',
  'volume': 2710},
 {'complete': True,
  'mid': {'c': '108.943', 'h': '109.348', 'l': '108.710', 'o': '109.302'},
  'time': '2019-01-02T06:00:00.000000000Z',
  'volume': 6642},
 {'complete': True,
  'mid': {'c': '109.191', 'h': '109.284', 'l': '108.822', 'o': '108.946'},
  'time': '2019-01-02T10:00:00.000000000Z',
  'volume': 6613},
 {'complete': True,
  'mid': {'c': '109.442', 'h': '109.464', 'l': '109.177', 'o': '109.189'},
  'time': '2019-01-02T14:00:00.000000000Z',
  'volume': 7780}]

pandasデータフレームへの変換

辞書形式のデータはやや扱いづらいので、pandasのデータフレームへ変換します。

TIME = [i['time'][:-11] for i in response]
CLOSE = [i['mid']['c'] for i in response]
HIGH = [i['mid']['h'] for i in response]
LOW = [i['mid']['l'] for i in response]
OPEN = [i['mid']['o'] for i in response]
VOLUME = [i['volume'] for i in response]
data = [TIME,CLOSE,HIGH,LOW,OPEN,VOLUME]
col = ['time','close','high','low','open','volume']
df = pd.DataFrame(columns = col)
for i,v in enumerate(df):
    df[v] = data[i]

dfを表示する以下のようなデータフレームが無事得られていると思います。

まとめコード

以上のコードをまとめて書いておきます。
これでひとまずデータは取得できたので、今後は書籍の内容を分析していきたと思います。

from oandapyV20 import API
from oandapyV20.contrib.factories import InstrumentsCandlesFactory
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
import tqdm

instrument = "USD_JPY"
granularity = "H4"
start_day = datetime(2019, 1, 1)
end_day = datetime(2019, 5, 1)
start = datetime.strftime(start_day, '%Y-%m-%dT%H:%M:%SZ')
end = datetime.strftime(end_day, '%Y-%m-%dT%H:%M:%SZ')

params = {
        "from": start,
        "to": end,
        "granularity": granularity
        }
res = []            
for r in InstrumentsCandlesFactory(instrument=instrument,params=params):
    client.request(r)
    res.extend(r.response.get('candles'))

TIME = [i['time'][:-11] for i in response]
CLOSE = [i['mid']['c'] for i in response]
HIGH = [i['mid']['h'] for i in response]
LOW = [i['mid']['l'] for i in response]
OPEN = [i['mid']['o'] for i in response]
VOLUME = [i['volume'] for i in response]
data = [TIME,CLOSE,HIGH,LOW,OPEN,VOLUME]
col = ['time','close','high','low','open','volume']
df = pd.DataFrame(columns = col)
for i,v in enumerate(df):
    df[v] = data[i]

参考(クラス化&進捗バー)

上記のコードでも問題ないのですが、10年分くらいの長期間の分足などを取得しようとすると進捗が見えないといつ終わるのかわからないので、進捗バーなどほしいかと思います。あと、後々の使いやすさも考えてクラス化などしたほうが良いんかなと思います。参考までにクラス化させて進捗バーを追加したコードを載せておきます。

from oandapyV20 import API
from oandapyV20.contrib.factories import InstrumentsCandlesFactory
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
import tqdm

token = 'xxxxxx'
client = API(access_token=token)
class Fetcher(object):
    def fetch(self,instrument,granularity,start_day,end_day):
        nth = 0
        delta_day = (end_day - start_day)
        divider = 100
        mod = timedelta(int(np.ceil(delta_day.days/divider)))
        bar = tqdm.tqdm(range(divider))

        res = []
        while start_day + mod * nth < end_day: #取得期間をdividerで分割した数に応じて繰り返す
            start = datetime.strftime(start_day + mod * nth, '%Y-%m-%dT%H:%M:%SZ') #分割した取得期間の開始日
            end = datetime.strftime(min(start_day + mod * (nth + 1), end_day), '%Y-%m-%dT%H:%M:%SZ') #分割した取得期間の終了日
            
            #oanda API用のparams設定
            params = {
                "from": start,
                "to": end,
                "granularity": granularity
                }

            #oanda APIによる過去データの取得
            for r in InstrumentsCandlesFactory(instrument=instrument,params=params):
                client.request(r)
                res.extend(r.response.get('candles'))

            #responseの形式をpandas DataFrameに変換
            TIME = [i['time'][:-11] for i in response]
            CLOSE = [i['mid']['c'] for i in response]
            HIGH = [i['mid']['h'] for i in response]
            LOW = [i['mid']['l'] for i in response]
            OPEN = [i['mid']['o'] for i in response]
            VOLUME = [i['volume'] for i in response]
            data = [TIME,CLOSE,HIGH,LOW,OPEN,VOLUME]
            col = ['time','close','high','low','open','volume']
            df = pd.DataFrame(columns = col)
            for i,v in enumerate(df):
                df[v] = data[i]

            #データフレームのpickle保存
            df.to_pickle('{}_{}_{}-{}.pickle'.format(\
                instrument,granularity,start_day.strftime('%Y%m%d'),end_day.strftime('%Y%m%d')))

            #進捗バーの表示
            bar.set_description("Get {} ~ {}".format(start, end))
            bar.update(1)
            nth += 1
        
if __name__ == "__main__":
    instrument = "USD_JPY"
    granularity = "H4"
    start_day = datetime(2010, 1, 1)
    end_day = datetime(2019, 5, 1)
    fet = Fetcher()    
    fet.fetch(instrument,granularity,start_day,end_day)

コメント

  1. ducker より:

    大変参考になりました。ありがとうございます。

タイトルとURLをコピーしました