[Python3]MT5에서 데이터를 가져와 close와 200EMA와 볼리반을 그리기

머리



Python3과 MT5를 연동시켜 자동매매 시스템을 만들고 싶었기 때문에, 완성까지 걸리는 공수를 근사하기 위해 조금 손을 움직였습니다.
일단 움직이게 한 상태이므로 코드는 전혀 정리되어 있지 않습니다.
향후 완성시킬지 어떨지는 미정입니다만, 현시점의 더러운 코드에서도 누군가의 도움이 될지도 생각해 기사로 했습니다.

환경


  • Visual Studio Code Version: 1.57.0
  • Python3.8.6
  • numpy: 1.20.3
  • pandas: 1.1.3
  • TA-Lib: 0.4.20
  • pip: 21.1.2
  • MetaTrader5: 5.0.33
  • matplotlib: 3.3.2

  • 그리기 결과




    그림 1: 그리기 직후

    그림 2: 그림 1의 왼쪽 위 그림의 사각형 선택 부분을 확대. 다른 2개의 그림에 관해서도 같은 부분을 확대.

    그림 3: 그림 2의 왼쪽 위 그림의 사각형 선택 부분을 확대. 다른 2개의 그림에 관해서도 같은 부분을 확대.

    그림 4: 그림 3의 왼쪽 위 그림의 사각형 선택 부분을 확대. 다른 2개의 그림에 대해서는 그림 3에서 변화 없음.

    소스 코드


    import MetaTrader5 as mt5
    from datetime import datetime
    from pytz import timezone
    import numpy as np
    import pandas as pd
    import talib as ta
    import matplotlib.pyplot as plt
    
    def filterColumns(rates, dict_columns):
        """
        必要なカラムのみに絞り込む
    
        Parameters
        ---------
        rates : numpy.ndarray | pandas.DataFrame
            MT5から読み込んだデータ
        dict_columns : dictionary
            必要なカラム
            {置換前のカラム名1:置換後のカラム名1, 置換前のカラム名2:置換後のカラム名2, ...}
    
        Returns
        ---------
        df_rates : pandas.DataFrame
            必要なカラムのみに絞ったDataFrame
        """
        df_rates = pd.DataFrame(rates)
        df_rates['time'] = pd.to_datetime(df_rates['time'], unit='s')
        df_rates = df_rates.rename(columns=dict_columns)
        return_columns = ['time'] + list(dict_columns.values())
        return df_rates.loc[:, return_columns]
    
    utc_tz = timezone('UTC')
    pd.set_option('max_row', None)
    
    ###########################
    # MT5からデータを取得
    ###########################
    mt5.initialize()
    EURJPY_D1_rates = mt5.copy_rates_range("GBPUSD", mt5.TIMEFRAME_D1, datetime(2019,6,12,0), datetime(2021,6,12,0))
    EURJPY_H4_rates = mt5.copy_rates_range("GBPUSD", mt5.TIMEFRAME_H4, datetime(2019,6,12,0), datetime(2021,6,12,0))
    EURJPY_H1_rates = mt5.copy_rates_range("GBPUSD", mt5.TIMEFRAME_H1, datetime(2019,6,12,0), datetime(2021,6,12,0))
    mt5.shutdown()
    
    ###########################
    # テクニカルデータの作成とデータの整形
    ###########################
    # D1
    # MT5から読み込んだデータをpandasのDataFrame型に変換
    df_EURJPY_D1_rates = pd.DataFrame(EURJPY_D1_rates)
    # TA-Libを使用して200EMAの値を算出し、DataFrameの新規カラムとして追加
    df_EURJPY_D1_rates['ema'] = ta.EMA(df_EURJPY_D1_rates.close, timeperiod=200)
    # 必要なカラムのみに絞り込み
    df_EURJPY_D1_rates = filterColumns(df_EURJPY_D1_rates, {'close':'D1_close', 'ema':'D1_200ema'})
    
    # H4
    df_EURJPY_H4_rates = pd.DataFrame(EURJPY_H4_rates)
    df_EURJPY_H4_rates['ema'] = ta.EMA(df_EURJPY_H4_rates.close, timeperiod=200)
    df_EURJPY_H4_rates['upper_band'], df_EURJPY_H4_rates['middle_band'], df_EURJPY_H4_rates['lower_band'] = ta.BBANDS(df_EURJPY_H4_rates.close, timeperiod=20)
    df_EURJPY_H4_rates = filterColumns(df_EURJPY_H4_rates, {'close':'H4_close', 'ema':'H4_200ema', 'upper_band':'H4_20band_upper', 'middle_band':'H4_20band_middle', 'lower_band':'H4_20band_lower'})
    
    # H1
    df_EURJPY_H1_rates = pd.DataFrame(EURJPY_H1_rates)
    df_EURJPY_H1_rates['ema'] = ta.EMA(df_EURJPY_H1_rates.close, timeperiod=200)
    df_EURJPY_H1_rates['upper_band'], df_EURJPY_H1_rates['middle_band'], df_EURJPY_H1_rates['lower_band'] = ta.BBANDS(df_EURJPY_H1_rates.close, timeperiod=20)
    df_EURJPY_H1_rates = filterColumns(df_EURJPY_H1_rates, {'close':'H1_close', 'ema':'H1_200ema', 'upper_band':'H1_20band_upper', 'middle_band':'H1_20band_middle', 'lower_band':'H1_20band_lower'})
    
    # H1のデータに対して右からH4, D1の順で日時データをキーとして結合
    df_EURJPY_H4_D1_rates = pd.merge(df_EURJPY_H4_rates, df_EURJPY_D1_rates, on='time', how='outer')
    df_EURJPY_H1_H4_D1_rates = pd.merge(df_EURJPY_H1_rates, df_EURJPY_H4_D1_rates, on='time', how='outer')
    
    ###########################
    # 4650~4750行目を表示
    # - 4686行目以前はデータが足りないためD1_200emaのデータは作られていない
    ###########################
    print('\n---------------------------')
    print('- GBPUSD rates')
    print('- length: ', len(df_EURJPY_H1_H4_D1_rates))
    print('---------------------------')
    print(df_EURJPY_H1_H4_D1_rates[4650:4750])
    
    # TODO H1がNaNとなる原因を調査する
    # TODO H1がNaNとなっている行だけ日付順に並んでおらず、結合後のDataFrameの最後に纏められてしまう原因を調査する
    # TODO H1がNaNの行は削除する
    
    # CSVに出力
    df_EURJPY_H1_H4_D1_rates.to_csv('20210613_0504.csv')
    
    ###########################
    # チャートの描画設定
    ###########################
    fig = plt.figure()
    
    ax1 = fig.add_subplot(221)
    ax2 = fig.add_subplot(222)
    ax3 = fig.add_subplot(223)
    
    ax1.plot(df_EURJPY_H1_rates.loc[:,'time'], df_EURJPY_H1_rates.loc[:,'H1_close'], linestyle = "solid", label = "H1_close")
    ax1.plot(df_EURJPY_H1_rates.loc[:,'time'], df_EURJPY_H1_rates.loc[:,'H1_200ema'], linestyle = "dashed", label = "H1_200ema")
    ax1.plot(df_EURJPY_H1_rates.loc[:,'time'], df_EURJPY_H1_rates.loc[:,'H1_20band_upper'], linestyle = "dotted", label = "H1_20band_upper", color = "red")
    ax1.plot(df_EURJPY_H1_rates.loc[:,'time'], df_EURJPY_H1_rates.loc[:,'H1_20band_middle'], linestyle = "dotted", label = "H1_20band_middle", color = "red")
    ax1.plot(df_EURJPY_H1_rates.loc[:,'time'], df_EURJPY_H1_rates.loc[:,'H1_20band_lower'], linestyle = "dotted", label = "H1_20band_lower", color = "red")
    ax1.legend()
    
    ax2.plot(df_EURJPY_H4_rates.loc[:,'time'], df_EURJPY_H4_rates.loc[:,'H4_close'], linestyle = "solid", label = "H1_close")
    ax2.plot(df_EURJPY_H4_rates.loc[:,'time'], df_EURJPY_H4_rates.loc[:,'H4_200ema'], linestyle = "dashed", label = "H1_200ema")
    ax2.plot(df_EURJPY_H4_rates.loc[:,'time'], df_EURJPY_H4_rates.loc[:,'H4_20band_upper'], linestyle = "dotted", label = "H1_20band_upper", color = "red")
    ax2.plot(df_EURJPY_H4_rates.loc[:,'time'], df_EURJPY_H4_rates.loc[:,'H4_20band_middle'], linestyle = "dotted", label = "H1_20band_middle", color = "red")
    ax2.plot(df_EURJPY_H4_rates.loc[:,'time'], df_EURJPY_H4_rates.loc[:,'H4_20band_lower'], linestyle = "dotted", label = "H1_20band_lower", color = "red")
    ax2.legend()
    
    ax3.plot(df_EURJPY_D1_rates.loc[:,'time'], df_EURJPY_D1_rates.loc[:,'D1_close'], linestyle = "solid", label = "H1_close")
    ax3.plot(df_EURJPY_D1_rates.loc[:,'time'], df_EURJPY_D1_rates.loc[:,'D1_200ema'], linestyle = "dashed", label = "H1_200ema")
    ax3.legend()
    
    ###########################
    # チャートの描画
    ###########################
    plt.show()
    

    좋은 웹페이지 즐겨찾기