Can the latest ChatGPT (GPT-4) convert MT4 EAs to MT5 EAs? A verification study

ChatGPT

ChatGPT is a chatbot AI provided by OpenAI. It is known for its programming skills necessary for EA development.

In March 2023, GPT-4 was implemented in ChatGPT, and I’d like to compare its progress with MQL5 programming skills.

By the way, I asked ChatGPT what GPT-4 is.

Please briefly explain the difference between GPT-4 and GPT-3.5.
The difference between GPT-4 and GPT-3.5 is that GPT-4 has been trained on a larger dataset, improving its contextual understanding, consistency, and accuracy. As a result, GPT-4 generally outperforms GPT-3.5.

In a previous article, I tried coding MQL5 with GPT-3.5, but compared to MQL4, MQL5 seemed to be more challenging and I struggled a lot.

https://nanpin-martin.com/chatgpt_003/

So this time, let’s have the latest evolved ChatGPT (GPT-4) convert the MT4 EA to an MT5 EA.

Converting MQL4 code to MQL5

This time, we will use the MT4 EA code (MQL4) created in the following article as input.

https://nanpin-martin.com/ea-coding_mql4_001/

Paste the entire code as follows and ask ChatGPT to convert it to an MT5 EA.

Input: MQL4 code

Please convert the following MQL4 code to MQL5 so that it can be compiled in MT5.

//+------------------------------------------------------------------+
//| nanpin-martin.mq4 |
//| ` Copyright 2022, nanpin-martin.com |
//| "https://nanpin-martin.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
//+------------------------------------------------------------------+
//| Input settings |
//+------------------------------------------------------------------+

input double first_lot = 0.01;//Initial lot
input double nanpin_range = 200;//Nanpin width
input double profit_target = 143;//Profit target
input int magic_number = 10001; //Magic number
static int ticket_number;//Ticket number
double slippage = 10;//Slippage

//+------------------------------------------------------------------+
//| Loop processing |
//+------------------------------------------------------------------+
void OnTick()
{

//+----Variable definition--------------------------------------------+

int cnt;
int current_buy_position;//Latest buy position
int current_sell_position;//Latest sell position
int buy_position;//Number of buy positions
int sell_position;//Number of sell positions
double buy_profit;//Buy position's unrealized profit/loss
double sell_profit;//Sell position's unrealized profit/loss

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

//+----Confirming positions-------------------------------------------+

buy_position=0;//Initializing the number of buy positions
sell_position=0;//Initializing the number of sell positions
current_buy_position=-1;//Initializing the latest buy position
current_sell_position=-1;//Initializing the latest sell position

for(cnt=0;cnt<OrdersTotal();cnt++)//Confirming positions { if(OrderSelect(cnt,SELECT_BY_POS)==false)continue; if(OrderMagicNumber()!=magic_number)continue; if(OrderType()==OP_BUY) { current_buy_position=cnt; buy_position+=1; buy_profit=buy_profit+OrderProfit(); };//Confirming buy positions if(OrderType()==OP_SELL) { current_sell_position=cnt; sell_position+=1; sell_profit=sell_profit+OrderProfit(); };//Confirming sell positions } //+------------------------------------------------------------------+ //+----New entry order------------------------------------------------+ if(buy_position==0)//If no buy position is held { ticket_number=OrderSend( Symbol(), //Currency pair OP_BUY, //buy:OP_BUY, sell:OP_SELL first_lot, //Number of lots Ask, //Order price slippage, //Slippage 0, //Settlement stop order 0, //Settlement limit order "first_buy", //Order comment magic_number, //Magic number 0, //Order expiration Blue //Arrow color ); } if(sell_position==0)//If no sell position is held { ticket_number=OrderSend( Symbol(), //Currency pair OP_SELL, //buy:OP_BUY, sell:OP_SELL first_lot, //Number of lots Bid, //Order price slippage, //Slippage 0, //Settlement stop order 0, //Settlement limit order "first_sell", //Order comment magic_number, //Magic number 0, //Order expiration Red //Arrow color ); } //+------------------------------------------------------------------+ //+----Additional entry (Nanpin) order----------------------------------------+ if(buy_position>0) //If holding one or more buy positions
{
OrderSelect(current_buy_position,SELECT_BY_POS); //Select the latest buy position
if(Ask<(OrderOpenPrice()-nanpin_range*Point)) //If the current price reaches the Nanpin width { ticket_number=OrderSend( Symbol(), //Currency pair OP_BUY, //buy:OP_BUY, sell:OP_SELL round(OrderLots()1.5100)/100, //Number of lots Ask, //Order price slippage, //Slippage 0, //Settlement stop order 0, //Settlement limit order "nanpin_buy", //Order comment magic_number, //Magic number 0, //Order expiration Blue //Arrow color ); } } if(sell_position>0) //If holding one or more sell positions
{
OrderSelect(current_sell_position,SELECT_BY_POS); //Select the latest sell position
if(Bid>(OrderOpenPrice()+nanpin_range*Point)) //If the current price reaches the Nanpin width
{
ticket_number=OrderSend(
Symbol(), //Currency pair
OP_SELL, //buy:OP_BUY, sell:OP_SELL
round(OrderLots()1.5100)/100, //Number of lots
Bid, //Order price
slippage, //Slippage
0, //Settlement stop order
0, //Settlement limit order
"nanpin_sell", //Order comment
magic_number, //Magic number
0, //Order expiration
Red //Arrow color
);

}
}

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

//+----Position Close Order----------------------------------------------+

if(buy_position>0&&buy_profit>profit_target*buy_position)
{
buyClose(Red);//Close all buy positions
}

if(sell_position>0&&sell_profit>profit_target*sell_position)
{
sellClose(Blue);//Close all sell positions
}

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

}

//+------------------------------------------------------------------+
//| Loop process end |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Function to close positions |
//+------------------------------------------------------------------+

//+----Function to close buy positions----------------------------------------+
void buyClose(color clr)
{
int i;
for(i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
continue;
if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=magic_number)
continue;
if(OrderType()==OP_BUY)
OrderClose(OrderTicket(),OrderLots(),Bid,NormalizeDouble(slippage,0),clr);
}
}

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

