見出し画像

生成AIとの連携を繰り返しながら取引を行うGPT-EA(FX自動売買)のテンプレート

割引あり

この記事では、実際にMT5のEAとして稼働可能なレベルのロジックを搭載したGPT-EA(生成AIとの連携を自動的に行うFX自動売買ツール)について、MQL5とPythonの連携、さらにはPythonとGPT APIとの連携の仕組みや各処理のロジックについて詳細に解説を行います。

最後には、この記事で紹介したGPT-EAのソースコード全文や必要なファイル一式をダウンロード可能です。これらを手順に従ってセットするだけで、生成AI機能搭載型EAとしてそのまま使用していただくことも可能です。

MQL5や Pythonが行う処理の概要

今回用意するEAは、生成AI技術であるGPTを活用し、FX市場のデータを高度に分析して自動売買を行うツールであり、Generative Pre-trained TransformerExpert Advisorの融合ということでGPT-EAと名付けます。
以下はこのGPT-EAの処理の流れの簡単なイメージ図です。

画像
GPT-EAの処理の流れ

MQL5で行う処理と、Windows上に保存されるファイル、Pythonで行う処理の3つに分かれています。今回の仕組みでは、PythonのMT5ライブラリを利用してPythonからMT5にアクセスするといったことは行いません。
MQLとPythonをそれぞれ独立に動かし、Windows上のテキストファイルやバッチファイルを介してお互いの処理を連動させるようにします。
※Windows PCにてMT5をインストールして実行する前提です。

FX自動売買ロジックの概要

今回の目的は、MQL5とPythonを連携させてGPT-EA(生成AIによる予測を取り入れたEA)のベースモデルを作成することです。したがって、売買ロジックは非常にシンプルなものとし、テクニカル指標などは一切使いません。
まずは、AIの能力そのものをそのまま活かす仕組みを採用します。

  • GPT APIには、過去18本の4時間足データ(72時間分)を渡した上で、以下の内容を伝える

    • 順張り買いエントリーを前提とすること

    • 12時間経過してもエントリーしなかった場合は、エントリーをキャンセルすること

    • エントリーしてから48時間を経過しても利益確定目標やロスカット基準に到達しなかった場合はその時点の価格でクローズすること

  • GPT APIからは、以下の3つの価格のみを受け取る

    • エントリー基準価格

    • 利益確定目標価格

    • ロスカット基準価格

  • GPT APIから受け取った価格にしたがったエントリー注文を行う

    • エントリー基準価格以上になったら買いを行う逆指値(Buy Stop)注文

    • 利益確定(Take Profit)とロスカット(Stop Loss)も注文時に設定

    • 12時間経過してもエントリーが成立しなかった場合は、注文をキャンセル

  • エントリー後、48時間経過しても利益確定(Take Profit)とロスカット(Stop Loss)のどちらにも到達していなかった場合は、その時点の価格でポジションをクローズ

  • 以上の処理を4時間足が更新される度に繰り返す、つまりエントリー注文は4時間ごとに行う

この記事では、以上を実装する方法を具体的に説明していきます。取引戦略は順張り買いエントリーに限定していますが、EAのロジック上は逆張り買いや売りにも対応するようなロジックを実装しており、GPTのプロンプトを調整すれば容易に拡張が可能な仕組みを取り入れています。

Input(グローバル変数)

MQL5内のグローバル変数として以下を定義します。ユーザーが自由に入力できるパラメータとEA内に固定で設定するものに分けていますが、変数の設定は比較的自由にカスタマイズ可能な仕様にしています。

//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+

//--- 入力パラメータ
input double lot_size      = 0.01;  // ロット数
input double spread_limit  = 20;    // 許容スプレッド(point)
input int    magic_number  = 10001; // マジックナンバー
input int    initial_order = 0;     // 起動時の注文(0:なし, 1:あり)
ulong  slippage      = 10;          // スリッページ

//--- 主要な定数・設定
#define POSITION_LIMIT        12        // 最大ポジション数
#define ENTRY_TIME_LIMIT      (12*60)   // エントリー待機制限時間(分)
#define CLOSE_TIME_LIMIT      (48*60)   // ポジション保有制限時間(分)
#define HISTORY_BARS          18        // 過去何本の足を取得するか
#define ANALYZE_TIMEFRAME     PERIOD_H4 // 4時間足を指定
#define TARGET_SIZE           5         // 「target_prices.txt」から受け取る数値の数
#define DEFAULT_TARGET_PRICE  0.0       // ターゲット価格の初期値

//+------------------------------------------------------------------+

ロット数

