FX自動売買(EA)の作り方Python

PythonとMT5を連携させたEA【テクニカル指標による売買判断パターン拡張】

※アフィリエイト広告を利用しています

広告

初心者向けになるべくコードの意味まで丁寧に解説するように心がけていますので、初心者の方も是非、PythonでのFX自動売買botの作成にチャレンジしてみてください。

    広告

    FX自動売買ツールの設計概要

    前回の記事でもご紹介した通り、基本的なFX自動売買ツール(bot)の設計概要は以下の通りです。

    • 四本値(始値、高値、安値、終値)データを取得
    • 四本値データを基にテクニカル指標を計算
    • テクニカル指標を基に売買判断フラグを生成
    • ポジション情報を取得して既存のポジションを確認
    • 新規エントリー(買いまたは売り)の条件を満たしている場合、注文を送信
    • エントリー時に設定した利確幅またはストップロス幅に到達したらポジションクローズ
    • 上記全てをループ処理

      ロジック概要

      前回作成したFX自動売買ツール(bot)のロジック概要は以下の通りでした。

      • テクニカル指標(MAとRSI)を用いて売買判断条件を作成
      • 売買判断条件を満たした場合にbuyまたはsellの注文を行う
      • ATR(Average True Range)を基準に利確幅とストップロス幅を決める

        今回は、このテクニカル指標による売買判断条件を拡張させる方法をご紹介します。

        Inputの設定

        以下のインプットを用意していますが、今回の拡張に関係してくるのは最後のbar_periodです。

        symbol = "GOLD" # 取引対象
        first_lot = 0.01 # 初期ロット数
        tp_factor = 2.0 # 利確係数
        sl_factor = 1.5 # ストップロス係数
        magic_number = 10001 # マジックナンバー
        slippage = 10 # スリッページ
        bar_period = 30 # 取得する四本値の本数

        取得する四本値の本数(bar_period)

        これは取得するバー(四本値)の本数です。使用するテクニカル指標に合わせて必要な本数を設定するようにしてください。

        例えば、MA(移動平均)の期間は15で設定している場合、30本あれば十分ですが、期間を50や100に設定する場合は、その分必要な本数を増やす必要があります。基本的には使用する期間よりも2本くらい多めに設定しておくと良いですが、ロジックがシンプルなのである程度余裕を持たせた本数にしておいてもそれほど処理が遅くなったりはしないと思います。

        テクニカル指標の関数定義

        今回は、テクニカル指標を計算する関数をATR、MA、RSIだけでなく、MACD、ボリンジャーバンド、ストキャスティクスまで拡張します。

        ATR(Average True Range)

        def calculate_atr(data, period=14):
            data['tr'] = np.maximum((data['high'] - data['low']), 
                                    np.maximum(abs(data['high'] - data['close'].shift()), abs(data['low'] - data['close'].shift())))
            data['atr'] = data['tr'].rolling(window=period).mean()
            return data

        引数は、’high’、’low ‘、’close’が入ったデータフレーム(data)です。
        期間(period)はデフォルトで14と設定しています。
        例えば15分足のdataを与えれば、期間14のATRが15分足ベースで計算されます。

        MA(単純移動平均)

        def calculate_ma(data, period=15, price_type='close'):
            data['ma'] = data[price_type].rolling(window=period).mean()
            return data

        引数は、’close’が入ったデータフレーム(data)です。
        price_type=’close’で終値の単純移動平均を計算します。
        期間(period)はデフォルトで15と設定しています。
        例えば15分足のdataを与えれば、期間15の終値ベースのMAが15分足ベースで計算されます。

        単純移動平均(MA):
        ある期間の平均値を計算することで、価格のトレンドを把握するための指標です。価格がMAよりも上にある場合は上昇トレンド、下にある場合は下降トレンドと判断されることが多いです。

        RSI(Relative Strength Index)

        def calculate_rsi(data, period=14, price_type='close'):
            delta = data[price_type].diff()
            gains = delta.where(delta > 0, 0)
            losses = -delta.where(delta < 0, 0)
            avg_gain = gains.rolling(window=period).mean()
            avg_loss = losses.rolling(window=period).mean()
            rs = avg_gain / avg_loss
            data['rsi'] = 100 - (100 / (1 + rs))
            return data

        引数は、’close’が入ったデータフレーム(data)です。
        price_type=’close’で終値のRSIを計算します。
        期間(period)はデフォルトで14と設定しています。
        例えば15分足のdataを与えれば、期間14のRSIが15分足ベースで計算されます。

        相対力指数(RSI):
        ある期間の価格変動をもとに、買われ過ぎ・売られ過ぎの状況を示すオシレーター指標です。RSIが30以下の場合は買われ過ぎ、70以上の場合は売られ過ぎと判断されることが一般的です。

        MACD(移動平均収束拡散法)

        def calculate_macd(data, short_period=12, long_period=26, signal_period=9, price_type='close'):
            short_ema = data[price_type].ewm(span=short_period, adjust=False).mean()
            long_ema = data[price_type].ewm(span=long_period, adjust=False).mean()
            data['macd'] = short_ema - long_ema
            data['signal'] = data['macd'].ewm(span=signal_period, adjust=False).mean()
            return data

        引数は、’close’が入ったデータフレーム(data)です。
        price_type=’close’で終値のMACDを計算します。
        期間(period)はデフォルトで12, 26, 9と設定しています。
        例えば15分足のdataを与えれば、終値ベースのMACDが15分足ベースで計算されます。

        移動平均収束拡散法(MACD):
        短期の移動平均と長期の移動平均の差をとることで、トレンドの強さや転換を把握するための指標です。MACDがシグナル線を上抜けると買いシグナル、下抜けると売りシグナルと判断されることが多いです。

        ボリンジャーバンド

        def calculate_bollinger(data, period=20, std_dev=2, price_type='close'):
            data['middle_band'] = data[price_type].rolling(window=period).mean()
            data['upper_band'] = data['middle_band'] + std_dev * data[price_type].rolling(window=period).std()
            data['lower_band'] = data['middle_band'] - std_dev * data[price_type].rolling(window=period).std()
            return data

        引数は、’close’が入ったデータフレーム(data)です。
        price_type=’close’で終値のボリンジャーバンドを計算します。
        期間(period)はデフォルトで20と設定しています。
        std_dev=2で、2σのボリンジャーバンドです。
        例えば15分足のdataを与えれば、期間20で2σのボリンジャーバンドが15分足ベースで計算されます。

        ボリンジャーバンド:
        移動平均とその標準偏差をもとに、価格の上限・下限を示すバンドを描くことで、価格の変動範囲を把握するための指標です。価格がバンドの上限・下限を突き抜けると、逆の方向への価格変動が予想されます。

        ストキャスティクス(%K)

        def calculate_stochastics(data, k_period=14, d_period=3, slowing=3):
            highest_high = data['high'].rolling(window=k_period).max()
            lowest_low = data['low'].rolling(window=k_period).min()
            data['%K'] = ((data['close'] - lowest_low) / (highest_high - lowest_low)) * 100
            data['%K'] = data['%K'].rolling(window=slowing).mean()
            data['%D'] = data['%K'].rolling(window=d_period).mean()
            return data

        引数は、’high’、’low ‘、’close’が入ったデータフレーム(data)です。
        期間(period)はデフォルトで14, 3と設定しています。
        例えば15分足のdataを与えれば、期間14, 3のストキャスティクスが15分足ベースで計算されます。

        ストキャスティクス(%K):
        過去の価格範囲の中で現在の終値がどの程度上昇したかを示すオシレーターです。0~100の値で表され、一般的には%Kが20以下の場合は買われすぎ(オーバーソールド)、80以上の場合は売られすぎ(オーバーボート)と判断されます。

        売買判断フラグを設定する関数

        ここでは、上記で設定したテクニカル指標を組み合わせた売買判断フラグを設定する関数をいくつかのパターンでご紹介します。全体のコードのうち、generate_trade_flgs関数部分を以下のいずれかに変更することで適用可能です。

        各パターン共通

        引数の設定

        引数は四本値のデータフレーム(data)と、現在価格(symbol_tick)です。

        売買判断フラグ

        買いフラグ(buy_flg)と売りフラグ(sell_flg)をそれぞれ設定します。

        パターン1: 単純移動平均とRSIを利用

        def generate_trade_flgs(data, symbol_tick):
        
            # テクニカル指標の計算
            data = calculate_ma(data)
            data = calculate_rsi(data)
        
            # 売買判断フラグ
            buy_flg = (symbol_tick.ask > data['ma'].iloc[-2]) & (data['rsi'].iloc[-2] < 30)
            sell_flg = (symbol_tick.bid < data['ma'].iloc[-2]) & (data['rsi'].iloc[-2] > 70)
        
            return buy_flg, sell_flg
        • 買いフラグ (buy_flg):
          現在のAsk価格がMAよりも上で、かつRSIが30未満の場合に買いフラグを立てます。これは、上昇トレンドで買われ過ぎの状況が続いていることを示し、買いチャンスと判断しています。
        • 売りフラグ (sell_flg):
          現在のBid価格がMAよりも下で、かつRSIが70以上の場合に売りフラグを立てます。これは、下降トレンドで売られ過ぎの状況が続いていることを示し、売りチャンスと判断しています。

        パターン2: MACDとボリンジャーバンドを利用

        def generate_trade_flgs(data, symbol_tick):
        
            # テクニカル指標の計算
            data = calculate_macd(data)
            data = calculate_bollinger(data)
        
            # 売買判断フラグ
            buy_flg = (data['macd'].iloc[-2] > data['macd_signal'].iloc[-2]) & (symbol_tick.ask < data['bollinger_lower'].iloc[-2])
            sell_flg = (data['macd'].iloc[-2] < data['macd_signal'].iloc[-2]) & (symbol_tick.bid > data['bollinger_upper'].iloc[-2])
        
            return buy_flg, sell_flg
        • 買いフラグ (buy_flg):
          MACDがシグナル線よりも上で、かつ現在のAsk価格がボリンジャーバンドの下限よりも下の場合に買いフラグを立てます。これは、上昇トレンドで価格が下限を突き抜けたことを示し、買いチャンスと判断しています。
        • 売りフラグ (sell_flg):
          MACDがシグナル線よりも下で、かつ現在のBid価格がボリンジャーバンドの上限よりも上の場合に売りフラグを立てます。これは、下降トレンドで価格が上限を突き抜けたことを示し、売りチャンスと判断しています。

        パターン3: ストキャスティクスとRSIを利用

        def generate_trade_flgs(data, symbol_tick):
        
            # テクニカル指標の計算
            data = calculate_atr(data)
            data = calculate_rsi(data)
            data = calculate_stochastics(data)
        
            # 売買判断フラグ
            buy_flg = (data['%K'].iloc[-2] < 20) & (data['rsi'].iloc[-2] < 30) sell_flg = (data['%K'].iloc[-2] > 80) & (data['rsi'].iloc[-2] > 70)
        
            return buy_flg, sell_flg
        • 買いフラグ (buy_flg):
          %Kが20よりも小さく、かつRSIが30よりも小さい場合に買いフラグを立てます。これは、市場が買われすぎであり、さらにRSIでも売られすぎの状態であることを示し、買いチャンスと判断しています。
        • 売りフラグ (sell_flg):
          %Kが80よりも大きく、かつRSIが70よりも大きい場合に売りフラグを立てます。これは、市場が売られすぎであり、さらにRSIでも買われすぎの状態であることを示し、売りチャンスと判断しています。

        パターン4: 単純移動平均とMACDを利用

        def generate_trade_flgs(data, symbol_tick):
        
            # テクニカル指標の計算
            data = calculate_ma(data)
            data = calculate_macd(data)
        
            # 売買判断フラグ
            buy_flg = (symbol_tick.ask > data['ma'].iloc[-2]) & (data['macd'].iloc[-2] > data['macd_signal'].iloc[-2])
            sell_flg = (symbol_tick.bid < data['ma'].iloc[-2]) & (data['macd'].iloc[-2] < data['macd_signal'].iloc[-2])
        
            return buy_flg, sell_flg
        • 買いフラグ (buy_flg):
          現在のAsk価格がMAよりも高く、かつMACDがMACDシグナルよりも高い場合に買いフラグを立てます。これは、上昇トレンドであり、さらにMACDでも上昇トレンドの勢いがあることを示し、買いチャンスと判断しています。
        • 売りフラグ (sell_flg):
          現在のBid価格がMAよりも低く、かつMACDがMACDシグナルよりも低い場合に売りフラグを立てます。これは、下降トレンドであり、さらにMACDでも下降トレンドの勢いがあることを示し、売りチャンスと判断しています。

        パターン5: ボリンジャーバンドとストキャスティクスを利用

        def generate_trade_flgs(data, symbol_tick):
        
            # テクニカル指標の計算
            data = calculate_bollinger(data)
            data = calculate_stochastics(data)
        
            # 売買判断フラグ
            buy_flg = (symbol_tick.ask < data['bollinger_lower'].iloc[-2]) & (data['%K'].iloc[-2] < 20) sell_flg = (symbol_tick.bid > data['bollinger_upper'].iloc[-2]) & (data['%K'].iloc[-2] > 80)
        
            return buy_flg, sell_flg
        • 買いフラグ (buy_flg):
          現在のAsk価格がボリンジャーバンドのローワーバンドよりも低く、かつストキャスティクスの%Kが20以下の場合に買いフラグを立てます。これは、価格が過去の範囲の下限に達しており、さらにオシレーターでも買いシグナルが出ていることを示し、買いチャンスと判断しています。
        • 売りフラグ (sell_flg):
          現在のBid価格がボリンジャーバンドのアッパーバンドよりも高く、かつストキャスティクスの%Kが80以上の場合に売りフラグを立てます。これは、価格が過去の範囲の上限に達しており、さらにオシレーターでも売りシグナルが出ていることを示し、売りチャンスと判断しています。

        まとめ

        以上、”売買判断フラグを設定する関数”部分をMAやRSIだけでなく、他のテクニカル指標に置き換える方法をご紹介しました。今回取り上げたパターンだけでなく、各々でこのコードをベースに様々なパターンに発展させることも比較的容易だと思います。

        是非、オリジナルの売買判断ロジックを取り入れてみてください。

        機械学習モデルの導入

        この記事では、テクニカル指標を用いて売買判断を決定するロジックをご紹介しましたが、この売買判断ロジック部分を機械学習モデルによるものに変更するだけで、シンプルなMLbot(機械学習を取り入れたFX自動売買ツール)に変換可能です。

        以下の記事では、その方法をご紹介しています。この記事のbotの拡張方法の解説になります。

        Pythonでバックテスト

        PythonでFX自動売買ツールを開発するために、バックテスト環境を整えることも重要です。以下の記事ではMT4やMT5ではなく、Pythonでバックテストを行う方法をご紹介しています。

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