Русский 中文 Español Deutsch 日本語 Português
Features of Experts Advisors

Features of Experts Advisors

MetaTrader 4Examples | 18 August 2005, 16:57
26 671 3
MetaQuotes
MetaQuotes

Creation of expert advisors in the MetaTrader trading system has a number of features.

  • Before opening a position, you should check if there is money available on the account. If there is not enough money on the account, the operation of opening a position will not be successful. The "FreeMargin" value must not be less than 1000 only during tests because the price of one lot is 1000 during tests.

    if(AccountFreeMargin() < 1000) return(0);    // not enough money
  • You can access history data by using the predefined arrays Time, Open, Low, High, Close, Volume. Due to historical reasons, index in these arrays increases from the end to the beginning. It means that the latest data have index 0. Index 1 indicates data shifted one period backwards, index 2 means data shifted two periods backwards, 3 is three periods backwards, etc.

    // if Close on the previous bar is less than 
    // Close on the bar before previous
    if(Close[1] < Close[2]) return(0);
  • It is also possible to access historical data using other time intervals and even using other currency pairs. To get such data, it is necessary to define a one-dimensional array first and perform a copy operation using the "ArrayCopySeries" function. Mind that, while calling the function, it is possible to pass a less number of parameters and do not specify default parameters.

    double eur_close_m1[];
    int number_copied = ArrayCopySeries(eur_close_m1, MODE_CLOSE, "EURUSD", PERIOD_M1);
  • In the process of writing an expert advisor, as well as any other software, it is sometimes necessary to get some additional debugging information. The MQL4 language provides several methods for getting such information.

    • The "Alert" function displays a dialog box with some data defined by the user.

      Alert("FreeMargin grows to ", AccountFreeMargin(), "!");
    • The "Comment" function displays data defined by the user in the upper-left corner of the chart. The character sequence "\n" is used to start a new line.

      Comment("FreeMargin is ", AccountFreeMargin(), ".");
    • The "Print" function saves data defined by the user to the system log.

      Print("FreeMargin is ", AccountFreeMargin(), ".");
  • To get the information about errors in the program, the "GetLastError" function is very useful. For example, an operation with an order always returns the ticket number. If the ticket number equals 0 (some error has occurred in the process of performing the operation), it is necessary to call the "GetLastError" function to get additional information about the error:

    int iTickNum = 0;
    int iLastError = 0;
    ...
    iTickNum = OrderSet (OP_BUY, g_Lots, Ask, 3, 0, Ask + g_TakeProfit * g_Points, Red);
    if (iTickNum <= 0) 
       {
         iLastError = GetLastError();
         if (iLastError != ERROR_SUCCESS) Alert("Some Message");
       }

    You should remember that calling the "GetLastError" function displays the code of the last error and resets its value. That is why calling this function once again in a row will always return value 0.

  • How to define the beginning of a new bar? (It can be necessary to find out that the previous bar has just been finished.) There are several methods to do it.


    The first method is based on checking the number of bars:

    int prevbars = 0;
    ...
    if(prevbars == Bars) return(0);
    prevbars = Bars;
    ...

    This method can fail to work while loading the history. That is, the number of bars is changed while the "previous" one has not been finished yet. In this case you can make checking more complicated by introducing a check for difference between the values equal to one.

    The next method is based on the fact that the "Volume" value is generated depending on the number of ticks that have come for each bar and the first tick means that the "Volume" value of a new bar equals 1:

    if( Volume > 1) return(0);
    ...

    This method can fail to work when there are a lot of incoming price ticks. The matter is that incoming price tricks are processed in a separate thread. And if this thread is busy when the next tick comes, this new incoming tick is not processed to avoid overloading the processor! In this case you can also make checking more complicated by saving the previous "Volume" value.

    The third method is based on the time a bar is opened:

    datetime prevtime=0;
    ...
    if(prevtime == Time[0]) return(0);
    prevtime = Time[0];
    ...

    It is the most reliable method. It works in all cases.

  • An example of working with a file of the "CSV" type:

    int h1;
    h1 = FileOpen("my_data.csv", MODE_CSV | MODE_WRITE, ";");
    if(h1 < 0)
      {
       Print("Unable to open file my_data.csv");
       return(false);
      }
    FileWrite(h1, High[1], Low[1], Close[1], Volume[1]);  
    FileClose(h1);

    Some explanations to the code. The file of the "CSV" format is opened first. In case there occurs an error while opening the file, the program is exited. In case the file is successfully opened, its content gets cleared, data are saved to the file and the file is closed. If you need to keep the content of the file being opened, you should use the MODE_READ opening mode:

    int h1;
    h1 = FileOpen("my_data.csv", MODE_CSV | MODE_WRITE | MODE_READ, ";");
    if(h1 < 0)
      {
       Print("Unable to open file my_data.csv");
       return(false);
      }
    FileSeek(h1, 0, SEEK_END);
    FileWrite(h1, High[1], Low[1], Close[1], Volume[1]);  
    FileClose(h1);

    In this example, data are added to the end of the file. To do it, we used the "FileSeek" function right after it was opened.

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/1494