//+----Function to close sell positions---------------------------------------+
void sellClose(color clr)
{
int i;
for(i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
continue;
if(OrderSymbol()!=Symbol()||OrderMagicNumber()!=magic_number)
continue;
if(OrderType()==OP_SELL)
OrderClose(OrderTicket(),OrderLots(),Ask,NormalizeDouble(slippage,0),clr);
}
}

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

Output: MQL5 Code

As follows, I received a reply immediately.

The following code has converted the MQL4 code to MQL5 and made it compilable on MT5.

//+------------------------------------------------------------------+
//| nanpin-martin.mq5 |
//| ` Copyright 2022, nanpin-martin.com |
//| "https://nanpin-martin.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Setting Input |
//+------------------------------------------------------------------+

input double first_lot = 0.01; //Initial lot
input double nanpin_range = 200; //Nanpin width
input double profit_target = 143; //Profit target
input int magic_number = 10001; //Magic number
static int ticket_number; //Ticket number
double slippage = 10; //Slippage

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| Loop processing |
//+------------------------------------------------------------------+
void OnTick()
{

//+----Variable definition-----------------------------------------------------+

int cnt;
int current_buy_position; //Latest buy position
int current_sell_position; //Latest sell position
int buy_position; //Number of buy positions
int sell_position; //Number of sell positions
double buy_profit; //Unrealized profit and loss of buy position
double sell_profit; //Unrealized profit and loss of sell position

MqlTradeRequest request;
MqlTradeResult result;

//+------------------------------------------------------------------+
//+----Checking Positions--------------------------------------------------+

buy_position = 0; //initializing the number of buy positions
sell_position = 0; //initializing the number of sell positions
current_buy_position = -1; //initializing the latest buy position
current_sell_position = -1; //initializing the latest sell position

for(cnt = 0; cnt < PositionsTotal(); cnt++) //Checking positions { ulong position_ticket = PositionGetTicket(cnt); if(PositionGetInteger(POSITION_MAGIC) != magic_number) continue; if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { current_buy_position = cnt; buy_position++; buy_profit = buy_profit + PositionGetDouble(POSITION_PROFIT); }; //Checking buy positions if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { current_sell_position = cnt; sell_position++; sell_profit = sell_profit + PositionGetDouble(POSITION_PROFIT); }; //Checking sell positions } //+------------------------------------------------------------------+ //+----New Entry Orders------------------------------------------------+ if(buy_position == 0) //if there are no buy positions { ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = Symbol(); request.volume = first_lot; request.type = ORDER_TYPE_BUY; request.price = NormalizeDouble(Ask, _Digits); request.sl = 0; request.tp = 0; request.deviation = slippage; request.magic = magic_number; request.comment = "first_buy"; OrderSend(request, result); } if(sell_position == 0) //if there are no sell positions { ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = Symbol(); request.volume = first_lot; request.type = ORDER_TYPE_SELL; request.price = NormalizeDouble(Bid, _Digits); request.sl = 0; request.tp = 0; request.deviation = slippage; request.magic = magic_number; request.comment = "first_sell"; OrderSend(request, result); } //+------------------------------------------------------------------+ //+----Additional entry (Averaging) order----------------------------------------+ if(buy_position > 0) //if holding more than one buy position
{
PositionSelectByTicket(PositionGetTicket(current_buy_position)); //select the latest buy position
if(Ask < (PositionGetDouble(POSITION_PRICE_OPEN) - nanpin_range * _Point)) //if the current price has reached the averaging range { ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = Symbol(); request.volume = MathRound(PositionGetDouble(POSITION_VOLUME) * 1.5 * 100) / 100; request.type = ORDER_TYPE_BUY; request.price = NormalizeDouble(Ask, _Digits); request.sl = 0; request.tp = 0; request.deviation = slippage; request.magic = magic_number; request.comment = "nanpin_buy"; OrderSend(request, result); } } if(sell_position > 0) //if holding more than one sell position
{
PositionSelectByTicket(PositionGetTicket(current_sell_position)); //select the latest sell position
if(Bid > (PositionGetDouble(POSITION_PRICE_OPEN) + nanpin_range * _Point)) //if the current price has reached the averaging range
{
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = MathRound(PositionGetDouble(POSITION_VOLUME) * 1.5 * 100) / 100;
request.type = ORDER_TYPE_SELL;
request.price = NormalizeDouble(Bid, _Digits);
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.comment = "nanpin_sell";
OrderSend(request, result);
}
}

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

//+----Position close order----------------------------------------------+

if(buy_position > 0 && buy_profit > profit_target * buy_position)
{
buyClose(clrRed); //close all buy positions
}

if(sell_position > 0 && sell_profit > profit_target * sell_position)
{
sellClose(clrBlue); //close all sell positions
}

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

}

//+------------------------------------------------------------------+
//| Loop processing end |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Function to close positions |
//+------------------------------------------------------------------+

//+----Function to close buy positions----------------------------------------+
void buyClose(color clr)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong position_ticket = PositionGetTicket(i);
if(PositionSelectByTicket(position_ticket) == false)
continue;
if(PositionGetSymbol(position_ticket) != Symbol() || PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.position = position_ticket;
request.type = ORDER_TYPE_SELL;
request.price = NormalizeDouble(Bid, _Digits);
request.volume = PositionGetDouble(POSITION_VOLUME);
request.deviation = slippage;
request.comment = "Close buy position";
request.arrow_color = clr;
OrderSend(request, result);
}
}
}

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

