ChatGPTFX自動売買(EA)の作り方MQL4MQL5

チャット型AI(ChatGPT)に、MT4のEAをMT5のEAに変換してもらってみた【GPT-3.5編】

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

広告

ChatGPTは、OpenAIによって提供されているチャット型AIです。

どんな質問にもそれなりに回答してくれる、さらにはプログラミングスキルも兼ね備えている、とのことで、以下、ChatGPTとの対話形式も取り入れて話を進めます。

Q:MQL4で書かれたEAを提供しますので、そのロジックを解読・理解して、MQL5で書き直すことは出来ますか?
A:はい、MQL4で書かれたEAのロジックを理解して、MQL5で書き直すことは可能です。MQL4とMQL5は類似しているため、大部分のロジックをそのまま移植することができますが、いくつかの違いもありますので注意が必要です。MQL5のドキュメンテーションを読んで理解することが望ましいです。
出だしは順調な回答です。もしこれが実現出来るのであれば、MQL4に慣れすぎてMQL5にはなかなか移行出来ないEA開発者(プログラマー)にとっては、夢のようなツールではないでしょうか。
ということで今回は、ChatGPTにMT4(MQL4)のEAをMT5(MQL5)のEAに変換してもらうことにしましょう。
この記事で用いているChatGPTはGPT-3.5です。より進化したGPT-4で同様のことを行っている記事もございますのでよろしければご覧ください。
広告

MT4のEAをChatGPTに解読してもらう

今回は、以下の記事で作成したEAを使います。

まずは、Chat GPTがこのEAのロジックを読めるか確認してみます。

Q:以下は、MQL4で書かれたEAです。どのようなロジックか解読して、詳細を説明していただけるでしょうか。

<実際のコードは省略>

A:
このEAは、MetaTrader 4 (MQL4) で書かれたFXトレードのExpert Advisor (EA) です。EAは自動トレードを行うプログラムです。このEAは、一定のロジックに基づいて、FX市場での買い・売り注文を自動的に実行します。

  • 入力:
    • first_lot: 初期ロット数
    • nanpin_range: ナンピン幅
    • profit_target: 利益目標
    • magic_number: マジックナンバー
    • slippage: スリッページ
  • ロジック:
    1. 現在のポジションを確認します。買い・売りのポジション数、およびそれぞれのポジションの含み損益を計算します。
    2. 買い・売りのいずれかのポジションがない場合、新規エントリー注文を実行します。
    3. 売り・買いのいずれかのポジションがあり、含み損益が一定のレンジに達した場合、決済注文を実行します。

このEAは、買い・売りのポジションを自動的に実行するものですが、実際の取引には様々なリスクが伴いますので、取引には十分な知識と経験が必要です。

概要をきちんと説明してくれています。正しく理解出来ているようです。

ロジックを指定してMT5のEAを作成してもらう

続けて、ChatGPTに答えてもらったロジックでそのままMT5のEAの作成をお願いしてみます。

Q:以下のロジックのEAをMQL5のコードでお願いします。

  • 入力:
    • first_lot: 初期ロット数
    • nanpin_range: ナンピン幅
    • profit_target: 利益目標
    • magic_number: マジックナンバー
    • slippage: スリッページ
  • ロジック:
    1. 現在のポジションを確認します。買い・売りのポジション数、およびそれぞれのポジションの含み損益を計算します。
    2. 買い・売りのいずれかのポジションがない場合、新規エントリー注文を実行します。
    3. 売り・買いのいずれかのポジションがあり、含み損益が一定のレンジに達した場合、決済注文を実行します。
A:以下がMQL5による実装の例です。
#include <Trade/Trade.mqh>

input double first_lot = 0.1;
input double nanpin_range = 20.0;
input double profit_target = 100.0;
input int magic_number = 12345;
input int slippage = 3;

int start()
{
double lot = first_lot;
double balance = AccountBalance();
int total_buy = 0, total_sell = 0;
double buy_profit = 0.0, sell_profit = 0.0;
int ticket_buy = 0, ticket_sell = 0;

for (int i = OrdersTotal() - 1; i >= 0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false)
continue;

if (OrderMagicNumber() != magic_number)
continue;

if (OrderType() == OP_BUY)
{
total_buy++;
buy_profit += OrderProfit();
if (total_buy == 1)
ticket_buy = OrderTicket();
}
else if (OrderType() == OP_SELL)
{
total_sell++;
sell_profit += OrderProfit();
if (total_sell == 1)
ticket_sell = OrderTicket();
}
}

