How do I add Order Comment to inputs so EA places a the comment in MT4 order form?

 

I have a binary options ea I want to use to trade MT4 binary options on Grand Capital MT4, but with that broker the expiration time needs to go in the Comment field in the Order Window (such as 1 for a 1 minute expiration).

The broker allows 1 minute expirations and higher.

But if you leave the comment field blank the default expiration time is on every hour, and on every 30 minutes pass the hour.

Since the ea can't place a order comment it keeps using the default expiration times.

How do I add a comment input to the ea (and to the code) so for example if the input is 1 the ea will place a 1 in the order comment so the order will open with a 1 minute expiration time (see screenshot)?

Is this even possible?

Below I added a simple binary options ea (a piece of junk gambling ea) that I created just for the purpose of posting here to see if someone can add a comment feature to it.

If you can add the comment feature to it I can see how you did it and transfer it to my main ea.

Thanks in advance.


#property copyright ""
#property link      ""
#property version   ""
#property description ""

#include <stdlib.mqh>
#include <stderror.mqh>

int MagicNumber = 123456;
extern double Investment_or_Lots = 0.1;
extern int BO_Expiration_Seconds = 60;
extern int Forex_Expiration_Minutes = 15; //maximum trade duration
extern int Period1 = 21;
extern int MA_Shift = 0;
extern int Candle_Close = 1;
int LotDigits; //initialized in OnInit
double MM_Martingale_ProfitFactor = 1;
extern int Use_Martingale = 3;
extern double MM_Martingale_LossFactor = 2;
bool MM_Martingale_RestartProfit = true;
bool MM_Martingale_RestartLoss = false;

int MaxSlippage = 3; //adjusted in OnInit
int MaxOpenTrades = 1;
int MaxLongTrades = 1;
int MaxShortTrades = 1;
int MaxPendingOrders = 1;
bool Hedging = true;
int OrderRetry = 5; //# of retries if sending order returns error
int OrderWait = 5; //# of seconds to wait if sending order returns error
double myPoint; //initialized in OnInit

void CloseByDuration(int sec) //close trades opened longer than sec seconds
  {
   if(!IsTradeAllowed()) return;
   bool success = false;
   int err;
   int total = OrdersTotal();
   for(int i = total-1; i >= 0; i--)
     {
      while(IsTradeContextBusy()) Sleep(100);
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() > 1 || OrderOpenTime() + sec > TimeCurrent()) continue;
      while(IsTradeContextBusy()) Sleep(100);
      RefreshRates();
      double price = Bid;
      if(OrderType() == OP_SELL)
         price = Ask;
      success = OrderClose(OrderTicket(), NormalizeDouble(OrderLots(), LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, clrWhite);
      if(!success)
        {
         err = GetLastError();
         myAlert("error", "OrderClose failed; error #"+err+" "+ErrorDescription(err));
        }
     }
   if(success) myAlert("order", "Orders closed by duration: "+Symbol()+" Magic #"+MagicNumber);
  }

double MM_Size() //martingale / anti-martingale
  {
   double lots = Investment_or_Lots;
   double MaxLot = MarketInfo(Symbol(), MODE_MAXLOT);
   double MinLot = MarketInfo(Symbol(), MODE_MINLOT);
   if(SelectLastHistoryTrade())
     {
      double orderprofit = OrderProfit();
      double orderlots = OrderLots();
      double boprofit = BOProfit(OrderTicket());
      if(orderprofit + boprofit > 0 && !MM_Martingale_RestartProfit)
         lots = orderlots * MM_Martingale_ProfitFactor;
      else if(orderprofit + boprofit < 0 && !MM_Martingale_RestartLoss)
         lots = orderlots * MM_Martingale_LossFactor;
      else if(orderprofit + boprofit == 0)
         lots = orderlots;
     }
   if(ConsecutiveLosses(Use_Martingale))
      lots = Investment_or_Lots;
   if(lots > MaxLot) lots = MaxLot;
   if(lots < MinLot) lots = MinLot;
   return(lots);
  }

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | BO MA EA @ "+Symbol()+","+Period()+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

int TradesCount(int type) //returns # of open trades for order type, current symbol and magic number
  {
   int result = 0;
   int total = OrdersTotal();
   for(int i = 0; i < total; i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      result++;
     }
   return(result);
  }

