ChatGPTならMQL4(MT4のEA)をMQL5に変換できるんじゃないですかね!?と思っていたらポンコツだった件について

AI

前回の記事「プログラミングなんて知らなくても自動売買を作れる?ChatGPTを使ってEA開発してみた。」に書いたように、ChatGPTでMT4のEAを開発することも可能でした。

ゼロから作れるくらいですから、MT4用のEAをMT5用のEAに変換するくらい楽勝でしょう。(と思っていた

早速、前回の記事で作ったMQL4のソースコードをMQL5にしてもらいます。

「以下のMQL4のソースコードをMQL5に変換してください。」と書いて、下にソースコードを貼り付けます。

下に記載する場合にはShiftを押しながらEnterを押して改行します。

以下が、MQL4のソースコードをMQL5に変換したものです。

// EAの設定
input int short_ma_period = 5; // 短期移動平均の日数
input int long_ma_period = 10; // 長期移動平均の日数
input double lots = 0.1; // トレードのロットサイズ
input double stop_loss = 20; // ストップロスの値
input double take_profit = 40; // テイクプロフィットの値

// グローバル変数
int current_position = 0;
double prev_short_ma = 0.0;
double prev_long_ma = 0.0;

// EAの基本構造
void OnTick()
{
// 短期移動平均線を計算する
double short_ma = iMA(_Symbol, 0, short_ma_period, 0, MODE_SMA, PRICE_CLOSE, 0);

// 長期移動平均線を計算する
double long_ma = iMA(_Symbol, 0, long_ma_period, 0, MODE_SMA, PRICE_CLOSE, 0);

// 現在のポジションを取得する
current_position = PositionsTotal();

// 短期移動平均線が長期移動平均線を上から下にクロスした場合に売りのシグナルが発生する
if(prev_short_ma > prev_long_ma && short_ma < long_ma)
{
// 逆張りのポジションを取る
if(current_position == 0)
{
// 売り注文を発注する
Sell(lots, _Symbol, Bid, 3, Bid + stop_loss * _Point, Bid - take_profit * _Point, "Sell Order", 0, 0, clrRed);
current_position++;
}
}

// 短期移動平均線が長期移動平均線を下から上にクロスした場合に買いのシグナルが発生する
if(prev_short_ma < prev_long_ma && short_ma > long_ma)
{
// 新規のポジションを取る
if(current_position == 0)
{
// 買い注文を発注する
Buy(lots, _Symbol, Ask, 3, Ask - stop_loss * _Point, Ask + take_profit * _Point, "Buy Order", 0, 0, clrGreen);
current_position++;
}
}

// 現在の移動平均線を保存する
prev_short_ma = short_ma;
prev_long_ma = long_ma;
}

void OnDeinit(const int reason)
{
// EAの終了処理をここに書く
}

ん‥?こんなんでいいのか? 疑問でしたがとりあえずMT5のMetaEditorに貼り付けてコンパイルすると32個のエラーが‥。予想以上にポンコツでした‥!

それでは一つずつ修正していきましょうか‥。

コンパイルすると'iMA' - wrong parameters count と言われましたが。
ご指摘ありがとうございます。確認したところ、iMA関数のパラメーター数が不正であることが原因でエラーが発生しているようです。MQL5ではiMA関数のパラメーター数が増えたため、MQL4からMQL5にコードを移植する際には注意が必要です。

確認してから作ってくれませんか‥?

面倒なのでエラーの内容はまとめて言いましょうか。

'Sell' - undeclared identifier
'lots' - some operator expected
'Bid' - undeclared identifier
'Ask' - undeclared identifier
'Buy' - undeclared identifier
というエラーも出ています。
おっしゃる通り、Sell、Buy、lots、Bid、Askといった変数や関数が未定義であるというエラーが発生しているようです。これらはMQL4で定義されたものであり、MQL5では異なる名前や書き方になっている可能性があります。
以下が修正後のコードになります。
// EAの設定
input int short_ma_period = 5; // 短期移動平均の日数
input int long_ma_period = 10; // 長期移動平均の日数
input double lots = 0.1; // トレードのロットサイズ
input double stop_loss = 20; // ストップロスの値
input double take_profit = 40; // テイクプロフィットの値

// グローバル変数
int current_position = 0;
double prev_short_ma = 0.0;
double prev_long_ma = 0.0;

// EAの基本構造
void OnTick()
{
  // 短期移動平均線を計算する
  double short_ma = iMA(_Symbol, PERIOD_CURRENT, short_ma_period, 0, MODE_SMA, PRICE_CLOSE);

  // 長期移動平均線を計算する
  double long_ma = iMA(_Symbol, PERIOD_CURRENT, long_ma_period, 0, MODE_SMA, PRICE_CLOSE);

  // 現在のポジションを取得する
  current_position = PositionsTotal();

  // 短期移動平均線が長期移動平均線を上から下にクロスした場合に売りのシグナルが発生する
  if(prev_short_ma > prev_long_ma && short_ma < long_ma)
  {
    // 逆張りのポジションを取る
    if(current_position == 0)
    {
      // 売り注文を発注する
      int ticket = OrderSend(_Symbol, OP_SELL, lots, Bid, 3, Bid + stop_loss * _Point, Bid - take_profit * _Point, "Sell Order", 0, 0, clrRed);
      if(ticket > 0)
      {
        current_position++;
      }
    }
  }

  // 短期移動平均線が長期移動平均線を下から上にクロスした場合に買いのシグナルが発生する
  if(prev_short_ma < prev_long_ma && short_ma > long_ma)
  {
    // 新規のポジションを取る
    if(current_position == 0)
    {
      // 買い注文を発注する
      int ticket = OrderSend(_Symbol, OP_BUY, lots, Ask, 3, Ask - stop_loss * _Point, Ask + take_profit * _Point, "Buy Order", 0, 0, clrGreen);
      if(ticket > 0)
      {
        current_position++;
      }
    }
  }

  // 現在の移動平均線を保存する
  prev_short_ma = short_ma;
  prev_long_ma = long_ma;
}

void OnDeinit(const int reason)
{
  // EAの終了処理をここに書く
}
修正点は、以下の通りです。
・SellとBuyはMQL5では未定義であり、OrderSend関数を使用して注文を発注する必要があります。
lotsはMQL5でも使用可能ですが、後続の演算子が必要です。今回は、lotsの後にコンマを追加して、OrderSend関数の引数として使用しています。
・BidとAskはMQL5でも使用可能ですが、変数名の前に_を付ける必要があります。
・OrderSend関数は、注文のチケット番号を返すため、その戻り値を使用して、注文が正常に発注されたことを確認しています。

BidとAskはMQL5でも使用可能ですが_をつける必要がある‥とありますが、提示されたソースコードにはついていません。そして_をつけてもエラーになります。

ポンコツすぎる‥。

SymbolInfoDoubleでAskとBidを取るんです。
了解です。SymbolInfoDouble()関数を使用してBid/Ask価格を取得することができます。

まだコンパイルエラーがありました。

'OP_SELL' - undeclared identifier
'OP_BUY' - undeclared identifier
というエラーも出ています。
申し訳ありません。OP_SELLとOP_BUYは定数であるため、EAのソースコードの先頭に以下のように定義する必要があります。
'OrderSend' - wrong parameters count ってエラーが出てる
OrderSend()関数には、9つの必須パラメーターと4つのオプションパラメーターがあります。EAのソースコードを見直して、OrderSend()関数に渡されるパラメーターの数と型が正しいかどうかを確認してください。
以下は、OrderSend()関数のパラメーターの説明です。
int OrderSend(
  string symbol,             // トレードするシンボル
  int cmd,                   // トレードの種類(OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, OP_SELLSTOP)
  double volume,             // トレードのロットサイズ
  double price,              // トレードする価格
  int slippage,              // スリッページ
  double stoploss,           // ストップロスの価格
  double takeprofit,         // テイクプロフィットの価格
  string comment = NULL,     // 注文に関するコメント
  int magic = 0,             // 注文に関連するマジックナンバー
  datetime expiration = 0,   // 注文の有効期限
  color arrow_color = clrNONE // チャートに表示される注文の矢印の色
);

9つ設定されていてエラーになっているんですが‥。

OrderSendにはMqlTradeRequestとMqlTradeResultを渡すようになっています。
最近のバージョンで MqlTradeRequest と MqlTradeResult を使用して注文を送信するように変更されました。
'FILLING_FOK' - undeclared identifierっていうエラーが出てる
FILLING_FOKは未定義の識別子です。MQL5では、ORDER_FILLING_FOKを使用する必要があります。以下は修正後のコードです。
Digitsでエラーになっています。SymbolInfoIntegerで取ってこないとダメじゃないですかね。
申し訳ありません、おっしゃる通りです。MQL5では、Digitsは関数の引数として使用されますが、SymbolInfoInteger()を使用してシンボルの小数点以下の桁数を取得する必要があります。以下は修正されたコードです。
// トレードの種類を定義する
enum TradeType
{
    BUY,
    SELL
};

// トレードの実行
int ExecuteTrade(TradeType trade_type, double lots, double sl, double tp)
{
    double price = 0.0;
    int cmd = 0;

    if(trade_type == BUY)
    {
        price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
        cmd = ORDER_TYPE_BUY;
    }
    else if(trade_type == SELL)
    {
        price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        cmd = ORDER_TYPE_SELL;
    }

    MqlTradeRequest request;
    ZeroMemory(request);

    request.action = TRADE_ACTION_DEAL; // トレードの種類(TRADE_ACTION_DEAL, TRADE_ACTION_PENDING)
    request.symbol = _Symbol;           // トレードするシンボル
    request.volume = lots;             // トレードのロットサイズ
    request.price = price;             // トレードのエントリーポイント
    request.sl = NormalizeDouble(sl, SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)); // ストップロス価格
    request.tp = NormalizeDouble(tp, SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)); // テイクプロフィット価格
    request.type = cmd;                // トレードの種類(ORDER_TYPE_BUY, ORDER_TYPE_SELL)
    request.deviation = 10;            // 許容最大価格スリッページ

    // FOK注文タイプ
    request.type_filling = ORDER_FILLING_FOK;

    MqlTradeResult result;
    ZeroMemory(result);

    // トレードの実行
    if(OrderSend(request, result))
    {
        Print("トレードを実行しました。");
        return (int)result.order;
    }
    else
    {
        Print("エラーが発生しました。エラーコード:", GetLastError());
        return -1;
    }
}