if (total_buy == 0 && total_sell == 0)
{
int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, slippage, 0, 0, "", magic_number, 0, Green);
if (ticket < 0)
Print("OrderSend failed with error ", GetLastError());
}
else if (total_buy > 0 && buy_profit >= nanpin_range)
{
if (OrderClose(ticket_buy, lot, Bid, slippage, Red))
Print("OrderClose buy successful");
else
Print("OrderClose buy failed with error ", GetLastError());
}
else if (total_sell > 0 && sell_profit >= nanpin_range)
{
if (OrderClose(ticket_sell, lot, Ask, slippage, Blue))
Print("OrderClose sell successful");
else
Print("OrderClose sell failed with error ", GetLastError());
}

return (0);
}
注意:このコードはテスト用であり、実際のトレードに使用する前に必ずテストすることが推奨されます。
それなりな回答が返ってきました。
ただし、そのままコンパイルしてみると、「46 errors, 6 warnings」でした。残念。

エラー原因を聞いてみる。

ひとまず、最初のエラーについて聞いてみます。
Q:AccountBalance();がエラーになります。

A:

AccountBalance() 関数は MQL4 の関数であり、MQL5 では使用できません。代わりに AccountInfoDouble(ACCOUNT_BALANCE) 関数を使用してください。

次のように修正します。

double balance = AccountInfoDouble(ACCOUNT_BALANCE);

あれ。MQL5でお願いしたつもりだったのですが。。

改めて聞いたら「その関数はMQL5では使用出来ない」と認識し直して、修正してくれたようです。このあたりがまだまだChatGPTの実力不足なのでしょうか。ただ後から修正してくれるだけでも良しとしましょうか。

該当部分を書き換えてみたところ、その部分のエラーは解消されました。素晴らしい。

ただ、この進め方だと残りのエラー解消にも時間がかかりそうなので、もう少しアプローチを変えてみます。

MQL4のコードをそのまま渡してみる

これまでの経験から、どうやらChatGPTはOrderSelect関数をMQL4で書いてしまう癖がある様です。MT5のOrderSelect関数を使う場合は引数がチケットだけのはずですが、そこで必ずエラーになります。

MQL4のコードを提示して変換をお願い

次に、以下の質問を投げてみます。

Q:以下は、MQL4で書かれたEAです。MQL4の関数ではなく、MQL5の関数を使うことによって、MT5用のEAに作り直せるでしょうか。

<実際のコードは省略>

A:はい、MQL4のコードをMQL5に移植することはできます。しかし、MQL4とMQL5の関数名や引数、書き方などに違いがあるため、変更が必要になります。例えば、MQL4の「OrderSelect」関数はMQL5で「OrderSelect」関数という名前では使用できないため、「OrderSelect」関数を「OrderSelect」関数に変更する必要があります。また、MQL4で使用されている変数型や定数などもMQL5でも同じように使用できますが、新しいMQL5の変数型や定数も利用することができます。
しまった。「作り直せるでしょうか」という曖昧な表現をしてしまったので、「作り直してください」ではなく、「作り直せるか答えてください」と受け取ってしまったようです。
しかも、「OrderSelect」関数は使用できないため、「OrderSelect」関数を「OrderSelect」関数に変更する必要があります。という少し混乱した言い回しになってしまいます。少し失敗です。

表現を変えて質問をやり直す

以下のように、今度は明確に書き直しを指示してみました。

Q:以下は、MQL4で書かれたEAです。MQL4の関数ではなく、MQL5の関数を使ってコードを書き直してください。

<実際のコードは省略>

A:以下は、書き直したMQL5のEAです。

#property copyright "Copyright 2022, nanpin-martin.com"
#property link "https://nanpin-martin.com/"

input double first_lot = 0.01;
input double nanpin_range = 200;
input double profit_target = 143;
input int magic_number = 10001;
int ticket_number;
double slippage = 10;

void OnTick()
{
int cnt;
int current_buy_position = -1;
int current_sell_position = -1;
int buy_position = 0;
int sell_position = 0;
double buy_profit = 0;
double sell_profit = 0;

for(cnt = 0; cnt < PositionsTotal(); cnt++)
{
if(!PositionSelect(cnt))
continue;
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
if(PositionGetInteger(POSITION_TYPE) == TRADE_ACTION_BUY)
{
current_buy_position = cnt;
buy_position++;
buy_profit += PositionGetDouble(POSITION_PROFIT);
}
if(PositionGetInteger(POSITION_TYPE) == TRADE_ACTION_SELL)
{
current_sell_position = cnt;
sell_position++;
sell_profit += PositionGetDouble(POSITION_PROFIT);
}
}

if(buy_position == 0)
{
ticket_number = OrderSend(
Symbol(),
TRADE_ACTION_BUY,
first_lot,
Ask,
slippage,
0,
0,
"first_buy",
magic_number,
0,
clrBlue
);
}
if(sell_position == 0)
{
ticket_number = OrderSend(
Symbol(),
TRADE_ACTION_SELL,
first_lot,
Bid,
slippage,
0,
0,
"first_sell",
magic_number,
0,
clrBlue
);
}
}
OrderSelect関数だった箇所が、PositionSelect関数になっていて、以前よりは良い感じに見えます。
ただし、そのままコンパイルしてみたところ、「8 errors, 1 warnings」でした。でも以前よりは惜しい。
中身を見てみると、先ほどもそうなのですが、OrderSend関数をMQL4で書いてしまっているようです。
OrderSend関数については、MQL4とMQL5でだいぶ異なってくるので、この辺りをChatGPTはまだまだ学習しきれていない様子が伺えます。