Last comments | Go to discussion (3)
Sumit Dutta
Sumit Dutta | 21 May 2018 at 19:45
//+------------------------------------------------------------------+
//|                                       GoldminerAbsoluteEntry.mq4 |
//|                                             Copyright © 2009, Me |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Me"

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Magenta
#property indicator_color2 Yellow

extern string Remark1 = "-- Goldminer1 Settings --";
extern int RISK = 4;
extern int VerifyShift = 1;

//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,234);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,233);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexEmptyValue(1,0.0);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {

   //+------------------------------------------------------------------+
   //| Goldminer Begin                                                  |
   //+------------------------------------------------------------------+

   double GN1,GN2;
   string GoldMiner;

   for(int a=0;a<Bars;a++){//For Loop
   GN1=iCustom(0,0,"goldminer1",RISK,Bars,0,a+VerifyShift);
   GN2=iCustom(0,0,"goldminer1",RISK,Bars,1,a+VerifyShift);

   if(GN2>GN1){GoldMiner="Up";
      ExtMapBuffer2[a]=Low[a];}
   else if(GN1>GN2){GoldMiner="Down";
      ExtMapBuffer1[a]=High[a];}
   else {GoldMiner="None";}

   }//End Of For Loop

   //+---------------------------------------------------------------+
   return(0);
  }
//+------------------------------------------------------------------+
Sumit Dutta
Sumit Dutta | 21 May 2018 at 19:47
Sumit Dutta:
any one help i want my indicator alart up when back singel candel is green or alart down when back sigel candel is reed filter signal
Paweł Wilski
Paweł Wilski | 2 Aug 2024 at 11:37
//+------------------------------------------------------------------+
//|                                       GoldminerAbsoluteEntry.mq4 |
//|                                             Copyright © 2009, Me |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Me"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Magenta
#property indicator_color2 Yellow

extern string Remark1 = "-- Goldminer1 Settings --";
extern int RISK = 4;
extern int VerifyShift = 1;

//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
    //---- indicators
    SetIndexStyle(0, DRAW_ARROW);
    SetIndexArrow(0, 234);
    SetIndexBuffer(0, ExtMapBuffer1);
    SetIndexEmptyValue(0, 0.0);
    SetIndexStyle(1, DRAW_ARROW);
    SetIndexArrow(1, 233);
    SetIndexBuffer(1, ExtMapBuffer2);
    SetIndexEmptyValue(1, 0.0);
    //----
    return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
    return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
    //+------------------------------------------------------------------+
    //| Goldminer Begin                                                  |
    //+------------------------------------------------------------------+

    double GN1, GN2;
    string GoldMiner;

    // Ensure there are enough bars
    if (Bars <= VerifyShift) return(0);

    int counted_bars = IndicatorCounted();
    int limit = Bars - counted_bars;

    // Clear buffers
    ArraySetAsSeries(ExtMapBuffer1, true);
    ArraySetAsSeries(ExtMapBuffer2, true);

    for (int a = limit - 1; a >= 0; a--)
    {
        GN1 = iCustom(NULL, 0, "goldminer1", RISK, Bars, 0, a + VerifyShift);
        GN2 = iCustom(NULL, 0, "goldminer1", RISK, Bars, 1, a + VerifyShift);

        if (GN2 > GN1)
        {
            GoldMiner = "Up";
            ExtMapBuffer2[a] = Low[a];
            // Check if previous candle is green (bullish)
            if (Close[1] > Open[1])
            {
                Alert("GoldMiner Up signal with previous candle green.");
            }
        }
        else if (GN1 > GN2)
        {
            GoldMiner = "Down";
            ExtMapBuffer1[a] = High[a];
            // Check if previous candle is red (bearish)
            if (Close[1] < Open[1])
            {
                Alert("GoldMiner Down signal with previous candle red.");
            }
        }
        else
        {
            GoldMiner = "None";
        }
    }

    //+---------------------------------------------------------------+
    return(0);
  }
//+------------------------------------------------------------------+
Features of Custom Indicators Creation Features of Custom Indicators Creation
Creation of Custom Indicators in the MetaTrader trading system has a number of features.
Creating a Trading Administrator Panel in MQL5 (Part VI):Trade Management Panel (II) Creating a Trading Administrator Panel in MQL5 (Part VI):Trade Management Panel (II)
In this article, we enhance the Trade Management Panel of our multi-functional Admin Panel. We introduce a powerful helper function that simplifies the code, improving readability, maintainability, and efficiency. We will also demonstrate how to seamlessly integrate additional buttons and enhance the interface to handle a wider range of trading tasks. Whether managing positions, adjusting orders, or simplifying user interactions, this guide will help you develop a robust, user-friendly Trade Management Panel.
Strategy Tester: Modes of Modeling during Testing Strategy Tester: Modes of Modeling during Testing
Many programs of technical analysis allow to test trading strategies on history data. In the most cases, the testing is conducted on already completed data without any attempts to model the trends within a price bar. It was made quickly, but not precisely
Developing a Replay System (Part 53): Things Get Complicated (V) Developing a Replay System (Part 53): Things Get Complicated (V)
In this article, we'll cover an important topic that few people understand: Custom Events. Dangers. Advantages and disadvantages of these elements. This topic is key for those who want to become a professional programmer in MQL5 or any other language. Here we will focus on MQL5 and MetaTrader 5.