売買注文を行う際のロット数です。ロット数を変動させることは想定していません。

許容スプレッド(point)

許容できるスプレッドの上限を指定します。このGPT-EAでは、スプレッドが拡大している時には余計な処理を行わないような対処をしています。
取引通貨ペアによって平常時の平均スプレッド等が変わってくると思います。それに合わせて設定します。

マジックナンバー

マジックナンバーとは、注文がどのEA・ロジックから実行されたかを識別するための番号です。このGPT-EAでは、複数のマジックナンバーを使い分けたりしませんので、任意の値で問題ありません。

起動時の注文

EA起動時に注文を行うかどうかを指定します。基本的には0にしておいてください。EAをセットしてもまずは何も起こらず、次の4時間足の更新タイミングで初めてGPT APIへのアクセスと最初の注文送信が行われます。
1に設定すると、EAをセットしてすぐにGPT APIへのアクセスと最初の注文送信が始まるのでご注意ください。動作確認目的のための設定です。

スリッページ

スリッページとは、EAが発注したレートと、実際にFX会社側が約定するレートに乖離が生じること(またはその価格差)です。許容スリッページはFX会社によって異なり、設定不可の場合はスリッページの指定ができませんので、この値を設定しても意味がないこともあります。

最大ポジション数

ポジションを最大いくつまで同時に保有するかを指定します。このGPT-EAでは、エントリーの間隔と保有の制限時間が設定されるの保有ポジション数はある程度制限されますが、想定外の事態なども考慮してポジション数自体の制御も入れておきます。

エントリー待機制限時間(分)

12時間経過してもエントリーが成立しなかった場合、注文をキャンセルする仕組みを入れるための設定です。単位は分で設定します。

ポジション保有制限時間(分)

48時間経過しても利確やロスカットが成立しなかった場合、その時点の価格でポジションをクローズする仕組みを入れるための設定です。単位は分で設定します。

その他の設定

4時間足を過去18本取得して、GPT APIに渡す仕組みを導入しています。
また、「target_prices.txt」を介して受け取る数値の数は5個なので、その設定もしておきます。
GPT APIとのやり取りをより複雑にアレンジする場合は変更する必要も出てきます。

MQL5のメイン処理

まず、MQL5内のOnTick関数のコードについて全て順番に解説します。

4時間足の更新確認

// 4時間足が更新されたタイミングの確認
   static int init_order_flg = initial_order;
   static bool bars_H4_check = false;
   int current_bars_H4 = iBars(NULL,PERIOD_H4);
   static int pre_bars_H4 = current_bars_H4;
   int bars_H4_change = current_bars_H4 - pre_bars_H4;
   if(bars_H4_change > 0 || init_order_flg == 1)
     {
      init_order_flg = 0;
      bars_H4_check = true;
      RecordOHLCAndExecuteBatch(g_ea);
     }
   pre_bars_H4 = current_bars_H4;

今回のGPT-EAでは、4時間足が更新されたタイミングで最新状態の確認と取引戦略の決定やエントリー注文の送信まで行います。

  • 4時間に一度、4時間足が更新されるタイミングがあり、その瞬間にbars_H4_check = trueとなります。

  • RecordOHLCAndExecuteBatch関数を実行することにより、その時のOHLCデータ(過去18本の4時間足)の取得とバッチファイルの実行(Pythonスクリプトの実行)を行います。

  • インプットで起動時の注文(initial_order)を1に設定しておくと、4時間足の更新に関係なく、初回のEA稼働時だけ一連の処理が実行されます。

最新のティック情報の取得

// 最新のティック情報の取得
   MqlTick last_tick;
   if(!SymbolInfoTick(_Symbol, last_tick))
     {
      Print(__FUNCTION__, ": Failed to get tick data. err=", GetLastError());
      return;
     }
   double Ask = last_tick.ask;
   double Bid = last_tick.bid;
   double Spread = MathRound((Ask - Bid) / Point()) * Point();
  • 最新のAskとBidを取得します。

  • AskとBidの差からSpreadも計算します。

コメント表示

// コメント表示
   int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); // 小数点の桁数を取得
   string format_str = " \nAsk: %." + IntegerToString(digits) + "f\nBid: %." + IntegerToString(digits) + "f\nSpread: %." + IntegerToString(digits) + "f\n\nLast Update: \n %s\n\n%s\n en: %." + IntegerToString(digits) + "f\n tp: %." + IntegerToString(digits) + "f\n sl: %." + IntegerToString(digits) + "f\n\n";

   string message = StringFormat(
                       format_str,
                       Ask, Bid, Spread,
                       TimeToString(g_ea.last_update, TIME_DATE | TIME_MINUTES),
                       g_ea.entry_type,
                       g_ea.en_price, g_ea.tp_price, g_ea.sl_price
                    );
   Comment(message);

