ChatGPTは、OpenAIによって提供されているチャット型AIです。
どんな質問にもそれなりに回答してくれる、さらにはプログラミングスキルも兼ね備えている、とのことで、以下、ChatGPTとの対話形式も取り入れて話を進めます。
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: スリッページ
- ロジック:
- 現在のポジションを確認します。買い・売りのポジション数、およびそれぞれのポジションの含み損益を計算します。
- 買い・売りのいずれかのポジションがない場合、新規エントリー注文を実行します。
- 売り・買いのいずれかのポジションがあり、含み損益が一定のレンジに達した場合、決済注文を実行します。
このEAは、買い・売りのポジションを自動的に実行するものですが、実際の取引には様々なリスクが伴いますので、取引には十分な知識と経験が必要です。
ロジックを指定してMT5のEAを作成してもらう
続けて、ChatGPTに答えてもらったロジックでそのままMT5のEAの作成をお願いしてみます。
- 入力:
- first_lot: 初期ロット数
- nanpin_range: ナンピン幅
- profit_target: 利益目標
- magic_number: マジックナンバー
- slippage: スリッページ
- ロジック:
- 現在のポジションを確認します。買い・売りのポジション数、およびそれぞれのポジションの含み損益を計算します。
- 買い・売りのいずれかのポジションがない場合、新規エントリー注文を実行します。
- 売り・買いのいずれかのポジションがあり、含み損益が一定のレンジに達した場合、決済注文を実行します。
#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);
}
エラー原因を聞いてみる。
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に作り直せるでしょうか。
<実際のコードは省略>
表現を変えて質問をやり直す
以下のように、今度は明確に書き直しを指示してみました。
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
);
}
}
OrderSend関数の変換に特化してもう少し詰めてみる
色々と質問方法を変えてみたりしたのですが、なかなか良い感じに使える状態に到達しませんでした。以下は、コード部分を省略して、ChatGPTとのやり取りだけ少しご紹介します。
A:以下がMQL5用のOrderSend関数に書き直したコードです。
A:このエラーは、「OP_BUY」という識別子が定義されていないというエラーです。MQL5では「TRADE_ACTION_BUY」を使用する必要があります。
正しいコードは次のようになります。
Q:’OrderSend’ – wrong parameters countというエラーが出ます。修正できますか?
A:これは引数の数が不正です。正しい引数の数に揃えて、OrderSend関数を修正することが必要です。正しいOrderSend関数の例を以下に示します:
A:はい、あります。MQL5のOrderSend関数には12つの引数が必要ですが、上記のコードでは10つしか指定されていません。
以下が正しいコードになりますので、参考にしてください。
A:はい、その通りです。OrderSend関数には12個の引数が必要ですが、現在のコードでは11個しか指定されていません。正しいコードは以下のようになります。
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開発のサポートとしては十分に利用価値はあるのかなと思っています。
最後に、こんな質問をしてみました。
という良いお返事が得られたところで、今回は終了にしたいと思います。
「AIは永遠に学習し続けられる」というのも大いなる強みですね。
他にも試してみたら、またご報告します。
BingAIでMT5用EAを作成してみた
ChatGPTで他にも試してみた



キャッシュバック口座の開設
作成したEAを利用して実際に運用する際は、通常の口座開設ではなく、キャッシュバック口座を開設するのがおすすめです。以下の記事で、キャッシュバックサイト経由で海外FX口座を開設する際のメリットとデメリットをまとめていますのでご覧ください。
利用者の特性に応じて、リアル口座をどのように開設するのが最適かを考える参考になると思います。