OrderSend関数の変換に特化してもう少し詰めてみる

色々と質問方法を変えてみたりしたのですが、なかなか良い感じに使える状態に到達しませんでした。以下は、コード部分を省略して、ChatGPTとのやり取りだけ少しご紹介します。

Q:以下は、MQL4における成行注文のコードです、MQL5用のOrderSend関数を使って書き直してください。

A:以下がMQL5用のOrderSend関数に書き直したコードです。

Q:OP_BUYがエラーになります

A:このエラーは、「OP_BUY」という識別子が定義されていないというエラーです。MQL5では「TRADE_ACTION_BUY」を使用する必要があります。

正しいコードは次のようになります。

Q:’OrderSend’ – wrong parameters countというエラーが出ます。修正できますか?

A:これは引数の数が不正です。正しい引数の数に揃えて、OrderSend関数を修正することが必要です。正しいOrderSend関数の例を以下に示します:

Q:以下はMQL5のOrderSend関数のコードです。「’OrderSend’ – wrong parameters count」というコンパイルエラーになります。修正してください
A:これでは正常に動作しません。OrderSend関数には引数が11個必要です。 以下のように修正します。
Q:これはMQL4ではなく、MQL5のコードですか?
A:はい、MQL5のコードです。
Q:まだ同様のエラーになります。他に修正点はありませんか?

A:はい、あります。MQL5のOrderSend関数には12つの引数が必要ですが、上記のコードでは10つしか指定されていません。

以下が正しいコードになりますので、参考にしてください。

Q:引数が12個必要なのに、11個になっていますか?

A:はい、その通りです。OrderSend関数には12個の引数が必要ですが、現在のコードでは11個しか指定されていません。正しいコードは以下のようになります。

と、少し謎なやり取りも挟みつつ、結局のところ永遠にMQL4仕様のOrderSend関数を繰り返すのみ、という感じでした。残念ながら、MQL5で使える感じには仕上げることができませんでした。

MQL5版のナンピンマーチンEAコード

以上の通り、いろいろと試行錯誤してみましたが、ChatGPTだけの実力ではMT4(MQL4)のコードをMT5(MQL5)のコードに変換というのは現時点ではなかなか厳しいようです。

以下は、ChatGPTに人力を”少しだけ”加えて、協力して作り上げたコードになります。

//+------------------------------------------------------------------+
//| nanpin-martin.mq5 |
//| Copyright 2022, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, nanpin-martin.com"
#property link "https://nanpin-martin.com/"

input double first_lot = 0.01;
input double nanpin_range = 200;
input double profit_target = 143;
input int magic_number = 10001;
int ticket_number;
double slippage = 10;

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick()
{
int buy_position = 0;
int sell_position = 0;
double buy_profit = 0.0;
double sell_profit = 0.0;
double current_buy_lot = 0.0;
double current_sell_lot = 0.0;
double current_buy_price = 0.0;
double current_sell_price = 0.0;

for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i)!="")
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
buy_position++;
buy_profit += PositionGetDouble(POSITION_PROFIT);
current_buy_lot = PositionGetDouble(POSITION_VOLUME);
current_buy_price = PositionGetDouble(POSITION_PRICE_OPEN);
}
else
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
sell_position++;
sell_profit += PositionGetDouble(POSITION_PROFIT);
current_sell_lot = PositionGetDouble(POSITION_VOLUME);
current_sell_price = PositionGetDouble(POSITION_PRICE_OPEN);
}
}
}


MqlTick last_tick;
SymbolInfoTick(_Symbol,last_tick);

double Ask=last_tick.ask;
double Bid=last_tick.bid;