//+----Function to close sell positions---------------------------------------+
void sellClose(color clr)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong position_ticket = PositionGetTicket(i);
if(PositionSelectByTicket(position_ticket) == false)
continue;
if(PositionGetSymbol(position_ticket) != Symbol() || PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.position = position_ticket;
request.type = ORDER_TYPE_BUY;
request.price = NormalizeDouble(Ask, _Digits);
request.volume = PositionGetDouble(POSITION_VOLUME);
request.deviation = slippage;
request.comment = "Close sell position";
request.arrow_color = clr;
OrderSend(request, result);
}
}
}

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

This modified code is updated with MQL5 syntax and functions, allowing it to compile correctly in MT5. To use it on the MT5 platform, copy and paste this code into a new MQL5 file.

I have noticed that GPT-3.5 tends to use the OrderSend function in a more MQL4-like way, which doesn’t always work well with MQL5 specifications. However, GPT-4 seems to have improved in this regard, which is a sign of evolution.

Compilation error locations

However, when I pasted the code I received from ChatGPT and tried to compile it, I got multiple errors: “40 errors, 14 warnings.”

Enumeration of Error Contents

The content was about Ask, Bid, and request errors, so I will list them as follows to check.

Multiple errors occurred as follows. ‘Ask’ – undeclared identifier
‘Bid’ – undeclared identifier
‘request’ – undeclared identifier
‘request’ – variable expected
‘request’ – cannot convert enum