以下のようなコメントを表示するためのコードです。

コメント表示

最新のターゲット価格更新時間とその結果を表示するようにしています。
EAの稼働状況を確認しやすくするためのもので、ロジックには影響ありません。

スプレッド判定

// スプレッドが許容スプレッドを超える場合は以降の処理をスキップ
   if(Spread > spread_limit * Point())
      return;

現在のスプレッドを計算し、指定した許容スプレッド(spread_limit)を超えている場合は、後続の処理は行わずに終了する処理です。スプレッドが拡大している時は予測や取引を含めて余計な処理は行わないようにします。

Python処理の完了確認

// process_done.txtがない場合は以降の処理をスキップ
   if(!CheckProcessDoneFile())
      return;

 MQL5側が、Pythonの実行処理を待機するための処理です。

  • Pythonは、処理の開始時点でprocess_done.txtを削除します。

  • Pythonは、処理の終了時点でprocess_done.txtを作成します。

  • MQL5は、process_done.txtが存在しない間はPython処理実行中と判断し、処理を中断します。

ターゲット価格の取得

// ターゲット価格の取得
   GetTargetPrices(g_ea);
  • 4時間に1度のPython処理が終わったかどうかを確認します。

  • Python処理が終わっていたら、以下のターゲット価格の更新を行います。

    • エントリー基準価格

    • 利益確定目標価格

    • ロスカット基準価格

エントリー注文のキャンセル

// 現在の注文状況をチェックし、時間制限を超えていたら注文キャンセル
   if(OrdersTotal() > 0)
     {
      CancelExpiredOrders();
     }
  • 全ての待機中のエントリー注文(指値や逆指値に到達していないケース)を確認し、12時間経過しているものがあれば注文をキャンセルします。

保有ポジションのクローズ

// 現在のポジション状況をチェックし、時間制限を超えていたら強制クローズ
   if(PositionsTotal() > 0)
     {
      CloseExpiredPositions();
     }
  • 全ての保有ポジションのエントリー時刻を確認し、48時間経過しているものがあればポジションをクローズします。

エントリータイプの確認

// エントリータイプの確認
   double price;
   switch(g_ea.en_type)
     {
      case 1:
         g_ea.entry_type = "Buy Stop";
         price = Ask;
         break;
      case 2:
         g_ea.entry_type = "Buy Limit";
         price = Ask;
         break;
      case 3:
         g_ea.entry_type = "Sell Stop";
         price = Bid;
         break;
      case 4:
         g_ea.entry_type = "Sell Limit";
         price = Bid;
         break;
      default:
         g_ea.entry_type = "Unknown";
         price = Bid;
         break;
     }
  • エントリータイプ(g_ea.en_type)は1~4の値を取る想定です。

    1. Buy Stop:順張り買いエントリー(買いの逆指値注文)

    2. Buy Limit:順張り買いエントリー(買いの逆指値注文)

    3. Sell Stop:順張り買いエントリー(買いの逆指値注文)

    4. Sell Limit:順張り買いエントリー(買いの逆指値注文)

  • 今回のGPT-EAでは、エントリータイプ(g_ea.en_type)は必ず1になる仕様にしているので、順張り買いエントリーしか行いません。

  • 今後の発展としては、様々な戦略を使い分けたり、GPTにどの戦略を選択するか決めてもらう方法も考えられるでしょう。

エントリー条件判定