if(buy_position == 0)
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_BUY; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = first_lot; // ロット数
request.price = Ask;// 注文価格
request.sl = 0; // ストップロス価格
request.tp = 0; // リミット価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.comment = "first_buy"; // コメント
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);

}
if(sell_position == 0)
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_SELL; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = first_lot; // ロット数
request.price = Bid;// 注文価格
request.sl = 0; // ストップロス価格
request.tp = 0; // リミット価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.comment = "first_sell"; // コメント
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);

}


//+----追加エントリー(ナンピン)注文----------------------------------------+

if(buy_position > 0)
{
if(Ask < current_buy_price - nanpin_range * Point()) //現在価格がナンピン幅に達しているか
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_BUY; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = round(current_buy_lot*1.5*100)/100; // ロット数
request.price = Ask;// 注文価格
request.sl = 0; // ストップロス価格
request.tp = 0; // リミット価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.comment = "nanpin_buy"; // コメント
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);
}


}


if(sell_position > 0)
{
if(Bid > current_sell_price + nanpin_range * Point())
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_SELL; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = round(current_sell_lot*1.5*100)/100; // ロット数
request.price = Bid;// 注文価格
request.sl = 0; // ストップロス価格
request.tp = 0; // リミット価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.comment = "nanpin_sell"; // コメント
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);


}
}

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

//+----ポジションクローズ注文----------------------------------------------+

if(buy_position>0&&buy_profit>profit_target*buy_position)
{
buyClose();//すべてbuyポジションをクローズ
}

if(sell_position>0&&sell_profit>profit_target*sell_position)
{
sellClose();//すべてsellポジションをクローズ
}

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

}
//+------------------------------------------------------------------+
//| buyポジションをクローズする関数 |
//+------------------------------------------------------------------+
void buyClose()
{

for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i)!="")
{
if(PositionGetInteger(POSITION_MAGIC)==magic_number)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.position =PositionGetTicket(i);
request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_SELL; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = PositionGetDouble(POSITION_VOLUME); // ロット数
request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);// 注文価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);


}

}
}
}
}


//+------------------------------------------------------------------+
//| sellポジションをクローズする関数 |
//+------------------------------------------------------------------+
void sellClose()
{

for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i)!="")
{
if(PositionGetInteger(POSITION_MAGIC)==magic_number)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{

MqlTradeRequest request = {};
MqlTradeResult result = {};

request.position =PositionGetTicket(i);
request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_BUY; // 注文タイプ
request.magic = magic_number; // マジックナンバー(識別用)
request.symbol = Symbol(); // 通貨ペア名
request.volume = PositionGetDouble(POSITION_VOLUME); // ロット数
request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);// 注文価格
request.deviation = slippage; // スリッページ
request.expiration = 0; // 有効期限
request.type_filling = ORDER_FILLING_IOC;

OrderSend(request, result);


}

}
}
}
}
//+------------------------------------------------------------------+

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

//+------------------------------------------------------------------+
コンパイルしてみたところエラーはなし、バックテストもしてみましたが、それなりに問題なく動きました。
詳しいロジックの解説は、以下の記事をご覧ください。

このまま使うこともおそらく可能だと思いますが、ご利用の際は、利用者ご自身の責任の上でお願いします。

まとめ

以前の記事でも見た通り、さらに今回はもう少し深く突っ込んで見ましたが、やはりChatGPTさんはMQL4の方が得意で、MQL5の方は苦手な印象は変わりませんでした。

「MQL4のコードをMQL5に変換してくれる夢のようなツール」というにはまだ少し早いのかもしれません。

ただ、おそらくChatGPTも学習して進化し続けているのかと思いますので、いずれそのような時期が訪れることにも期待します。

また、質問の仕方によってはMQL5開発のサポートとしては十分に利用価値はあるのかなと思っています。

最後に、こんな質問をしてみました。

Q:あなたはこれから学習し続けて、進化して、今よりもMQL5のプログラミング能力が向上していく可能性はありますか?
A:はい、それは可能です。AIモデルは学習することで進化し、より良い結果を生み出すことができます。しかし、それには常に新しいデータとトレーニングを継続することが必要です。そのため、私がMQL5のプログラミング能力を向上させるためには、常に学習することが重要です。

という良いお返事が得られたところで、今回は終了にしたいと思います。

「AIは永遠に学習し続けられる」というのも大いなる強みですね。

他にも試してみたら、またご報告します。

BingAIでMT5用EAを作成してみた

ChatGPTで他にも試してみた

キャッシュバック口座の開設

作成したEAを利用して実際に運用する際は、通常の口座開設ではなく、キャッシュバック口座を開設するのがおすすめです。以下の記事で、キャッシュバックサイト経由で海外FX口座を開設する際のメリットとデメリットをまとめていますのでご覧ください。

利用者の特性に応じて、リアル口座をどのように開設するのが最適かを考える参考になると思います。

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