I apologize for the confusion. Please try the corrected code below.<Code is omitted>

Please try the above corrected code. This code should be converted to the MQL5 language and can be compiled in MT5. If you have any questions, please feel free to contact us.

The code here has been slightly simplified. The content includes the conversion of the parts that were using Ask and Bid to send orders to use trade.Buy() and trade.Sell() functions instead.

Error in Buy() Function

However, now an error occurs in that part.

It seems that there is an error in the following code.

trade.Buy(first_lot, _Symbol, ask, slippage, 0, 0, "first_buy", magic_number);

‘Buy’ – wrong parameters count

My apologies. In MQL5, the parameters of the CTrade class’s Buy() method are different. Please modify it as follows:

trade.Buy(first_lot, _Symbol, ask, 0, 0, 0, magic_number, "first_buy");

Similarly, the parameters of the Sell() method also need to be corrected.

trade.Sell(first_lot, _Symbol, bid, 0, 0, 0, magic_number, "first_sell");

These modifications should resolve the error. Please check.

Providing the error details will help us find a solution quickly.
However, even after making the specified modifications, the error was not resolved.

Perhaps my question was too vague, and the fact that “‘Buy’ – wrong parameters count” is the error content did not come across well.

I will try to clarify a little more.

Since the error is ‘Buy’ – wrong parameters count, I think the modification content is different.

I apologize.CTradeWhen using theBuy()andSell()methods of the class, please modify the code as follows:

MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.type_filling = ORDER_FILLING_FOK;

// For Buy orders
request.type = ORDER_TYPE_BUY;
request.volume = first_lot;
request.price = ask;
request.comment = "first_buy";
if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}

// For Sell orders
request.type = ORDER_TYPE_SELL;
request.volume = first_lot;
request.price = bid;
request.comment = "first_sell";
if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}

These modifications should resolve the error. Please check.

I’m not sure if my explanation was clear this time, or if they found improvements on their own, but they have returned to the request format for the order submission part of the code. It looks promising.

Completion of the Entire Code

So, I ask them to rewrite the code once more.

Considering the above, can you rewrite all the code?
Based on the above modifications, I have revised the entire code as follows.
//+------------------------------------------------------------------+
//| nanpin-martin.mq5 |
//| ` Copyright 2022, nanpin-martin.com |
//| "https://nanpin-martin.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh>
CTrade trade;

input double first_lot = 0.01; //Initial lot
input double nanpin_range = 200; //Nanpin width
input double profit_target = 143; //Profit target
input int magic_number = 10001; //Magic number
double slippage = 10; //Slippage

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
int current_buy_position; //Latest buy position
int current_sell_position; //Latest sell position
int buy_position; //Number of buy positions
int sell_position; //Number of sell positions
double buy_profit; //Unrealized profit and loss of buy positions
double sell_profit; //Unrealized profit and loss of sell positions
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

buy_position = 0;
sell_position = 0;
current_buy_position = -1;
current_sell_position = -1;

for(int cnt = 0; cnt < PositionsTotal(); cnt++)
{
ulong ticket = PositionGetTicket(cnt);
if(PositionSelectByTicket(ticket))
{
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
current_buy_position = cnt;
buy_position += 1;
buy_profit += PositionGetDouble(POSITION_PROFIT);
}
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
current_sell_position = cnt;
sell_position += 1;
sell_profit += PositionGetDouble(POSITION_PROFIT);
}
}
}