// エントリー条件判定
   if(bars_H4_check && TimeCurrent() - g_ea.last_chk >= 60)
     {
      bars_H4_check = false;
      g_ea.last_chk = TimeCurrent();

      if(OrdersTotal() + PositionsTotal() >= POSITION_LIMIT)
        {
         Print("Position limit exceeded");
        }
      else
        {
         if((g_ea.en_type == 1 && Ask < g_ea.en_price && g_ea.tp_price > g_ea.en_price && g_ea.sl_price < g_ea.en_price) ||
            (g_ea.en_type == 2 && Ask > g_ea.en_price && g_ea.tp_price > g_ea.en_price && g_ea.sl_price < g_ea.en_price) ||
            (g_ea.en_type == 3 && Bid > g_ea.en_price && g_ea.tp_price < g_ea.en_price && g_ea.sl_price > g_ea.en_price) ||
            (g_ea.en_type == 4 && Bid < g_ea.en_price && g_ea.tp_price < g_ea.en_price && g_ea.sl_price > g_ea.en_price))
           {
            g_ea.en_flg = true;
            Print("[", g_ea.entry_type, " Order Sent at ", g_ea.price, "] en=", g_ea.en_price,
               " tp=", g_ea.tp_price, " sl=", g_ea.sl_price);
           }
         else
           {
            g_ea.en_flg = false;
            Print("[No ", g_ea.entry_type, " Order Sent at ", g_ea.price, "] en=", g_ea.en_price, " tp=", g_ea.tp_price,
                  " sl=", g_ea.sl_price);
            g_ea.chk_cnt += 1;
            if(g_ea.chk_cnt < 10)
              {
               bars_H4_check = true;
              }
            else
              {
               g_ea.chk_cnt = 0;
              }
           }
        }
     }
  • 各エントリータイプごとに、ターゲット価格が妥当かどうかの確認を入れます。例えば、順張り買いエントリーであれば、以下の判定を行います。

    • 現在価格がエントリー基準価格より小さいか

    • 利益確定目標価格がエントリー基準価格より大きいか

    • ストップロス基準価格がエントリー基準価格より小さいか

  • 以上の条件を満たした場合にのみ、エントリー条件(g_ea.en_flg)がtrueになります。

エントリー注文

// エントリー注文
   if(g_ea.en_flg)
     {
      g_ea.en_flg = false;

      if(SendOrder(g_ea.en_type, g_ea.en_price, g_ea.tp_price, g_ea.sl_price))
        {
         g_ea.chk_cnt = 0;
        }
      else
        {
         g_ea.chk_cnt += 1;
         if(g_ea.chk_cnt < 10)
           {
            bars_H4_check = true;
           }
         else
           {
            g_ea.chk_cnt = 0;
           }
        }
     }
  • エントリー条件(g_ea.en_flg)がtrueの場合に、エントリー注文を行います。

  • 成行注文は行わず、指値または逆指値で待機注文を行う形を採用しているので、4時間に1回のエントリー注文を繰り返し、エントリー基準価格までの到達を待機するような流れです。

  • 全てのエントリー注文が成立すればポジション数は増えていきますが、ポジション保有制限時間も設けているので、無限にポジションが増えていくような仕組みではありません。

  • 4時間足が更新される度に、GPTの取引戦略判断によってエントリーチャレンジを行い、毎回勝敗判定を行うようなイメージです。それぞれの勝敗の積み重ねが累計損益になります。

MQL5とPythonの連携

ここからはMQL5がPythonと連携する仕組みについて解説します。
左側のMQL5と右側のPythonをつなぐ処理です。

画像
GPT-EAの処理の流れ

まずは概要です。

MQL5からPythonへの連携

  • MQL5から必要な情報はテキストファイル(ohlc.csv)で保存

  • MQL5からバッチファイル(get_gpt_reply.bat)を実行

  • バッチファイルがPythonスクリプト(get_gpt_reply.py)を実行

  • Pythonスクリプトはテキストファイルをインプットとして実行

PythonからMQL5への連携

  • Pythonスクリプトの実行結果はテキストファイル(target_prices.txt)で保存

  • MQLはテキストファイルを読み込むことで結果(target_prices)を取得

つまり、常にバッチファイルあるいはテキストファイルを介していて、MQL5とPythonで直接のやり取りはありません。

ShellExecuteW関数

#import "Shell32.dll"
int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
#import

MQL5からバッチファイル(.bat)を実行するために、ShellExecuteW関数を使用します。この関数はWindows APIの一部で、外部プログラムやドキュメントを開くために使用されます。
上記のようにMQL内で"Shell32.dll"をインポートすることで使用可能です。

バッチファイルのパスを設定

// バッチファイルのパス
input string user_name = "ご自身のPC環境の[ユーザー名]"; // ユーザー名
string get_gpt_reply_bat = "C:\\Users\\"+user_name+"\\get_gpt_reply.bat";

MQL5からは、「get_gpt_reply.bat」というバッチファイルを介してPythonスクリプトを実行するので、そのパスを指定しておきます。ここでは”C:¥Users¥[ユーザー名]¥”の直下にファイルを置いている場合を想定していますが、任意の場所でも問題ありません。[ユーザー名]部分は、それぞれの環境に合わせてEAのインプットで指定する必要があります。

画像
EAのインプット画面

バッチファイルの作成

バッチファイルの作成方法は、以下の内容をテキストファイルに記載した状態で.batという拡張子で保存するだけです。

get_gpt_reply.bat

@echo off
C:\Users\[ユーザー名]\anaconda3\python.exe C:\Users\[ユーザー名]\get_gpt_reply.py