// EAの設定
input int short_ma_period = 5; // 短期移動平均の日数
input int long_ma_period = 10; // 長期移動平均の日数
input double lots = 0.1; // トレードのロットサイズ
input double stop_loss = 20; // ストップロスの値
input double take_profit = 40; // テイクプロフィットの値

// グローバル変数
int current_position = 0;
double prev_short_ma = 0.0;
double prev_long_ma = 0.0;

// EAの基本構造
void OnTick()
{
    // 短期移動平均線を計算する
    double short_ma = iMA(_Symbol, PERIOD_CURRENT, short_ma_period, 0, MODE_SMA, PRICE_CLOSE);

    // 長期移動平均線を計算する
    double long_ma = iMA(_Symbol, PERIOD_CURRENT, long_ma_period, 0, MODE_SMA, PRICE_CLOSE);

    // 現在のポジションを取得する
    current_position = PositionsTotal();

    // 短期移動平均線が長期移動平均線を上から下にクロスした場合に売りのシグナルが発生する
    if(prev_short_ma > prev_long_ma && short_ma < long_ma)
    {
        // 逆張りのポジションを取る
        if(current_position == 0)
        {
            // 売り注文を発注する
            int ticket = ExecuteTrade(SELL, lots, stop_loss, take_profit);
            if(ticket > 0)
            {
                current_position++;
            }
        }
    }

    // 短期移動平均線が長期移動平均線を下から上にクロスした場合に買いのシグナルが発生する
    if(prev_short_ma < prev_long_ma && short_ma > long_ma)
    {
        // 新規のポジションを取る
        if(current_position == 0)
        {
            // 買い注文を発注する
            int ticket = ExecuteTrade(BUY, lots, stop_loss, take_profit);
            if(ticket > 0)
            {
                current_position++;
            }
        }
    }

    // 現在の移動平均線を保存する
    prev_short_ma = short_ma;
    prev_long_ma = long_ma;
}