if(buy_position == 0)
{
MqlTradeRequest request;
MqlTradeResult result;

request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.type = ORDER_TYPE_BUY;
request.volume = first_lot;
request.price = ask;
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.type_filling = ORDER_FILLING_FOK;
request.comment = "first_buy";

if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}
}

if(sell_position == 0)
{
MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.type = ORDER_TYPE_SELL;
request.volume = first_lot;
request.price = bid;
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.type_filling = ORDER_FILLING_FOK;
request.comment = "first_sell";

if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}
}

if(buy_position > 0)
{
if(PositionSelectByTicket(PositionGetTicket(current_buy_position)))
{
if(ask < (PositionGetDouble(POSITION_PRICE_OPEN) - nanpin_range * _Point))
{
MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.type = ORDER_TYPE_BUY;
request.volume = NormalizeDouble(PositionGetDouble(POSITION_VOLUME) * 1.5, 2);
request.price = ask;
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.type_filling = ORDER_FILLING_FOK;
request.comment = "nanpin_buy";

if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}
}
}
}

if(sell_position > 0)
{
if(PositionSelectByTicket(PositionGetTicket(current_sell_position)))
{
if(bid > (PositionGetDouble(POSITION_PRICE_OPEN) + nanpin_range * _Point))
{
MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.type = ORDER_TYPE_SELL;
request.volume = NormalizeDouble(PositionGetDouble(POSITION_VOLUME) * 1.5, 2);
request.price = bid;
request.sl = 0;
request.tp = 0;
request.deviation = slippage;
request.magic = magic_number;
request.type_filling = ORDER_FILLING_FOK;
request.comment = "nanpin_sell";

if(!trade.OrderSend(request, result))
{
Print("OrderSend failed with error: ", GetLastError());
}
}
}
}

if(buy_position > 0 && buy_profit > profit_target * buy_position)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC) == magic_number)
{
trade.PositionClose(ticket, slippage);
}
}
}
}

if(sell_position > 0 && sell_profit > profit_target * sell_position)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC) == magic_number)
{
trade.PositionClose(ticket, slippage);
}
}
}
}
}
//+------------------------------------------------------------------+
It seems to have turned out well this time. When I compiled it, there were no errors.
During the GPT-3.5 era, no matter how many times I asked about the error, I couldn’t resolve it with just ChatGPT’s ability, so the self-solving ability has improved considerably. This is also where I can feel the evolution of GPT-4.

Performing a backtest with the created EA

Now that the compilation has been completed successfully, I will perform a backtest using the created MT5 EA.

Minor adjustments to place orders on XM

I tried backtesting on XMTrading‘s GOLD. Then, no orders were placed at all.
However, I had a rough idea about this point, so I asked a little leading question like this:
When I performed the backtest, I got the following error.
OrderSend failed with error: 4756
I think it’s probably because of ORDER_FILLING_FOK.
If you encounter error 4756 with OrderSend, it means the order type is not allowed. Please try changing ORDER_FILLING_FOK to ORDER_FILLING_IOC. The modified code will look like this:
   if (buy_position == 0)
   {
      MqlTradeRequest request;
      MqlTradeResult result;

      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.type = ORDER_TYPE_BUY;
      request.volume = first_lot;
      request.price = ask;
      request.sl = 0;
      request.tp = 0;
      request.deviation = slippage;
      request.magic = magic_number;
      request.type_filling = ORDER_FILLING_IOC;
      request.comment = "first_buy";

      if (!trade.OrderSend(request, result))
      {
         Print("OrderSend failed with error: ", GetLastError());
      }
   }

   if (sell_position == 0)
   {
      MqlTradeRequest request;
      MqlTradeResult result;

      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.type = ORDER_TYPE_SELL;
      request.volume = first_lot;
      request.price = bid;
      request.sl = 0;
      request.tp = 0;
      request.deviation = slippage;
      request.magic = magic_number;
      request.type_filling = ORDER_FILLING_IOC;
      request.comment = "first_sell";

      if (!trade.OrderSend(request, result))
      {
         Print("OrderSend failed with error: ", GetLastError());
      }
   }