bool SelectLastHistoryTrade()
  {
   int lastOrder = -1;
   int total = OrdersHistoryTotal();
   for(int i = total-1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
        {
         lastOrder = i;
         break;
        }
     }
   return(lastOrder >= 0);
  }

double BOProfit(int ticket) //Binary Options profit
  {
   int total = OrdersHistoryTotal();
   for(int i = total-1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if(StringSubstr(OrderComment(), 0, 2) == "BO" && StringFind(OrderComment(), "#"+ticket+" ") >= 0)
         return OrderProfit();
     }
   return 0;
  }

bool ConsecutiveLosses(int n)
  {
   int count = 0;
   int total = OrdersHistoryTotal();
   for(int i = total-1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
        {
         double orderprofit = OrderProfit();
         double boprofit = BOProfit(OrderTicket());
         if(orderprofit + boprofit >= 0)
            break;
         count++;
        }
     }
   return(count >= n);
  }

int myOrderSend(int type, double price, double volume, string ordername) //send order, return ticket ("price" is irrelevant for market orders)
  {
   if(!IsTradeAllowed()) return(-1);
   int ticket = -1;
   int retries = 0;
   int err;
   int long_trades = TradesCount(OP_BUY);
   int short_trades = TradesCount(OP_SELL);
   int long_pending = TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP);
   int short_pending = TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP);
   string ordername_ = ordername;
   if(ordername != "")
      ordername_ = "("+ordername+")";
   //test Hedging
   if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0)))
     {
      myAlert("print", "Order"+ordername_+" not sent, hedging not allowed");
      return(-1);
     }
   //test maximum trades
   if((type % 2 == 0 && long_trades >= MaxLongTrades)
   || (type % 2 == 1 && short_trades >= MaxShortTrades)
   || (long_trades + short_trades >= MaxOpenTrades)
   || (type > 1 && long_pending + short_pending >= MaxPendingOrders))
     {
      myAlert("print", "Order"+ordername_+" not sent, maximum reached");
      return(-1);
     }
   //prepare to send order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   if(type == OP_BUY)
      price = Ask;
   else if(type == OP_SELL)
      price = Bid;
   else if(price < 0) //invalid price for pending order
     {
      myAlert("order", "Order"+ordername_+" not sent, invalid price for pending order");
   return(-1);
     }
   int clr = (type % 2 == 1) ? clrRed : clrBlue;
   while(ticket < 0 && retries < OrderRetry+1)
     {
      ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, ordername, MagicNumber, 0, clr);
      if(ticket < 0)
        {
         err = GetLastError();
         myAlert("print", "OrderSend"+ordername_+" error #"+err+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(ticket < 0)
     {
      myAlert("error", "OrderSend"+ordername_+" failed "+(OrderRetry+1)+" times; error #"+err+" "+ErrorDescription(err));
      return(-1);
     }
   string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"};
   myAlert("order", "Order sent"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+MagicNumber);
   return(ticket);
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {  
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
      MaxSlippage *= 10;
     }
   //initialize LotDigits
   double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(LotStep >= 1) LotDigits = 0;
   else if(LotStep >= 0.1) LotDigits = 1;
   else if(LotStep >= 0.01) LotDigits = 2;
   else LotDigits = 3;
   return(INIT_SUCCEEDED);
  }

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int ticket = -1;
   double price;  
  
   CloseByDuration(Forex_Expiration_Minutes * 60);
  
   //Binary Option Call
   if(Close[Candle_Close] > iMA(NULL, PERIOD_CURRENT, Period1, MA_Shift, MODE_SMA, PRICE_CLOSE, 0) //Candlestick Close > Moving Average
   )
     {
      RefreshRates();
      price = Ask;  
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_BUY, price, MM_Size(), "BO exp:"+IntegerToString(BO_Expiration_Seconds * 1)); //binary option order
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
     }
  
   //Binary Option Put
   if(Close[Candle_Close] < iMA(NULL, PERIOD_CURRENT, Period1, MA_Shift, MODE_SMA, PRICE_CLOSE, 0) //Candlestick Close < Moving Average
   )
     {
      RefreshRates();
      price = Bid;  
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_SELL, price, MM_Size(), "BO exp:"+IntegerToString(BO_Expiration_Seconds * 1)); //binary option order
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
     }
  }
//+------------------------------------------------------------------+

 
ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, ordername, MagicNumber, 0, clr);

try replacing ordername with "1"

 
Thank you. That worked. How do I add a input so it can be adjusted from the inputs?
 
