MT5のcandleデータをPythonのライブラリpandasのDataframeに取り込む方法について
使用するライブラリ
python3.9を使用しています。
pandasとMetaTrader5というPythonのライブラリを使います。
■padas
DatarameというExcelのようにデータを扱えるクラスが使えます。ですが、Excelよりも断然使いやすいです。
install方法pip install pandas
■MetaTrader5
MT5にPythonでアクセスするためのライブラリです。
install方法
pip install MetaTrader5
詳細
MetaTrader5のイニシャライズ
import MetaTrader5 as mt5
class Mt5Terminal:
def __init__(self):
ok = False
for i in range(120):
if mt5.initialize(path=r"C:\\Program Files\\OANDA MetaTrader 5\\terminal64.exe"):
ok = True
break
else:
print("initialize() failed, error code =", mt5.last_error())
time.sleep(60)
if not ok:
raise Exception("initialize() failed, error code =", mt5.last_error())
MT5を起動し、アカウント情報を設定して、通貨ペアのローソク足が確認できる状態にしておきます。
mt5.initialize()のパラメータに”MT5のterminal64.exeの場所”を指定して、callします。MT5に接続できない時もありますので、その場合はMT5を起動しなおしたり、Windowsを再起動するとうまくいくことがあります。
Summer Timeの計算
“夏時間、冬時間を計算”の投稿に記載しています。
MT5からcandleデータを取得してDataframeにする
最新位置から取得個数指定
# イニシャライズのコードに記載したclass Mt5Terminal:の続きです
@property
def zonemt5(self):
#GMT+2(夏時間の場合はGMT+3)
jst_time = datetime.datetime.now(tz=JST)
# jst_time = datetime.datetime.now()
if is_summer_time(jst_time):
return datetime.timedelta(hours=3)
else:
return datetime.timedelta(hours=2)
def _convert_timerate_granularity_to_mt5(self, granularity):
ret_timerate = None
if granularity == 'M1':
ret_timerate = mt5.TIMEFRAME_M1
elif granularity == 'M2':
ret_timerate = mt5.TIMEFRAME_M2
elif granularity == 'M3':
ret_timerate = mt5.TIMEFRAME_M3
elif granularity == 'M5':
ret_timerate = mt5.TIMEFRAME_M5
elif granularity == 'M15':
ret_timerate = mt5.TIMEFRAME_M15
elif granularity == 'M30':
ret_timerate = mt5.TIMEFRAME_M30
elif granularity == 'H1':
ret_timerate = mt5.TIMEFRAME_H1
elif granularity == 'H4':
ret_timerate = mt5.TIMEFRAME_H4
elif granularity == 'H6':
ret_timerate = mt5.TIMEFRAME_H6
elif granularity == 'D':
ret_timerate = mt5.TIMEFRAME_D1
elif granularity == 'W':
ret_timerate = mt5.TIMEFRAME_W1
elif granularity == 'M':
ret_timerate = mt5.TIMEFRAME_MN1
else:
raise Exception("ERROR:unsupport:",granularity)
return ret_timerate
def get_candle_from(self, symbol, granularity, count=2000, past_idx=0):
'''
:param symbol: ドル円の場合"USDUPY"
:param granularity: 五分足の場合"M5"
:param count: 取得数
:param past_idx: 取得開始index indexは現在から過去になるほど増える 現在が0
:return:
'''
UTC = datetime.timezone.utc
JST = datetime.timezone(datetime.timedelta(hours=+9), 'JST')
timerate = self._convert_timerate_granularity_to_mt5(granularity)
rates = mt5.copy_rates_from_pos(symbol, timerate, past_idx, count)
rates_frame = pd.DataFrame(rates)
try:
rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s')
except Exception as e:
print("ERROR: get_candle_from", symbol, granularity, count, datetime.datetime.now())
raise e
rates_frame.loc[:, 'time'] = rates_frame.time - self.zonemt5 #mt5時間対応
df = rates_frame.set_index('time')
df = df.tz_localize(UTC).tz_convert(JST)
if 'volume' not in df.columns:
if 'tick_volume' in df.columns:
df = df.rename(columns={'tick_volume': 'volume'})
return df
get_candle_from()ローソク足をDataframeに変換して返します。
パラメータpast_idxは最新のデータを取得する場合は0を指定して、1,2と増えるとその分過去の値を最後の値として、パラメータcountの数ローソク足を取得します。
_convert_timerate_granularity_to_mt5()で、”M5″などを、MetaTrader5用のパラメータに変換します。
取得したデータをDataframeに変換
rates_frame = pd.DataFrame(rates)
秒での時間をdatetime形式に変換する
rates_frame[‘time’] = pd.to_datetime(rates_frame[‘time’], unit=’s’)
MT5は夏時間は3時間、冬時間は2時間UTCからずれているのでその分を補正し、
rates_frame.loc[:, ‘time’] = rates_frame.time – self.zonemt5 #mt5時間対応
時刻データをDataframeのindexに
df = rates_frame.set_index(‘time’)
UTCをJSTに変換します。
df = df.tz_localize(UTC).tz_convert(JST)
volumeはtick_volumeとして格納されるので、volumeに変更します。
if 'volume' not in df.columns:
if 'tick_volume' in df.columns:
df = df.rename(columns={'tick_volume': 'volume'})
取得間隔指定
時間指定の場合は特にタイムゾーンを意識する必要があります。タイムゾーンはイギリスが中心で日本は+9時間、MT5は夏は+3時間、冬は+2時間ずれます。
MetaTrader5のpythonライブラリの公式サイトでは、utc時間でローソク足が取れるように記載されていますが、実際にやってみるとそうではなく、utc時間より夏は+3時間、冬は+2時間ずらした値を引数にする必要がありました。
def get_candle_from_to(self, symbol, granularity, time_from, time_to):
'''
ローソク足をfromからtoまで取得
:param symbol:
:param granularity:
:param time_from:
:param time_to:
:return:
'''
if time_to is None:
time_to = datetime.datetime.now(tz=UTC)
timerate = self._convert_timerate_granularity_to_mt5(granularity)
mt5_from = self._tz_del(time_from) + self.zonemt5
mt5_to = self._tz_del(time_to) + self.zonemt5
rates = mt5.copy_rates_range(symbol, timerate, mt5_from, mt5_to)
rates_frame = pd.DataFrame(rates)
rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') - self.zonemt5
rates_frame = rates_frame.copy()
rates_frame['time'] = rates_frame.time
df = rates_frame.set_index('time')
df = df.tz_localize(UTC).tz_convert(JST)
if 'volume' not in df.columns:
if 'tick_volume' in df.columns:
df = df.rename(columns={'tick_volume': 'volume'})
return df
get_candle_from_to()メソッドは、パラメータの時刻から一旦タイムゾーン情報を破棄し、MT5時間(夏は+3時間、冬は+2時間)を足しています。
mt5_from = self._tz_del(time_from) + self.zonemt5
mt5_to = self._tz_del(time_to) + self.zonemt5
_tz_del()は、以下のように時刻データの型を見て、データ形式に合わせてUTC時刻に変換しています。
サポートできていない方もあるとは思いますが、よく使用されそうなものは大抵これで処理可能だと思います。
def _tz_del(self, tgt_time):
if tgt_time is not None:
if type(tgt_time) is datetime.datetime:
if tgt_time.tzinfo == UTC:
pass
elif tgt_time.tzinfo is None:
tgt_time = tgt_time.replace(tzinfo=UTC)
elif str(tgt_time.tzinfo).startswith('UTC') or str(tgt_time.tzinfo).startswith('MT5'):
tgt_time = tgt_time.astimezone(UTC)
elif tgt_time.tzinfo is not None and (tgt_time.tzinfo == JST or tgt_time.tzinfo.zone == 'Asia/Tokyo'):
tgt_time = tgt_time.astimezone(UTC)
else:
raise Exception(tgt_time)
elif type(tgt_time) is pd.Timestamp:
if tgt_time.tzinfo == UTC:
pass
else:
tgt_time = tgt_time.tz_convert(UTC)
tgt_time = tgt_time.to_pydatetime()
elif type(tgt_time) is np.datetime64:
tgt_time = pd.to_datetime(tgt_time, unit='s')
tgt_time = tgt_time.tz_localize(UTC)
tgt_time = tgt_time.to_pydatetime()
else:
print(type(tgt_time))
raise Exception(tgt_time)
return tgt_time
MetaTrader5ライブラリを使用しMT5からロウソク足データを取得します。
このあたりのデータ変換処理はget_candle_from()と同じなので説明を省きますが、
取得したデータはMT5の時刻((夏は+3時間、冬は+2時間))ですので、UTCになるようにずらしてさらに日本時間JSTに変換しています。これでDatetimeのindexは日本時間になります。
rates = mt5.copy_rates_range(symbol, timerate, mt5_from, mt5_to)
rates_frame = pd.DataFrame(rates)
rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s') - self.zonemt5
rates_frame = rates_frame.copy()
rates_frame['time'] = rates_frame.time
df = rates_frame.set_index('time')
df = rates_frame.set_index('time')
df = df.tz_localize(UTC).tz_convert(JST)
以上です。
プログラムはGithubに置いています。
コメント