ここでは、Python実行ファイル(python.exe)とPythonスクリプト(get_gpt_reply.py)のパスを同じラインに書いています。

この記載は、Anacondaを用いてPythonの環境設定を行なった場合の例です。
[ユーザー名]の部分は、それぞれご自身の環境のユーザー名に置き換える必要があります。
その他、各々の環境におけるPythonをインストールした際のパスを記載していただければ問題ないです。

get_gpt_reply.pyは、実際にそのファイルを保存している場所でOKです。ここでは”C:¥Users¥[ユーザー名]¥”の直下に置いている想定です。

Pythonスクリプトの作成

続いて、右側のPythonにおける処理です。

画像
GPT-EAの処理の流れ

GPT APIとのやり取り

「get_gpt_reply.py」というPythonスクリプトで以下の処理を実行します。

  • MQL5から出力された18本(72時間分)の4時間足データ(ohlc.csv)を読み込む

  • 4時間足データ(ohlc.csv)をOpenAIのChatCompletion APIに渡して、エントリー基準価格、利確目標価格、ロスカット基準価格、の3つの数値を回答してもらう

  • 回答してもらった数値をテキストファイル(target_prices.txt)に出力する

その他事前準備

ご自身で環境の設定や調整が難しい方は、ひとまずここで行っているものと同じ環境を構築する必要があります。以下のリンク先に、より詳細な手順をまとめましたのでご確認ください。

必要な環境構築と、MetaTrader5(MT5)にGPT-EAをセットして実際に動かす運用手順について、初心者にもわかりやすい形で詳しく説明しています。

運用手順

  1. VPSを用意する

  2. デモ口座を開設する

  3. MT5をインストールする

  4. Pythonの実行環境を整える

  5. OpenAIからAPIキーを発行する

  6. GPT-EAのテンプレートを準備する

  7. MT5にGPT-EAをセットし運用開始する

以上のGPT-EAを運用するために必要となる工程を一つ一つ丁寧に解説しています。環境構築や操作方法に不安がある方は、ぜひ参考にしてください。

まとめ

以上、GPT-EAのベースモデルを作成しました。
改めてですが、今回作成したのはあくまでGPT-EAのベースモデルであり、様々なロジックに拡張する土台でもあります。
また、使用しているAIモデルの進化により勝手に精度が向上していくことも考えられるでしょう。

GPT-EA関連の記事は以下のマガジンにまとめています。

今後も様々な取り組みをまとめた記事を公開していく予定です。
応援よろしくお願いいたします。

有料部分の内容

以上、GPT-EAで行う処理の流れを具体的に説明してきました。
有料部分では一連の処理を実行するための全コードを掲載した以下のファイルをダウンロード可能にしています。

  • GPT-EA_note.mq5(MQL5のメイン処理だけでなく全ての関数を掲載)

  • get_gpt_reply.bat(get_gpt_reply.pyを実行するバッチファイル)

  • get_gpt_reply.py(GPT APIにアクセスするPythonスクリプト)

注意点

  • 当記事で掲載しているコードはPythonの環境設定やAPIキーの取得を含め、必要な準備が整っている上での実行を想定しています。環境設定に問題がある場合はご自身で解決していただかないと実際のプログラム実行まで辿り着けない可能性があります。

  • 記事執筆時点で稼働確認を行なっており、エラーが出ないことを確認しておりますが、その後の環境変化等で想定通りに稼働しない可能性はございます。動作保証等はいたしかねますのでご了承ください。

  • リアル口座にアクセスして取引を行うことも可能なコードになっておりますが、必ずデモ口座で事前に稼働確認をしていただくことを推奨いたします。

  • デモ口座での実施であっても、OpenAIのAPIにアクセスする仕組みを採用しているため、API料金が発生します。EAやPython処理を実行する際は特にご注意ください。

  • 当記事で解説しているロジック通りの動作を保証するものではございません。あくまでFX自動売買ツール開発のためのサンプルコードとしてご活用ください。

  • 今回作成したのはあくまでGPT-EAのベースモデルであり、様々なロジックに拡張するための土台になります。その後の改善の記事については順次更新予定です。応援よろしくお願いいたします。

ここから先は

3,429字

Amazon Pay支払いで総額2,025万円を山分け! 詳細

よろしければ応援お願いします。いただいたチップは今後の記事の執筆に活用させていただきます。

ピックアップされています

GPT-EA マガジン

  • 8本
生成AIとの連携を繰り返しながら取引を行うGPT-EA(FX自動売買)のテンプレート|sayama_ocha
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1