void OnDeinit(const int reason)
{
    // EAの終了処理をここに書く
}

ようやくコンパイルが通りました!自分で作った方が早かったんじゃないか説まであります(苦笑)

あとはこれが正しく動作するかどうかです。

ノートレード‥。どういうことでしょうか。原因を突き止める気力はありません。(時間の無駄!)

素直にゼロから作ったほうが早かったのでは‥?と思ってゼロから作ってみようと思ったのですが、これもまたエラーが多くて‥。

MQL5の仕様変更によるものなのか、MQL4で作るよりも修正が大変でした。(修正せずに放棄しました。素直にMQL4で作りましょう‥。)

前回の記事では「MQL5の方を使ったほうが良さそう」とか書いたのですがあれは嘘ですね‥。修正しておきます‥。

まとめ

現段階の、無料で使えるChatGPT(Ver 3.5)はMQL5の知識が古いためか正しく動作しないため、MQL4を使うよりも修正が困難。

MQL4からMQL5への変換は、自分で変換をした方が確実でした‥。

楽ができるのではと期待したんですがダメでした‥、という話です‥。

追記

最近、Google BardというChatGPTの対抗馬が日本でも使えるようになったとのことで、試してみましたが、こちらもMQL5は正しく生成してくれませんでした。(そもそもMQLですら無いようでした)

ChatGPT4も試してみましたが、こちらも微妙でした。トレードにcTradeクラスを使っているので「新しい仕様」に対応しているようでしたが、CMovingAveragesというクラスも使っていて、これがエラーの原因になりました。ググっても出てきませんし、どこから出てきたのかさっぱり‥。

MoveingAverage.mqhをインクルードしていたのでそれなんでしょうけど、CMovingAveragesが定義されたMoveingAverage.mqhなんてどこにあるんでしょうか‥。(どこで学習して覚えたのだろうか‥)

というわけで、今調べた時点ではGoogle BardやChatGPT4でも簡単にはいかないようです。

コメント

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