EMA EA problem at closing order

 

Hi,

I'm trying to build my own EA using EMA. When the program starts it will buy/sell according to the relative position of slow and fast EMA. Then the program should close the trade at the next EMA crossover. My first obstacle was to find a way to calculate EMA at the closing of candlestick, so I asked chatgpt to help me. After lots of attempts he brought me something using currenTime and prevTime values + the if condition. The calculations work even though i don't really understand why. I would be glad if someone can explain it to me. Now i'm struggling at closing my orders, when printing the EMA values I see the crossover but the program still won't close the trade. I'm sharing the code, i am backtesting it on GBP/JPY on M15 from 24 apr to 25 apr, there are 2 crossovers (picture), the program should run 3 trades on that day. Any help? here's my code below.


//+------------------------------------------------------------------+
//|                                                      EACrossover.mq4 |
//|                        Copyright 2024, Company Name               |
//|                                       http://www.company.net     |
//+------------------------------------------------------------------+
#property strict

// Global variables
input int fastEMA_Length = 9;     // Length of fast EMA
input int slowEMA_Length = 21;     // Length of slow EMA
input double lotSize = 0.1;  // Lot size
input int slippage = 3;     // slippage
input int magicNumber = 123456; // magic number
int buy_ticket, sell_ticket; // variables that store the OrderSend values
bool buying_order=false;
bool selling_order=false;
int i = 0; // bar counter
datetime prevTime = 0; // Variable to store the time of the previous tick (Created by ChatGPT)
// It is used for the calculation of EMA at the closure of candlestick

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("EA Initialization");
   return(INIT_SUCCEEDED);
  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = Time[0]; // Get the time of the current tick

// Check if the current tick is on a new bar by comparing its time with the previous tick
   if(currentTime != prevTime)
     {
      // Update the previous tick time with the current tick time
      prevTime = currentTime;
      i++; // Increment the bar counter

      // Calculate the EMAs for the current bar
      double currentFastEMA = iMA(NULL, 0, fastEMA_Length, 0, MODE_EMA, PRICE_CLOSE, 0);
      double currentSlowEMA = iMA(NULL, 0, slowEMA_Length, 0, MODE_EMA, PRICE_CLOSE, 0);

      if(OrdersTotal() == 0) // We open a trade when there is no trade actually opened
        {

         // Check EMA position to buy or sell
         if(currentFastEMA > currentSlowEMA)
           {
            buy_ticket = OrderSend(Symbol(), OP_BUY, lotSize, Ask, slippage, 0, 0, "", magicNumber, 0, Green);
            buying_order=true;
            Print("I'm buying !");
           }
         else
           {
            sell_ticket = OrderSend(Symbol(), OP_SELL, lotSize, Bid, slippage, 0, 0, "", magicNumber, 0, Green);
            selling_order=true;
            Print("I'm selling !");
           }
        }
      else
        {
         Print("FastEMA=",currentFastEMA," slowEMA=",currentSlowEMA," iteration n°",i);
         // If a trade is opened we decide to close it at the next EMA crossover
         if(buying_order==true)  //closing buying order
           {
            if(currentFastEMA < currentSlowEMA)
              {
               OrderClose(buy_ticket,lotSize, PRICE_CLOSE,slippage,clrNONE);
              }
            buying_order=false;
           }

         if(selling_order==true)  //closing selling order
           {
            if(currentFastEMA > currentSlowEMA)
              {
               OrderClose(sell_ticket,lotSize,PRICE_CLOSE,slippage,clrNONE);
              }
            selling_order=false;
           }
        }
     }
  }


 
OrderClose(buy_ticket,lotSize, PRICE_CLOSE,slippage,clrNONE);

PRICE_CLOSE is the constant zero. Use a real price.

You would have known that had you Check your return codes, and report your errors (including market prices and your variables). Don't look at GLE/LE unless you have an error. Don't just silence the compiler (MT5 / MT4+strict), it is trying to help you.
          What are Function return values ? How do I use them ? - MQL4 programming forum (2012)
          Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles (2014)

 
William Roeder #:

PRICE_CLOSE is the constant zero. Use a real price.

You would have known that had you Check your return codes, and report your errors (including market prices and your variables). Don't look at GLE/LE unless you have an error. Don't just silence the compiler (MT5 / MT4+strict), it is trying to help you.
          What are Function return values ? How do I use them ? - MQL4 programming forum (2012)
          Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles (2014)

Hi,

Thanks for replying i solved the issue.

To close a buy order one must close it at bid price. To close a sell order one must close it at ask price.

That means we rewrite the code :

            if(buying_order && currentFastEMA < currentSlowEMA) //closing buy order
             {              
               OrderClose(buy_ticket,lotSize, **Bid**,slippage,clrNONE);
               buying_order=false;
             }       
     
            if(selling_order && currentFastEMA > currentSlowEMA) //closing sell order
             {
               OrderClose(sell_ticket,lotSize,**Ask**,slippage,clrNONE);
               selling_order=false;
            }    
 
if(buying_order && currentFastEMA < currentSlowEMA) //closing buy order
             {              
               OrderClose(buy_ticket,lotSize, **Bid**,slippage,clrNONE);
               buying_order=false;

EAs must be coded to recover. If the power fails, OS crashes, terminal or chart is accidentally closed, on the next tick, any static / global ticket variables will have been lost. You will have an open order / position but don't know it, so the EA will never try to close it, trail SL, etc. How are you going to recover?

Use a OrderSelect / Position select loop on the first tick, or persistent storage (GV+flush or files) of ticket numbers required.

 

Hi

I agree with William Roeder above, instead of remembering the tickets, create a functions that will close only trades in chosen direction, so when you detect the signal for closing. Just call CloseOrders(OP_BUY) or CloseOrders(OP_SELL) and those would close all of your buy or sell trades opened by the EA (identified by magic number). For example:

void CloseOrders(int Type)
{
   int i=OrdersTotal();      
   datetime l_datetime = TimeCurrent();
   bool closed = false;
   while (i >=0)      
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
      {
         if( OrderMagicNumber()==magicNumber&& OrderType() == Type)
         {
            if (OrderSymbol() == Symbol()){        
               l_datetime = TimeCurrent();
               closed = false;
               int cnt =0;
               int ticket = OrderTicket();
               while(!closed && TimeCurrent() - l_datetime < 60 && cnt<20 && !IsStopped())
               {
                  closed = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100);
                  err = GetLastError();
                  if (err == 150) return;
                  Sleep(1000);
                  while (IsTradeContextBusy() && !IsStopped()) Sleep(1000);
                  RefreshRates();
                  cnt++;
               }
               
            }
         }
      }
      i--;
   }                     
} 

Have a nice weekend

 

Hello,

Thank you for your suggestions I noticed there was a problem this week with closing orders considering that I'm operating on 2 computers. I'm confused on how to use your closeorder function, i should implement it in a separate EA or my main EA ?

Reason: