My Beginner EA, Help Me Learn, From Concept To Code

 

Hello forum, I am trying to build my first basic EA. I don't have any background in programming and have been trying to learn mql4 on my own. When I thought I had finished coding my basic strategy, my back test resulted in several sent orders. Also, orders would close nearly immediately after being generated. Instead of fragmentarily trying to troubleshoot my code in the forum, I want to start over and ask for anyone's help in how to code my strategy. I very much want to independently create my own EAs, but I am having a hard time getting started by myself without knowing what went wrong, why, and what questions to ask to try to solve the problems. So, I am hoping that what comes of this thread is an instrumental learning experience for me to get a better foundation for constructing EAs in the future. Thank you in advance.

Without further ado, what I would like to build is a Scaling Triple Moving Average trading robot. Attached to X timeframe of Y currency pair, we would have three SMAs: a 14-period, a 21-period, and a 35-period. For our example, let's say price is moving above our SMAs. When price crosses above an SMA, we want a BUY order to be generated. We are excluding any position sizing bias towards one SMA or another, so each position lot size will be the same. Also, we won't set any take profit or stop loss with our positions. This means, we would have at most 3 active BUY orders of the same lot size if price is above all three SMAs, 2 active orders of the same lot size if price is above two SMAs but has not crossed above the third, etc. Then, when price drops below the SMAs, we want it to close one active position for each SMA that price drops below. An active position will be closed only if a position was opened due to price being above an SMA. For example:

  • EA starts and price is above the 14-period and 21-period SMAs, but below the 35-period SMA.

  • Two 1 mini lot Buy positions would be opened.

  • No positions would be closed due to price being below the 35-period SMA, because there was never a position opened based on price being above the 35-period SMA.

We will not be opening trades in the opposite direction, just scaling out and closing the BUY positions. Because of equal position sizing and FIFO, we cannot always close the exact order generated by each SMA. For example, if price crosses above the 14 SMA, the 21 SMA, the 35 SMA, but then drops below the 35 SMA, the order that has to be selected and closed will have to be the one generated by the 14 SMA. This is okay, this is what I want to experiment with for this EA.

Below, I'm outlining a mock event log to illustrate more how I am looking to make this EA work. Though I think it is clear that it is pretty simple and a basic starting place for me as a new trader and new to mql4:

  • EA starts

  • Price moves above the 14-period SMA, a 1 mini lot BUY order is generated. (No more orders will be generated based on price being above the 14-period SMA.)

  • Price moves above the 21-period SMA, a 1 mini lot BUY order is generated. (No more orders will be generated based on price being above the 21-period SMA.)

  • Price moves below the 21-period SMA, one of our open BUY positions is closed. (Order now able to be placed if price moves back above the 21-period SMA.)

  • Price moves above the 21-period SMA, a 1 mini lot BUY order is generated. (No more orders will be generated based on price being above the 21-period SMA.)

  • Price moves above the 35-period SMA, a 1 mini lot BUY order is generated. (No more orders will be generated based on price being above the 35-period SMA.)

  • Price moves below the 35-period SMA, one of our open BUY positions is closed. (Order now able to be placed if price moves back above the 35-period SMA.)

  • EA closed manually, X many positions open at time of close, closing X many orders (When we close the EA, we want to close any active trades that may have been opened by it.)

Additionally, here is big detail I have been thinking about. I think I need to gate the Order functions behind global Boolean variables. Here is a mock code to illustrate my understanding of this:

  • global Boolean variable 14_SMA_Order = false (by default, when the EA starts, no orders have been activated by it. All three SMA order Boolean statuses would therefore be false)

  • If price moves above 14-period SMA and 14_SMA_Order = false, then execute BUY trade

  • Price > 14-period SMA and 14_SMA_Order = false, therefore a BUY trade is executed and 14_SMA_Order = true

  • 14_SMA_Order = true now because an order was successfully sent and we no longer let the code open a trade based on price being above the 14-period SMA

  • If price moves below 14-period SMA and 14_SMA_Order = true, then close open BUY trade 

  • Price < 14-period SMA and 14_SMA_Order = true, therefore a BUY trade is closed and 14_SMA_Order = false

  • 14_SMA_Order = false now because an open trade was successfully closed and we reallow the code to open a trade based on price being above the 14-period SMA 

  • (Also, this way, the code cannot mistakenly try to close an order without having first opened an order, because the SMA order Boolean statuses are all false by default)

