🎉

生成AIを使ってMetaTrade5用のEAを作成しよう ~雛形作成編~

2024/02/18に公開

はじめに

最近の日本株式市場は中国市場の減速による資金流入、新NISA効果も相まってなかなか好調ですね。
私もその恩恵をいただいているのですが、儲けた分お馬さん達に溶かされる日々です。
なんか別の収入源が欲しいなーと思ったので、エキスパートアドバイザ("EA"とよばれるMetatrade上で動くFXの自動売買ロボット)を作って働いてもらいましょう。

なお、注意喚起ですがFX自動売買に関しては詐欺商品が非常に多いです。
今回作成するものも必ず儲かるものではありません。
特に昨今の為替相場は経済指標の発表前後でとんでもない値動きをすることも多く、私の考えではありますが、「完全放置で儲かる」EAはかなり難しいと言えるでしょう。
その辺りをご理解いただいた上で読み進めてください。

今回作るもの

今回はEAの雛形まで作ります。
正直EAの雛形を作るだけだったら10分でできてしまうのですが、システムのライブサイクルにも着目していきましょう。
と同時に、今回試したいことがあって、ChatGPT等の生成AIの力を使って勝てるEAを作っていきたいと思います。。。もっとも、生成AIの登場は次回以降の予定です。

では作成していきましょう。

Step 0

まず前提として、EAを作るにはMetaTrade5とMetaEditorのインストールが必要です。
これはMetaTrade5を採用しているFX会社様のサイトからダウンロードできます。
日本国内ですと、OANDA証券株式会社、 フィリップ証券、が有名どころですね。楽天証券はMetaTrade4をサポートしているんですが、5はサポートしてないんですよね。。

いずれも金融商品取引業として日本の金融庁から認可を得ており、「相対的」には信用できるのではないでしょうか?
海外FX会社もありますが、色々闇が深い部分もあるので今回は触れません。
なお、こちらWindows用が主流で、Mac用もあるにはあるのですが非常に使いにくい。。
そもそも、MetaEditor自体も非常に使いにくい、、、
私はファイル作成とコンパイルのみはWindows環境に任せて、実際のコーディングはMacのVSCodeで書いています。この辺りは好みの問題でしょう。

ではこれ以降、MetaTrade5とMetaEditorのインストールが済んで、開発環境も整っている前提で進めます。

Step1

まず、MetaEdotorを立ち上げ、画面上部の「新規作成」をクリックします。
すると、MQLウイザードファイルというモーダルが立ち上がるので、ここでエキスパートアドバイザ(テンプレート)
を選んで「次へ」ボタンを押してます。

次に名前を決めます。
今回はsample_eaとしておきます。

次に追加のイベントハンドラ設定がありますが、チェックを入れずに「次へ」を押して最後の完了ボタンを押してください。

すると、以下のようなデフォルトのテンプレートファイルが作成されます。

現状では

int OnInit()
void OnDeinit(const int reason)
void OnTick()

のみ存在しています。

int OnInit()

はプログラムの初期化、EAが起動した直後に呼び出されます。

void OnDeinit(
  const int  reason        // 初期化解除の理由コード
  );

はEAの初期化を削除する際に呼び出されます。

void  OnTick(void);

は、NewTickイベントが発生して新しい相場が処理されるときに呼び出されます。
NewTickイベントとは値動きが発生したタイミングで呼ばれる関数で、仮に15分足のチャートにEAを仕込んだとしても15分に一回、というわけでありません。
あくまで「値動きが発生したタイミング」です。
公式ドキュメント
(なお、この公式ドキュメントですが、個人的には非常にわかりづらく、嫌いです)

ではこの状態で一回コンパイルをやってみましょう。

エラーの発生もなく、コンパイルが完了しました。

コンパイルした結果ファイルは以下の画面のようにファイルを右クリックで選択し「フォルダを開く」で開いたフォルダの中に格納されています。

Step2

ここから雛形にふさわしい、簡単なトレードフローを実装していきます。

実装するとこんな感じになります。

//+------------------------------------------------------------------+
//|                                                    sample_ea.mq5 |
//|                        Copyright 2022, MetaQuotes Ltd.           |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
CTrade  trade;

//+------------------------------------------------------------------+
//| エキスパートアドバイザーの初期化関数                               |
//+------------------------------------------------------------------+
int OnInit()
  {
   // 初期化処理
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| エキスパートアドバイザーの終了関数                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // 終了処理
  }

//+------------------------------------------------------------------+
//| エキスパートアドバイザーのメイン処理関数                           |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 開いているポジションがあるかチェック
   if(PositionSelect(Symbol()))
     {
      // エグジット条件をチェック
      double profit = PositionGetDouble(POSITION_PROFIT);
      if(profit >= 20 * _Point || profit <= -40 * _Point)
        {
         // ポジションを閉じる
         trade.PositionClose(Symbol());
        }
     }
   else
     {
      // エントリーシグナルを監視
      if(LongSignal())
        {
         // ロングポジションを0.01ロットで開く
         trade.Buy(0.01, Symbol());
        }
      else if(ShortSignal())
        {
         // ショートポジションを0.01ロットで開く
         trade.Sell(0.01, Symbol());
        }
     }
  }

//+------------------------------------------------------------------+
//| ロングエントリーシグナルをチェックする関数                         |
//+------------------------------------------------------------------+
bool LongSignal()
  {
   // ロングエントリーシグナル検出のロジックをここに実装
   // これは仮の関数です
   return false;
  }

//+------------------------------------------------------------------+
//| ショートエントリーシグナルをチェックする関数                       |
//+------------------------------------------------------------------+
bool ShortSignal()
  {
   // ショートエントリーシグナル検出のロジックをここに実装
   // これは仮の関数です
   return false;
  }
//+------------------------------------------------------------------+

今回は雛形までなので、ここまでで止めておきます。
次回からこれを肉付けしていきます。

参考

https://www.mql5.com/ja/docs

Discussion