HistData.comのヒストリカルデータをMT5にインポートしてみる。
先ずHistData.comからヒストリカルデータを手動でダウンロードするが、データをインポート用のファイルに変換するためにPythonを使っている。
HistData.comは有志のトレーダーによって運営されており、FXを中心に、株価指数や商品のヒストリカルデータを無料、無登録でダウンロードできる。
ただ、データの信頼性は不明である。
基準時間や夏時間の有無なども個々のデータで確認したほうがいい。
HistData.comのホームページ:https://www.histdata.com/
MT4/5用のヒストリカルデータ(1分足):https://www.histdata.com/download-free-forex-data/?/metatrader/1-minute-bar-quotes
環境
ヒストリカルデータのダウンロード
今回は例として日経225のヒストリカルデータのダウンロード、インポート用ファイルへの変換、インポート用ファイルのインポートをしてみる。
①以下のアドレスをクリックする。
https://www.histdata.com/download-free-forex-data/?/metatrader/1-minute-bar-quotes
②「JPX/JPY(2010/November)」をクリックする。
これが日経225である。
他の銘柄でも同様だと思うが、最新年のデータは1か月ごと、それ以外は1年ごとになっている。面倒臭いが、一つ一つダウンロードする。
ここでは2010年から2024年2月までのデータをダウンロードする。ファイルはすべてzipファイルである。
ここでは、ダウンロードしたファイルは
C:\Users\****\Downloads\JPXJPY
に保存しているとする。
インポート用ファイルへの変換
①Spyderを起動する。
別にSpyderでなくてもよいが、インポート用ファイルの変換にはPyhtonを使う。なお、SpyderとはPython用のIDEである。
②IPythonコンソールに以下のコードをコピー&ペーストして「Enter」キーを押す。
import pandas as pd import shutil from datetime import timedelta symbol = 'JPXJPY' # 銘柄 start_year = 2010 # 開始年 end_month = 2 # 2024年の終了月 tick_vol = 15 # ティックボリューム。小さすぎるとヒストリー品質が悪くなる spread = 50 # スプレッド add_hour = 7 # 時間調整として加える時間 use_summer_time = True # 夏時間を適用するか否か download_folder = 'C:\\Users\\****\\Downloads\\JPXJPY' # ダウンロード・フォルダー # 2024年の各月のzipファイルを解凍する for i in range(1,end_month+1): if(i<10): shutil.unpack_archive(download_folder+'\\HISTDATA_COM_MT_'+symbol+ '_M120240'+str(i)+'.zip', download_folder) else: shutil.unpack_archive(download_folder+'\\HISTDATA_COM_MT_'+symbol+ '_M12024'+str(i)+'.zip', download_folder) # 2024年の各月のcsvファイルを読み込んでデータを結合する data = pd.DataFrame() for i in range(1,end_month+1): if(i<10): temp = pd.read_csv(download_folder+'\\DAT_MT_'+symbol+'_M1_20240'+ str(i)+'.csv', header=None) else: temp = pd.read_csv(download_folder+'\\DAT_MT_'+symbol+'_M1_2024'+ str(i)+'.csv', header=None) data = pd.concat([data, temp]) # データを年月日の行(0)を最優先、時間の行(1)をその次で並べ替える data = data.sort_values([0,1]) # データを2024年のcsvファイルとして出力する data.to_csv(download_folder+'\\DAT_MT_'+symbol+'_M1_2024.csv', index=False, header=False) # 2023年以前のzipファイルを解凍する for i in range(start_year,2024): shutil.unpack_archive(download_folder+'\\HISTDATA_COM_MT_'+symbol+ '_M1'+str(i)+'.zip', download_folder) # 2023年以前と2024年のcsvファイルを読み込んでデータを結合する data = pd.DataFrame() for i in range(start_year,2025): temp = pd.read_csv(download_folder+'\\DAT_MT_'+symbol+'_M1_'+str(i)+'.csv', header=None) data = pd.concat([data, temp]) # データを年月日の行(0)を最優先、時間の行(1)をその次で並べ替える data = data.sort_values([0,1]) # データに7と8の列を加える temp = pd.DataFrame(columns=[7,8]) data = pd.concat([data, temp], axis=1) # 列名を変更する data.columns = ['<DATE>','<TIME>','<OPEN>','<HIGH>','<LOW>','<CLOSE>', '<TICKVOL>','<VOL>','<SPREAD>'] # ティックボリューム、数量、スプレッドの列を埋める data['<TICKVOL>'] = tick_vol data['<VOL>'] = 0 # 数量は0でいい data['<SPREAD>'] = spread # 時間を調整する。必要あれば夏時間を適用する dt = data['<DATE>']+' '+data['<TIME>'] dt = pd.to_datetime(dt) dt = dt + timedelta(hours=add_hour) if(use_summer_time==True): # 頭の悪いやり方だが… s10 = (dt>=pd.to_datetime('2010-03-14')) & (dt<pd.to_datetime('2010-11-07')) s11 = (dt>=pd.to_datetime('2011-03-13')) & (dt<pd.to_datetime('2011-11-06')) s12 = (dt>=pd.to_datetime('2012-03-11')) & (dt<pd.to_datetime('2012-11-04')) s13 = (dt>=pd.to_datetime('2013-03-10')) & (dt<pd.to_datetime('2013-11-03')) s14 = (dt>=pd.to_datetime('2014-03-09')) & (dt<pd.to_datetime('2014-11-02')) s15 = (dt>=pd.to_datetime('2015-03-08')) & (dt<pd.to_datetime('2015-11-01')) s16 = (dt>=pd.to_datetime('2016-03-13')) & (dt<pd.to_datetime('2016-11-06')) s17 = (dt>=pd.to_datetime('2017-03-12')) & (dt<pd.to_datetime('2017-11-05')) s18 = (dt>=pd.to_datetime('2018-03-11')) & (dt<pd.to_datetime('2018-11-04')) s19 = (dt>=pd.to_datetime('2019-03-10')) & (dt<pd.to_datetime('2019-11-03')) s20 = (dt>=pd.to_datetime('2020-03-08')) & (dt<pd.to_datetime('2020-11-01')) s21 = (dt>=pd.to_datetime('2021-03-14')) & (dt<pd.to_datetime('2021-11-07')) s22 = (dt>=pd.to_datetime('2022-03-13')) & (dt<pd.to_datetime('2022-11-06')) s23 = (dt>=pd.to_datetime('2023-03-12')) & (dt<pd.to_datetime('2023-11-05')) s24 = (dt>=pd.to_datetime('2024-03-10')) & (dt<pd.to_datetime('2024-11-03')) s = (s10 | s11 | s12 | s13 | s14 | s15 | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24) dt = dt + timedelta(hours=1) * s date = dt.dt.strftime('%Y.%m.%d') time = dt.dt.strftime('%H:%M') data['<DATE>'] = date data['<TIME>'] = time # データを全期間のcsvファイルとして出力する data.to_csv(download_folder+'\\'+symbol+'.csv', index=False)
現時点で最新年は2024年である。
上のコードは最新年が変わるたびに修正する必要がある。
コードのコメントでも説明しているが、いくつか補足する。
ティックボリューム
ティックボリュームは小さすぎるとヒストリー品質が悪くなる。
ティックボリュームが0だとインポートのときにエラーになるので、とりあえず1にしたところ、ヒストリー品質が10%程度になってしまった。
考えてみると、ティックボリュームとは価格の変化の回数をカウントしているのであるから、ティックボリュームが1ということは価格変化が1回しかなかったことになる。となると、始値、高値、安値、終値がすべて同じになるかもしれない。このためにヒストリー品質が低くなったのではないだろうか。
OANDAで日経225に相当するJP225では、ティックボリュームは平均して15くらいなので、ここでは15と設定した。すると、ヒストリー品質は99%になった。
もしかすると、ヒストリー品質とは
ヒストリー品質 = 1分足の本数 * ティックボリューム / MT5が期待するティックボリュームの総数 * 100
という計算式で算出されるものなのかもしれない。
ついでに書くと、バックテストのモデルに全ティックというのがあるが、もしティックボリュームが100だったら、それに合わせて100個分のデータを生成するのではないだろうか。
もしそうだとすると、全ティックでバックテストした場合、ティックボリュームが多いほど、価格変化の回数が多くなり、価格変化の大きさは小さく滑らかになるので、パフォーマンスに若干影響するかもしれない。
スプレッド
HistData.comのヒストリカルデータにはスプレッドの情報がなく、0になってしまう。
MT4、MT5両方で使えるようにサイトでは説明されているが、基本的にはMT4用と考えたほうがよさそうだ。
MT5でスプレッドの情報がないのは困るので、やはりJP225を参考にし、スプレッドを50ポイントとして設定した。
時間調整と夏時間の適用
JPXJPYの時間を調べてみると、米国東部時間が使われているようである。
一方、OANDAのMT5はニューヨーク・クロージングを基準にしている。ニューヨーク・クロージングは米国東部時間より7時間進んだ時間だ。
つまり、JPXJPYの時間はニューヨーク・クロージングより7時間遅れている。
そこで、上のコードでは7時間進ませてニューヨーク・クロージングと一致するように時間を調整した。
また、JPXJPYの時間は夏時間が適用されていないようである。米国東部時間を使いながら夏時間を適用しないのは謎だが、このため、米国が夏時間になると、JPXJPYの時間は1時間遅れてしまう。
そこで、上のコードでは夏時間を適用させ、米国が夏時間のときに1時間進ませて、ずれがないようにした。
夏時間の判定の仕方は力業で頭の悪いやり方だが、とりあえずこのまま。
なお、私が確認した範囲では
JPXJPY(日経平均):米国東部時間、夏時間適用なし SPXUSD(S&P500):米国東部時間、夏時間適用なし XAUUSD(金):米国東部時間、夏時間適用あり WTIUSD(原油):米国東部時間、夏時間適用あり
のようである。必ずしも統一されていないので、注意が必要だ。
上のコードを実行すると、ダウンロードしたファイルを保存していた
C:\Users\****\Downloads\JPXJPY
に「JPXJPY.csv」ファイルが生成する。これがインポート用ファイルである。
インポート用ファイルのインポート
では、作成したインポート用ファイルをMT5にインポートする。
①MT5のメニューバーで「表示」をクリックする。
②「銘柄」をクリックする。
以下のabcはやらなくてもよいが、やれる環境にあればやっておくと便利。
JPXJPYはOANDAではJP225に相当する銘柄である。
abcをやっておくと、JPXJPYというカスタム銘柄を作成するに当たり、設定がJP225と同じになる。
その方が便利なので、後は必要にしたがって設定を修正すればいい。
「銘柄」で「仕様」タブをクリックする。
「OJ_Index」をクリックする。
「JP225」をクリックする。
③「銘柄」で「カスタム銘柄を作成する」をクリックする。
④「カスタム銘柄」で「銘柄」の行をダブルクリックする。
上のabcをやっている場合、「銘柄」の行は「JP225」になっているだろう。
⑤「JPXJPY」に変更する。
⑥真ん中やや下までスクロールし、「買いスワップ」と「売りスワップ」を「0」に変更する。
abcをやっている場合、「買いスワップ」と「売りスワップ」にある数値はたまたま、今この作業をしているときのJP225の数値にすぎず、これは日々変動するものだ。
ここではスワップは生じないものとして0にしておく。
⑦「YES」ボタンをクリックする。
⑧「銘柄」に戻って「チャートバー」タブをクリックする。
⑨銘柄を「JPXJPY」にする。
⑩「バーをインポートする」ボタンをクリックする。
⑪「レートをインポートします: JPXJPY」で「ファイル」の右にある「選択」ボタンをクリックする。
⑫「JPXJPY.csv」ファイルを選択して「開く」ボタンをクリックする。
⑬「区切り文字」で「,」を選択する。
HistData.comのファイルは「,」で区切っているようだ。ちなみにMT5内に元からあるヒストリカルデータだと「tab」で区切られているようだ。
⑭「スキップ」で「列」、「行」ともに「0」を選択する。
⑮「時差調整」で「0」を選択する。
⑯「ティックボリューム」でチェックを入れる。
⑰「YES」ボタンをクリックする。
⑱「銘柄」に戻り、インポートが終わったら「OK」ボタンをクリックする。