I hope all of this isn't over explained, I just wanted to make sure I made myself as clear as possible in the beginning to avoid possible confusions. I'm trying to ask for help with this from the standpoint of a student seeking help from a mentor or a teacher. I have my idea, I just need help seeing this project through from conceptual strategy to functioning code. Thank you again in advance to anyone who takes the time to help me with this.


Best regards,

Ryan 

 
Post your idea as a job in the Freelance section.
 

UPDATE: I did consider sending this to freelance, but I was able to make some progress on my own.

I managed to stop the issue of many orders sending at the start of the EA. I will post my code so far below. I will be adding in the other two SMAs, but I am currently just working on setting up the one. I had a semicolon after each "if" statement in the "void OnTick()" block. With the semicolon, the orders would keep sending. Without it, only one order is sent. That was an important fix. I don't understand how the semicolon affected the code in this way. If anyone knows the reason for this and could explain it, that would be greatly appreciated.

I am back testing against the EUR/USD daily chart, open prices only model, and I have two more issues I need to learn how to solve:

  • The Buy order will send only on the day the back test starts on, if criteria is met. That is, if price is above the SMA on the date the back test begins on, the order will send. But, if price starts below the SMA, and the back test moves on to bars that cross above the SMA, the order will not be triggered and no order is sent. This is confusing to me and I am unsure what the reason is for this.

  • The Order Close function is never triggered. During the back test, when it happens that an order is sent and price drops below the SMA, the order is never closed. I think I need some code that selects the order before closing it, but I am unsure how to do this. Because of each lot size being equal per trade and FIFO, I need to be able to find the order that was opened first and close that one.
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
      Alert("");
      Alert("Tiple Moving Average BUY has started.");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert Variables                                                 |
//+------------------------------------------------------------------+
double Order_Send_Price = Ask;
double Order_Close_Price = Bid;
double SMA_14 = iMA(Symbol(),NULL,14,0,MODE_SMA,PRICE_CLOSE,0);
double SMA_21 = iMA(Symbol(),NULL,21,0,MODE_SMA,PRICE_CLOSE,0);
double SMA_35 = iMA(Symbol(),NULL,35,0,MODE_SMA,PRICE_CLOSE,0);

bool SMA_14_Order=false;  
bool SMA_21_Order=false;
bool SMA_35_Order=false;

/// BUY_Order Open/Close Functions

void Open_BUY_Order()
   {
      OrderSend(Symbol(),OP_BUY,0.01,Ask,0,0,0,NULL,NULL,NULL,clrGreen);      
   }
void Close_BUY_Order()
   {
      OrderClose(0,0.01,Bid,0,clrRed);
   }


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
    if (Order_Send_Price > SMA_14 && SMA_14_Order==false)
      {
         Open_BUY_Order();
         SMA_14_Order = true;
      }
    if (Order_Close_Price < SMA_14 && SMA_14_Order==true)
      {
         Close_BUY_Order();
         SMA_14_Order = false;
      }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
      Alert("");
      Alert("Tiple Moving Average BUY has ended.");
  }

I think I am really close to finishing my project. I am trying to keep it simple and straightforward as my first EA. I just have these last few issues in the way of it being fully functioning. It has felt like solving one problem leads to three more sometimes, but I think it is almost done.

Ryan

The Fundamentals of Testing in MetaTrader 5
The Fundamentals of Testing in MetaTrader 5
  • www.mql5.com
What are the differences between the three modes of testing in MetaTrader 5, and what should be particularly looked for? How does the testing of an EA, trading simultaneously on multiple instruments, take place? When and how are the indicator values calculated during testing, and how are the events handled? How to synchronize the bars from different instruments during testing in an "open prices only" mode? This article aims to provide answers to these and many other questions.