MQL4 - automated forex trading   /  

Articles

Articles  MetaTrader 5  Step on New Rails: Custom Indicators in MQL5 To post a new article, please log in or register


This article is about
MetaTrader 4
Download MT 4 - 5.5 Mb

Mobile trading!
Buy a license and be mobile in your trading!

Step on New Rails: Custom Indicators in MQL5 [ ru ]

Introduction


Finally we've got an opportunity to try the new trade terminal - MetaTrader 5. No doubt, it is noteworthy and has many new features as compared to its predecessor. The important advantages of this platform among others are:

    • Essentially modified language allowing now to use the object-oriented programming, still allowing to use the rich advantages of structural programming.
    • The code execution speed, which now is much faster than in MetaTrader 4.
    • Essential increase of possibilities for displaying the necessary information.

    I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers.

    In this article we will consider indicators, their structure, drawing, types and their programming details, comparing to MQL4.

    There is nothing complicated in this article, moreover, anything of the considered here can be checked directly in the terminal using the attached files.

    I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new here.


    1. THE GENERAL STRUCTURE

    The general structure of the indicator as compared to MQL4 hasn't changed.

    As before, there are three functions - for initialization, for data processing, and for the indicator deinitailization.

    As before, many indicator parameters can be defined by properties (#property keyword). The most of them are designed specifically for indicators. Properties and input parameters as before, are defined in a global context.

    As example, let's consider the implementation of the custom coloring for RSI indicator. Here is the truncated version, the full one can be found in the file Color_RSI.mq5.

    Let's consider the parts of the code.

    //+------------------------------------------------------------------+
    //|                                                    Color_RSI.mq5 |
    //+------------------------------------------------------------------+
    
    // information properties
    #property copyright "TheXpert"
    #property link      "theforexpert@gmail.com"
    #property version   "1.00"
    
    // Indicator description -- the total length should not exceed 511 characters with CR symbols
    
    #property description "Indicator programming demo in MQL5"
    #property description "RSI indicator custom painting"

    The properties specified above are displayed in the indicator information panel (the "Common" tab of the properties). It looks like:




    // the indicator properties
    #property indicator_separate_window // indicator will be displayed in the separate subwindow
    
    //#property indicator_minimum 0
    //#property indicator_maximum 100
    
    #property indicator_buffers 2       // buffers used
    #property indicator_plots 1         // buffers displayed
    
    #property indicator_color1 DarkSalmon, DeepSkyBlue // we use 2 colors
    #property indicator_type1 DRAW_COLOR_LINE          // and special color style

    These properties are the indicator properties. The other properties description can be found in the help.

    //---- buffers
    double Values[];           // buffer for values
    double ValuesPainting[];   // buffer for color indexes
    double BufferForCopy[];    // additional buffer for copying
    
    // indicator input parameters
    input string               _1             = "RSI Parameters";
    input int                  RSIPeriod      = 5;
    input ENUM_APPLIED_PRICE   AppliedPrice   = PRICE_CLOSE;
    input string               _2             = "Color settings";
    input color                Down           = DarkSalmon;
    input color                Up             = DeepSkyBlue;
    
    // variable to store indicator handle
    int RSIHandle;

    Here are the indicator input parameters and global variables (do not confuse with global variables of the client terminal). The indicator input parameters are specified with the input identifier.

    Now it is possible to set enumeration for the input parameter, sometimes it is useful to avoid the incorrect parameters selection.

    For example, the AppliedPrice parameter will be displayed in a drop-down list with possible valid values.




    So all of the enumerations, including the user defined, will be displayed in the same drop-down list. For example, the following parameter

    //...
    enum DayOfWeek
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    };
    
    input DayOfWeek Day;
    
    //...

    will be displayed as follows:


    int OnInit()
    {
    
       // set the indicator buffers
       // set Values as a buffer for displaying
       SetIndexBuffer(0, Values,           INDICATOR_DATA);
       // set ValuesPainting as buffer for colors
       SetIndexBuffer(1, ValuesPainting,   INDICATOR_COLOR_INDEX);
       
       // Set beginning of Values buffer drawing
       PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, RSIPeriod);
       // Set indicator name
       IndicatorSetString(INDICATOR_SHORTNAME, "Color RSI(" + string(RSIPeriod) + ")");
       // Set empty value for Values buffer
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
       // Set colors for the buffer
       PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, Down);
       PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, Up);
    
       RSIHandle = iRSI(NULL, 0, RSIPeriod, AppliedPrice);
       
       ArrayResize(BufferForCopy, 3);
    
       // Set the indexation order for buffers (as series)
       ArraySetAsSeries(Values, true);
       ArraySetAsSeries(ValuesPainting, true);
       ArraySetAsSeries(BufferForCopy, true);
    
       return(0);
    }

    OnInit is the indicator initialization function. Here we configure the indicator buffers and their properties, and define the indicator variables which cannot be defined in the properties or must be set dynamically. Also there is an initial data initialization, including the handles assign that are needed for the indicators.

    // Function for data calculation
    // note that the function parameters can be renamed
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime& time[],
                    const double& open[],
                    const double& high[],
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
    {
       int toCount = (int)MathMin(rates_total, rates_total - prev_calculated + 1);
       
       if (prev_calculated < 0 || prev_calculated > rates_total)
       {
          toCount = rates_total;
       }
       
       int copied = CopyBuffer(RSIHandle, 0, 0, toCount, Values);
       if (copied == -1)
       {
          Print("Error while data copying. Error №", GetLastError());
          return 0;
       }
       
       // Coloring. Yes, now it became so simple
       for (int i = toCount - 2; i >= 0; --i)
       {
          
          if (Values[i + 1] != EMPTY_VALUE && 
              Values[i] > Values[i + 1])   ValuesPainting[i] = 1;
          else                             ValuesPainting[i] = 0;
       }
    
       return rates_total;
    }

    OnCalculate is the function for data calculation. This function can be of two kinds. Here is its standard form. The details are below.

    Function:

    // the function is not obligatory in a code
    /*
    void OnDeinit()
    {}
    */

    OnDeinit is the indicator deinitialization function. Often it is necessary to release the resources, for example, file handles. For other cases this function is not necessary.


    2. TWO CONCEPTS OF INDICATORS

    The first is standard, the same as we have got used to in MQL4, but in a slightly modified form. The function OnCalculate is used instead of the function Start.
    For the standard form it looks as follows:

    int OnCalculate(const int rates_total,      // Arrays size
                    const int prev_calculated,  // Bars processed on the previous call
                    const datetime& time[],     // Data for the current chart and timeframe...
                    const double& open[],
                    const double& high[],       
                    const double& low[],
                    const double& close[],
                    const long& tick_volume[],
                    const long& volume[],
                    const int& spread[])
    {
       return rates_total;
    }

    In order to reduce the amount of code intended for data copying, the chart data are passed directly as arrays to the parameters of the function. Moreover, the number of available bars is passed as the first parameter of the function, the number of bars processed after last call or 0 (zero) is passed as the second parameter.

    The 0 (zero) value can be passed at the first indicator call, as well as when loading new or missing data. This parameter is a replacement (alternative or equivalent - it's up to you) for IndicatorCounted(), which is inconvenient for many developers.

    The second concept is the replacement and expansion of the i<…>OnArray-like functions of MQL4. There is an indicator of such a type in the terminal examples – Custom Moving Average. This type of indicators is intended for data processing dependent on the user's choice, including the custom indicators.

    The function for data processing for the indicators of such type looks like this:

    int OnCalculate (const int rates_total,      // the size of the price[] array
                     const int prev_calculated,  // bars calculated in the previous call
                     const int begin,            // where notional data start from
                     const double& price[]       // data array for calculation
       );
    {
       return rates_total;
    }

    The last parameter of the function is the data selected by user for processing. If you want to apply an indicator with a lot of buffers, the first indicator buffer will be passed for data processing.



    The First Indicator's Data means that the indicator will be applied to the indicator first attached to the selected window of the chart .

    The Previous Indicator's Data means, that indicator will be applied to the indicator last attached to the selected window of the chart.

    These indicators can be used to assemble the entire stacks. For example, using the Custom Moving Average indicator it is possible to get the triple smoothing by imposing the first indicator to the necessary data, the second to the first and the third to the second:


    There are many standard indicators which implement this particular concept. Therefore, when you see the prompt for the function parameter applied_price_or_handle:

    it indicates that еру indicator is implemented the way that it can be calculated on the user data - the handle of these data must be passed as parameter applied_price_or_handle.

    Using the same way it is possible to organize data processing directly in the indicator code:

    {
       // ...
       RSIHandle = iRSI(NULL, 0, RSIPeriod, AppliedPrice);
       SmoothHandle = iMA(NULL, 0, SmoothPeriod, 0, MODE_EMA, RSIHandle);
       // ...
    }

    There is another new application of this concept - the ability to write universal service indicators. An example of such indicator is attached in the file Direction_Brush.mq5.


    Results are presented on the upper chart. The direction coloring in this case is separated as an independent entity and implemented in the other indicator.

    Certainly, their universality is limited, since they are applicable only for the zero buffer of the indicator. Nevertheless, I think that indicators of this type might be useful.

    From the other side, when you write a custom indicator, you should take it into account, because the main information processing in the zero buffer will allow to avoid implementing a multifunctional machine in one indicator. Many of the other actions can be made and executed in the external service indicators. All that you will have to do is attach service indicators with the required functionality to your custom щon.

    The application range is not so narrow as it might seem at first sight:

    • coloring the indicator characteristics (tops, directions, levels, segments, etc.), including the tone visualization;
    • different signals in different conditions;
    • collecting and displaying statistics - for example, the data distribution;
    • construction of universal indicators that can be calculated for one buffer - for example, moving averages, zigzag.

    The features mentioned above are not the exhaustive list of the concept implementation. I think that many other effective implementations will be found later.


    3. ACCESSING DATA

    The data access principles have changed in MQL5. Now the work occurs directly in the arrays, and as a result, the calculation speed has increased significantly. Now it's not necessary to create an array and call the iCustom function for each value. Instead, it is possible to get the necessary data count by calling one function, and then directly use the demanded data copied in a local array specified.

    Data copying is implemented by using the system function CopyBuffer. You can find the function description in the help.

    The maximum data count to copy for the indicator and static (with a predefined size) arrays is determined by the size of the array. The size of dynamic array can be changed if the number of copied data exceeds its size.

    Besides, there are special functions for accessing historical data:


    Function

    Description

    CopyBuffer

    Gets data of a specified buffer of a certain indicator in the necessary quantity.

    CopyRates

    Gets history data of MqlRates structure of a specified symbol-period in specified quantity into the rates_array array.

    CopyTime

    The function gets to time_array history data of bar opening time for the specified symbol-period pair in the specified quantity.

    CopyOpen

    The function gets into open_array the history data of bar open prices for the selected symbol-period pair in the specified quantity.

    CopyHigh

    The function gets into high_array the history data of highest bar prices for the selected symbol-period pair in the specified quantity.

    CopyLow

    The function gets into low_array the history data of minimal bar prices for the selected symbol-period pair in the specified quantity.

    CopyClose

    The function gets into close_array the history data of bar close prices for the selected symbol-period pair in the specified quantity.

    CopyTickVolume

    The function gets into volume_array the history data of tick volumes for the selected symbol-period pair in the specified quantity.

    CopyRealVolume

    The function gets into volume_array the history data of trade volumes for the selected symbol-period pair in the specified quantity.

    CopySpread

    The function gets into spread_array the history data of spread values for the selected symbol-period pair in the specified quantity.


    Details can be found in help.

    This data is passed in only one form of the indicator, for the other they should get their own.

    Due to the fact that the type of the historical data array is not necessarily double, it is recommended to use only dynamic non-indicator buffers for their storage.

    Also there is one more undocumented detail - if the copied data count is equal to 0 (zero), the function CopyBuffer will generate an error with code №4003, therefore the data count to copy should be not less than 1 (one) element.


    4. THE INDICATOR BUFFERS

    The buffers count is not limited.

    Now you don't have to think how to accommodate the information correctly, how to perform the intermediate calculations efficiently, working on creation of the cluster indicator.

    But we should not forget that the buffers storage requires memory. Therefore, if you specify a terminal history depth about 1,000,000 bars and attach the "thick" cluster indicator to the minute chart, do not be surprised when the terminal eats Gb of memory.

    The essence of the buffer also has undergone some changes. The amount of the buffers used is specified in the in property.

    #property indicator_buffers 2       // buffers used
    

    This value should correspond to the total buffers count.

    The number of displayed buffers is defined by the property:

    #property indicator_plots 1         // buffers displeyed

    Here is some detail. The most of the drawing styles needs only one INDICATOR_DATA buffer for drawing. However, there are some styles that require several indicator buffers for drawing.

    We mean the following drawing styles:

    • DRAW_HISTOGRAM2 -- requires two indicator buffers (HistogramSample.mq5)


    • DRAW_FILLING -- requires two indicator buffers (CrossMa.mq5)



    • DRAW_CANDLES -- requires four indicator buffers (CandleSample.mq5)



    • DRAW_BARS -- requires four indicator buffers (BarsSample.mq5)



    All of the above types except DRAW_FILLING style (it can't be colored), have colored analogues.

    All indicator buffers are now divided into 3 types:

      • INDICATOR_DATA – buffers, whose data are displayed on the chart. These buffers are intended for drawing and for working with iCustom. They should be registered first. In the case of their
        arbitrary order (wrong), the code will be compiled successfully and it will be drawn when applied to a chart, however, most likely, incorrectly.
      • INDICATOR_COLOR_INDEX – buffers for a colors storage. They are necessary for storing the color buffer indexes of INDICATOR_DATA type, having one of special color types (#property indicator_typeN). Such buffer (we name its color buffer) should be registered right after the main buffer, which uses it.
      • INDICATOR_CALCULATIONS – buffers of such a type are intended for storing results of auxiliary calculations. They are not displayed on the chart.
      int OnInit()
      {
         // ...
         SetIndexBuffer(0, V2, INDICATOR_DATA);
         SetIndexBuffer(1, V2C,INDICATOR_COLOR_INDEX);
         SetIndexBuffer(2, V4, INDICATOR_DATA);
         SetIndexBuffer(3, V4C,INDICATOR_COLOR_INDEX);
         SetIndexBuffer(4, V1, INDICATOR_CALCULATIONS);
         SetIndexBuffer(5, V3, INDICATOR_CALCULATIONS);
      
         // ...
         return 0;
      }

      There are also some features when referring to indicators via iCustom.

      • Buffers for drawing (the ones that are displayed on the chart) are available for reading. The buffer number (index) must match the one, for which the buffer is registered.
      • Buffers for a color storage may be available for reading, but not always. For example, in the code above buffer V2C can read and obtain the necessary values, but the buffer V4C is unavailable.
      • Buffers for intermediate calculations are not available, as it was in MQL4. If you want to have guaranteed access to the external data buffer, declare it as INDICATOR_DATA.

      In case of the request to the inaccessible buffer, the error 4806 The requested data was not found») will be generated.

      Let's consider the color buffers in details.

      In MQL4, for each color it was necessary to create a separate buffer, but now using the color styles, you can specify up to 63 colors for a one buffer. In some cases, it will allow to optimize the number of the buffers used, and thus to save the memory usage. It also opens new possibilities for writing indicators, in particular, the use of tone visualization.

      In addition, this innovation in some cases, greatly simplifies the logic of the application of several colors in comparison with MQL4. The most obvious example - separation of trends by colors. In MQL4 for the very economical (from correct cases) case of implementation it has required three (3) buffers and non-trivial programming.

      Now it easier than ever. Here are the code samples, the complete implementation can be found in file Color_RSI.mq5.


      #property indicator_color1 DarkSalmon, DeepSkyBlue // we use 2 colors
      #property indicator_type1 DRAW_COLOR_LINE          // and special color drawing style
      
      //---- buffers
      double Values[];           // buffer for values
      double ValuesPainting[];   // buffer for color indexes
      
      int OnInit()
      {
         // Registering buffers
         // Values as drawing buffer
         SetIndexBuffer(0, Values,           INDICATOR_DATA);
         // ValuesPainting as color storage buffer
         SetIndexBuffer(1, ValuesPainting,   INDICATOR_COLOR_INDEX);
        
         // …
       
         return(0);
      }
      
      // function for data calculation
      int OnCalculate(/*…*/)
      {
         int toCount = (int)MathMin(rates_total, rates_total - prev_calculated + 1);
        
         int copied = CopyBuffer(RSIHandle, 0, 0, rates_total, Values);
         if (copied == -1)
         {
            Print("Error while data copying. Error №", GetLastError());
            return 1;
         }
        
         // Colouring. Yes, now it became so simple
         for (int i = toCount - 2; i >= 0; --i)
         {
            if (Values[i] > Values[i + 1])   ValuesPainting[i] = 1;
            else                             ValuesPainting[i] = 0;
         }
      
         return rates_total;
      }

      Some more code, and we get the following:




      You should note some of details when using color types for drawing.

      For the color buffers, when using a dynamic color definition scheme, the maximal colors count is limited by the colors count defined in the indicator_colorN property. For example

      #property indicator_color1 DarkSalmon, DeepSkyBlue // we use 2 colors

      color scheme of the buffer will contain maximum two colors, even if you will set a larger number of colors dynamically (using the PlotIndexSetInteger).

      Therefore, the required number of colors should be written in one line - property definition line. Then they can be changed dynamically. The shortest color which I have found - "Red". However, you can always do the following:

      Instead of

      #property indicator_color1  Red, Red, Red, Red, Red, Red, Red, Red, //…

      you may write:

      #define C Red
      #property indicator_color1  C, C, C, C, C, C, C, C, C, C, C, C, C, C, //…

      The maximum number of colors for a buffer is 63. When the color number greater than the maximal (defined by property indicator_colorN) buffer will not be displayed.

      Here is an example of tone visualization, using the maximum number of colors:



      In general, the drawing opportunities have significantly increased, and that's great.


      5. ARRAYS

      During the direct reference to the array data by indexes, it is necessary to mean the data ordering type – AsSeries property. It cannot be defined for some of the array types.

      This flag cannot be set for the multidimensional and for static arrays. For the array types, which are passed to the OnCalculate function it is possible to set such a flag.

      The data copying using the function CopyBuffer doesn't depend on the AsSeries property, but its implementation is different for different buffers.

      For indicator buffers it is necessary to copy the entire depth of available history. It must be remembered.

      For dynamic and static (with a predefined size) arrays the data copying is performed from the present to the past.

      The function CopyBuffer changes the size of buffers for dynamic (except indicator's) buffers for the necessary size.

      It is not recommended to use the static arrays for data copying.

      In general, I advise you always to check, how you copy data and how you address them. The most simple and safe way is:

      • to set the AsSeries property for all of the buffers used for a storage of history data.
      • to take into account the buffer structures for the different buffers.
      • to always check the value of _LastError variable (last error code).

      In addition, I strongly advise to study the help for the CopyBuffer function and for all of the functions connected with AsSeries property.


      6. IndicatorCounted

      Now the debates about the necessity of the IndicatorCounted function will sink into oblivion, because this value is defined directly by us as return value of the previous function call.

      int OnCalculate(const int rates_total,      // array size
                      const int prev_calculated,  // bars processed after last call
                      //...)
      {
         return rates_total;
      }

      More often it is enough to return the rates_total value which contains the bars count of the current function call.

      However, if the price data were changed since the last OnCalculate() call (for example, history data were loaded or the history data blanks were filled), then the value of the input parameter prev_calculated will be set to 0 (zero) by the client terminal.

      Also, if OnCalculate function returns zero, then the indicator values are not shown in the DataWindow of the client terminal. Therefore, if you want to see the indicator and perform it sfull recalculation during the history loading process or after a connection failure, return 1 instead of 0.

      The another useful feature which has been added is determining how many bars has been calculated for the indicator. It is more useful for Expert Advisors which perform calculations on a large data. The function is BarsCalculated, its details can be found in the help.

      This function has another useful application. If the indicator hasn't been loaded, its loading may take some time - the time between the indicator handle creation and its use for the calculations.

      This time is required for initialization and its initial precalculation. It depends on the calculation speed and indicator details.

      During this time, the call for the CopyBuffer function generates the error 4806 -- "The requested data was not found".

      The function BarsCalculated can be used to determine the availability of the indicator data for copying:

         int WPRHandle = iWPR(NULL, 0, WPRPeriod);
      
         int copied = CopyBuffer(WPRHandle, 0, 0, bars, Values);
         int err = GetLastError();
      
         if (-1 == copied)
         {
            if (4806 == err)
            {
               for (int i = 0; i < 1000; ++i)
               {
                  if (BarsCalculated(WPRHandle) > 0) break;
               }
               copied = CopyBuffer(WPRHandle, 0, 0, bars, Values);
               err = GetLastError();
            }
         }
      
         if (-1 == copied)
         {
            Print("Error when trying to get WPR values, last error is ", err, " bars ", bars);
            return 0;
         }
         //...


      SUMMARY

      In conclusion, I would like to say that just some of the details have been considered in this article. But I hope that the basic aspects are presented here.

      It would be great if this article were a useful reference on the subject, where you could always look and find information about the details.

      If you have found any mistakes in this article, or have discovered something important, please inform me and I will try to correct it and improve the article as soon as possible.

      I am planning to outine the recent changes, besides that, I hope that some of the useful information will appear in comments.

      That's the reason to read them carefully.


      APPENDIX

      Color.mqh -- include file, copy this file to the folder MQL5/Include. This file is necessary for the Toned_WPR indicator.

      Color.mq5 -- library, copy this file to the folder MQL5/Libraries. This file is necessary for the Toned_WPR indicator.

      All of the over files are indicators.


      ACKNOWLEDGMENTS

      Again, I would like to thank Mr. Victor Rustamov (granit77) for the manuscript reading, useful discussions and helpful advices.

      Translated from Russian by MetaQuotes Software Corp.
      Original article: http://articles.mql4.com/ru/862

      Attachments:
      BarsSample.mq5 (1.1 Kb)
      CandleSample.mq5 (1.1 Kb)
      Color.mq5 (2.1 Kb)
      Color.mqh (831 bytes)
      Color_RSI.mq5 (6.1 Kb)
      CrossMa.mq5 (1.3 Kb)
      Direction_Brush.mq5 (1.7 Kb)
      HistogramSample.mq5 (1.3 Kb)
      Toned_WPR.mq5 (3.0 Kb)
      Created: 2009.10.30  Author: Андрей
      Warning: All rights to these materials are reserved by MetaQuotes Software Corp. Copying or reprinting of these materials in whole or in part is prohibited.
      Here Comes the New MetaTrader 5 and MQL5
      Here Comes the New MetaTrader 5 and MQL5

      This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

      5 comments  To add comments, please, log in or register
      MACDtrader wrote:
      I am with a broker that uses MT4. When is MT5 coming out and will the forex brokers be offering it ?


      The Beta Version is available for downloading from either the Metaquotes site directly at http://www.metaquotes.net/ru/files/mt5setup.exe in Russia/Cyprus or TadawulFX Broker in Switzerland at http://www.tadawulfx.com/v2/trading/metatrader5.html, it's also available for download

      from www.BostonTechnologies.com in Boston Massechuesettes.

      Those are the only places I know of that have it available so far.

      It requires XP or higher OS, and you may have to replace the PSAPI.DLL in the \Windows\System32 directory.

      You do this by renaming the original PSAPI.DLL found in the \Windows\System32 directory to PSAPI_OLD.DLL

      and then install the new(most recently downloaded) PSAPI.DLL file into the \Windows\System32 directory.

      To download this file go to www.google.comand type in PSAPI.DLL, it will take you to a site to download the file.

      I'm told that it will take another 6 months to work out the bugs, and for the mql4 programmers to buff up on the new language to convert the various custom indicators that were developed under MT4, so please report any bugs you find.

      It will probably be readily available and supported by a majority of the current MT4 Brokers in the second/third quarter

      of 2010. There you have it. Enjoy it...

      Rod Harrell

      +01-510-655-4966

      549 - 66th Street,

      Oakland, CA. 94609-1117, USA

      2009.11.05 07:02 RodOaklandCali

      Can anyone tell me if the Renko or Point & Figure charts will be available in MQL5. Most platforms are making them available.

      2009.11.04 18:51 traderdukeFX
      Great article. Thanks for sharing it ! =)
      2009.11.03 06:23 beto21_cwb
      I cannot answer this question. You should ask the terminal developers to get the answer.
      2009.11.02 11:33 TheXpert
      I am with a broker that uses MT4. When is MT5 coming out and will the forex brokers be offering it ?
      2009.10.31 21:32 MACDtrader
      5 comments