With this, it is expected that error 4756 will be resolved. If the problem is not resolved, you will need to check the allowed order types on the server. In that case, you can use the SymbolInfoInteger() function to check the SYMBOL_FILLING_MODE.

Please feel free to contact us if you have any other questions or concerns.

As ChatGPT answered, in the case of XMTrading, orders can only be placed with ORDER_FILLING_IOC.
This might be a difficult part because I did not mention which FX broker’s account to use or any conditions.
However, since they are teaching me how to check the allowed order types on the server, I feel that I can solve the problem if I continue to ask questions to ChatGPT.

Completion of MT5 EA for XM

By the way, there are four instances of ORDER_FILLING_FOK in the entire code. Please change all of them to ORDER_FILLING_IOC. Just copy and paste the entire code, modify the four instances, and compile it to complete the XMTrading-compatible MT5 scalping-martingale EA.

Good backtest results

This is a backtest with the default settings using the compiled file.
The trading target is XMTrading‘s Standard account GOLD, and the backtest period is from 2022/11/1 to 2023/1/31, a total of 3 months.

With a winning rate of over 96% and a profit factor of 6.43, the graph shows a solid upward trend typical of scalping-martingale EAs. As it is performing as expected to some extent, it can be inferred that the logic has been implemented without any issues.

Summary

So far, most of the ChatGPT-related articles we have seen on this site were about GPT-3.5, but the impression was that while MQL4 could produce a reasonably high-quality output, MQL5 was quite underwhelming.
However, with the new GPT-4, this impression has changed considerably. While it didn’t produce perfect code in one shot, there was a strong sense that it could solve problems on its own with just a few hints about errors or issues, and even programming beginners have a good chance of creating MT5 EAs if they give proper instructions.

Additionally, it seems to be getting closer to the “dream tool that converts MQL4 code to MQL5“.

Difference between GPT-3.5 and GPT-4

Finally, I asked this question:

Please tell me the difference between GPT-3.5 and GPT-4 in terms of MQL5 coding ability.

I am an AI based on OpenAI’s GPT-4, and compared to GPT-3.5, my range of knowledge and contextual understanding have improved. However, there isn’t a significant difference between GPT-4 and GPT-3.5 in terms of MQL5 coding ability. Both can generate and analyze basic MQL5 code, but for advanced coding and optimization, specialized knowledge and experience may be required.Both models support programming languages, but their ability to handle code complexity and specific problems is limited compared to specialized programmers and developers. When addressing MQL5 coding problems, both GPT-4 and GPT-3.5 offer help assuming they have the appropriate knowledge, but consider seeking expert advice as well.

Thank you. Still, I felt that GPT-4 had better coding ability. Where do you think the evolutionary points are?

GPT-4 is trained on an even larger dataset compared to GPT-3.5, and has a broader range of knowledge and contextual understanding. As a result, it may generally feel that GPT-4 has superior coding ability than GPT-3.5. The evolutionary points are as follows:

  1. Larger dataset: GPT-4 has more information and knowledge, which may enable it to propose more appropriate solutions to coding problems.
  2. Contextual understanding: GPT-4 has improved its ability to understand context more accurately and provide appropriate responses and suggestions. This allows for better code generation and analysis in response to user questions.
  3. Consistency and accuracy: GPT-4 has improved its ability to provide more consistent answers and suggestions, which is especially beneficial when dealing with long conversations or complex problems.

However, GPT-4 is not perfect and its support for programming languages is still limited. In particular, for the latest information and advanced knowledge about specific programming languages or frameworks, it is recommended to consult experts and developers.

Just by looking at this answer, it seems that ChatGPT’s explanatory ability has improved a bit.
Since MQL5 is relatively new, it seems that GPT-4 has been able to learn and improve its skills in areas that GPT-3.5 couldn’t reach.

I will try more and report back later.

Comments

Copied title and URL