input string ordername="1";

and remove all other expressions that include ordername except in the actual OrderSend

 

I am not sure what you mean by removing all expressions of ordername.

And when I add the input do I still keep the 1 in the ticket line instead of ordername:

ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, 1, MagicNumber, 0, clr);


Below are some highlighted examples of where ordername is found, but I don't understand how to remove it from the code.

ordername is mentioned about 13 times in the code above.

   if(!IsTradeAllowed()) return(-1);
   int ticket = -1;
   int retries = 0;
   int err;
   int long_trades = TradesCount(OP_BUY);
   int short_trades = TradesCount(OP_SELL);
   int long_pending = TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP);
   int short_pending = TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP);
   string ordername_ = ordername;
   if(ordername != "")
      ordername_ = "("+ordername+")";
   //test Hedging
   if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0)))
     {
      myAlert("print", "Order"+ordername_+" not sent, hedging not allowed");
      return(-1);
     }
   //test maximum trades
   if((type % 2 == 0 && long_trades >= MaxLongTrades)
   || (type % 2 == 1 && short_trades >= MaxShortTrades)
   || (long_trades + short_trades >= MaxOpenTrades)
   || (type > 1 && long_pending + short_pending >= MaxPendingOrders))
     {
      myAlert("print", "Order"+ordername_+" not sent, maximum reached");

      return(-1);

 

I think you have no idea what your code is doing.

Ask the owner of the code or try to understand how it works.

 

I looked closer at the EA and I believe that you already have an input

extern int BO_Expiration_Seconds = 60;

although this seems to be minutes, not seconds, so the default 60 would set 1 hour, not 60 seconds. If you set this input to 1 in your original posted EA it should expire after 1 minute.

Below I added a simple binary options ea (a piece of junk gambling ea) that I created just for the purpose of posting here to see if someone can add a

comment feature to it.

I agree with eddie above and don't see how you could have created this EA and not known that you had already included the input.

 
Don't paste code
Play video
Please edit your post.
For large amounts of code, attach it.
 

Very true I have no idea about ea coding, but I created the ea using EABuilder which does most of the work for your automatically.

As is the ea trades binary options MT4 brokers like GDMFX, MikiForex etc., but Grand capital is set up differently so that the EA expiration time on that broker works differently since that broker does not use the TradeToolsFX MT4 binary options plugin.

So initially GumRai suggested to replace ordername with a 1 to get a 1 minute expiration with that broker since  the expiration is placed in the comment. That worked, so I was trying to figure out how to add an extra input to adjust trade comment from.

The normal expiration time (Bo_Expiration_Seconds) is in seconds, not minutes.

So with GDMFX, MikiForex etc. a 1 minute expiration is 60 in the Bo_Expiration_Seconds input.

BUT GUMRAI you are correct. I used 1 second in the Bo_Expiration_Seconds input, and it worked as a 1 minute expiration with Grand Capital.

With other MT4 binary options brokers 3600 in that input would be a 60 minute expiration.

Thank you for your help.

 
hifromeddie: but I created the ea using EABuilder
  • We hate EA builder
  • You couldn't be bothered to learn mql4, therefor there is no common language for us to communicate.
  • There are only two choices: learn to code it, or pay someone. We're not going to code it FOR you. We are willing to HELP you when you post your attempt (using SRC) and the nature of your problem, but we are not going to debug your hundreds lines of code.
  • EA builder makes bad code counting up while closing multiple orders.
  • EA builder makes bad code Bars is unreliable (max bars on chart) volume is unreliable (miss ticks) Always use time
  • EA builder makes bad code Not adjusting for 4/5 digit brokers
  • EA builder makes bad code not adjusting for ECN brokers.
  • EA builder makes bad code not checking return codes.
  • EATree uses objects on chart to save values - not persistent storage (files or GV+Flush.) No recovery (crash/reboot.)
 
I didn't come on here for suggestions on how to fix bugs in the ea. I was just asking about how to add a comment input so the ea can be used with Grand Capital binary options which is set up differently then other MT4 binary options brokers that use the TradeToolsfx MT4 binary options plugin. That's all. I tried to learn mql4 6 years ago but it didn't click...couldn't figure it out. I paid multiple programmers over the years to build ea's for me. But recently discovered eabuilder which can create Forex and binary options ea's. The comment input is all I was asking about here (how to transfer the parameter in a ea comment input to the Mt4 order window comment field.)
Reason: