New MetaTrader 5 platform build 3490: Mobile Web Terminal version and new matrix methods in MQL5

 

The MetaTrader 5 platform update will be released on Friday, November 4, 2022.

The update introduces the new Web Terminal with full support for mobile devices. Now its interface automatically adapts to the user screen size.

In addition, we have improved the task manager for a more accurate monitoring of consumed resources and have added the OpenCL tab for managing available devices. The new OpenCL manager enables explicit specification of devices to be used for faster calculations.

We continue to expand platform capabilities in working with matrices and vectors. MQL5 features new functions for operations with price ticks and for data exchange between matrices and vectors. It also provides expanded assignment methods.

Mobile Web Terminal version and new matrix and vector methods in MQL5

In addition, we have implemented multiple fixes and improvements in all platform components. All new features, fixes and performance improvements are described in detail below.


Mobile version of the web platform

The new Web Terminal provides full-featured support for mobile devices. The interface will automatically adapt to the screen size, enabling efficient operations from iOS and Android phones and tablets:

Added support for mobile devices in the new web terminal

Also, the Web Terminal features a lot of fixes and improvements.

The new MetaTrader 5 Web Terminal supports the full set of trading functions. It enables users to:

  • Work with demo and live accounts
  • Receive any financial symbol quotes
  • Trade in any markets
  • Analyze symbol quotes using more than 30 indicators and 20 graphical objects
  • Use Economic Calendar data for fundamental analysis


MetaTrader 5 Client Terminal build 3490

  1. Terminal: Extended task manager features. The new version enables more accurate monitoring of consumed resources.

    • Added stack size display for threads.
    • Added display of the number of context switches.
    • Added recognition of system and third-party DLL threads.
    • Added display of kernel mode operating time. An increase in this metric compared to the time spent in user mode can indicate system-level issues: drivers problems, hardware errors or slow hardware. For further details, please read the Microsoft Documentation.
    • Added display of user mode operating time.

    OpenCL manager to control available devices


  2. Terminal: New OpenCL tab in terminal settings for managing available devices. The new OpenCL manager enables explicit specification of devices to be used for calculations.

    OpenCL manager to control available devices

  3. Terminal: Added indication of Stop Loss and Take Profit levels in the Depth of Market for accounts operating in FIFO mode (the mode can be enabled on the broker's side).

    According to the FIFO rule, positions for each instrument can only be closed in the same order in which they were opened. To ensure FIFO-compliant position closing by stop levels, the following logic has been implemented on the client terminal side:

    If multiple positions exist for the same instrument, the placing of stop levels for any of the positions causes the same levels to be placed for all other positions as well. Accordingly, if a level triggers, all positions will be closed in a FIFO-compliant order.

    Now, when the user opens the Depth of Market for an instrument which already has open positions for, the levels of existing positions (if any) are automatically specified in the Stop Loss and Take Profit fields.

  4. Terminal: Fixed deletion of Stop Loss and Take Profit levels using X buttons in the Toolbox\Trade window. The error occurred when the quick trading function was disabled. A click on the button will open a trading dialog with an empty value of the relevant level.

  5. Terminal: Fixed graph captions and final commission calculations in the trading report. The section could show incorrect Profit in report statistics and incorrect values in Equity and Balance graph tooltips.

  6. MQL5: Added vector and matrix methods CopyTicks and CopyTicksRange. They enable easy copying of tick data arrays into vectors and matrices.
    bool matrix::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
    bool vector::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
    
    bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
    bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
    The copied data type is specified in the 'flags' parameter using the ENUM_COPY_TICKS enumeration. The following values are available:
    COPY_TICKS_INFO    = 1,       // ticks resulting from Bid and/or Ask changes
    COPY_TICKS_TRADE   = 2,       // ticks resulting from Last and Volume changes
    COPY_TICKS_ALL     = 3,       // all ticks having changes
    COPY_TICKS_TIME_MS = 1<<8,    // time in milliseconds
    COPY_TICKS_BID     = 1<<9,    // Bid price
    COPY_TICKS_ASK     = 1<<10,   // Ask price
    COPY_TICKS_LAST    = 1<<11,   // Last price
    COPY_TICKS_VOLUME  = 1<<12,   // volume
    COPY_TICKS_FLAGS   = 1<<13,   // tick flags
    If multiple data types are selected (only available for matrices), the order of the rows in the matrix will correspond to the order of values in the enumeration.

  7. MQL5: Expanded features of matrix::Assign and vector::Assign methods.

    Now the matrix can be assigned a one-dimensional array or vector:
    bool matrix::Assign(const vector &vec);
    The result will be a one-row matrix.

    Also, a matrix can now be assigned to a vector (matrix smoothing will be performed):
    bool vector::Assign(const matrix &mat);
  8. MQL5: Added Swap methods for vectors and matrices.
    bool vector::Swap(vector &vec);
    bool vector::Swap(matrix &vec);
    bool vector::Swap(double &arr[]);
    bool matrix::Swap(vector &vec);
    bool matrix::Swap(matrix &vec);
    bool matrix::Swap(double &arr[]);
    Each array, vector or matrix refers to a memory buffer which contains the elements of that object. The Swap method actually swaps pointers to these buffers without writing the elements to memory. Therefore, a matrix remains a matrix, and a vector remains a vector. Swapping a matrix and a vector will result in a one-row matrix with vector elements and a vector with matrix elements in a flat representation (see the Flat method).
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
     {
    //---
      matrix a= {{1, 2, 3}, {4, 5, 6}};
      Print("a before Swap: \n", a);
      matrix b= {{5, 10, 15, 20}, {25, 30, 35, 40}, {45, 50, 55, 60}};
      Print("b before Swap: \n", b);  
    //--- swap matrix pointers
      a.Swap(b);
      Print("a after Swap: \n", a);
      Print("b after Swap: \n", b);
      /*
      a before Swap:
      [[1,2,3]
      [4,5,6]]
      b before Swap:
      [[5,10,15,20]
      [25,30,35,40]
      [45,50,55,60]]
      
      a after Swap:
      [[5,10,15,20]
      [25,30,35,40]
      [45,50,55,60]]
      b after Swap:
      [[1,2,3]
      [4,5,6]]
      */
      vector v=vector::Full(10, 7);
      Print("v before Swap: \n", v);
      Print("b before Swap: \n", b);
      v.Swap(b);
      Print("v after Swap: \n", v);
      Print("b after Swap: \n", b);
      /*
      v before Swap:
      [7,7,7,7,7,7,7,7,7,7]
      b before Swap:
      [[1,2,3]
      [4,5,6]]
      
      v after Swap:
      [1,2,3,4,5,6]
      b after Swap:
      [[7,7,7,7,7,7,7,7,7,7]]
      */
     }
    The Swap() method also enables operations with dynamic arrays (fixed-sized arrays cannot be passed as parameters). The array can be of any dimension but of an agreed size, which means that the total size of a matrix or vector must be a multiple of the array's zero dimension. The array's zero dimension is the number of elements contained at the first index. For example, for a dynamic three-dimensional array 'double array[][2][3]', the zero dimension is the product of the second and third dimension sizes: 2x3=6. So, such an array can only be used in the Swap method with matrices and vectors whose total size is a multiple of 6: 6, 12, 18, 24, etc.

    Consider the following example:
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
     {
    //--- fill the 1x10 matrix with the value 7.0
      matrix m= matrix::Full(1, 10, 7.0);
      Print("matrix before Swap:\n", m);
    //--- try to swap the matrix and the array
      double array_small[2][5]= {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
      Print("array_small before Swap:");
      ArrayPrint(array_small);
      if(m.Swap(array_small))
       {
        Print("array_small after Swap:");
        ArrayPrint(array_small);
        Print("matrix after Swap: \n", m);
       }
      else // the matrix size is not a multiple of the first array dimension
       {
        Print("m.Swap(array_small) failed. Error ", GetLastError());
       }
      /*
      matrix before Swap:
      [[7,7,7,7,7,7,7,7,7,7]]
      array_small before Swap:
               [,0]     [,1]     [,2]     [,3]     [,4]
      [0,]  1.00000  2.00000  3.00000  4.00000  5.00000
      [1,]  6.00000  7.00000  8.00000  9.00000 10.00000
      m.Swap(array_small) failed. Error 4006
      */
    //--- use a larger matrix and retry the swap operation
      double array_static[3][10]= {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
         {2, 4, 6, 8, 10, 12, 14, 16, 18, 20},
         {3, 6, 9, 12, 15, 18, 21, 24, 27, 30}
       };
      Print("array_static before Swap:");
      ArrayPrint(array_static);
      if(m.Swap(array_static))
       {
        Print("array_static after Swap:");
        ArrayPrint(array_static);
        Print("matrix after Swap: \n", m);
       }
      else // a static array cannot be used to swap with a matrix
       {
        Print("m.Swap(array_static) failed. Error ", GetLastError());
       }
      /*
      array_static before Swap:
             [,0]     [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]     [,9]
      [0,]  1.00000  2.00000  3.00000  4.00000  5.00000  6.00000  7.00000  8.00000  9.00000 10.00000
      [1,]  2.00000  4.00000  6.00000  8.00000 10.00000 12.00000 14.00000 16.00000 18.00000 20.00000
      [2,]  3.00000  6.00000  9.00000 12.00000 15.00000 18.00000 21.00000 24.00000 27.00000 30.00000
      m.Swap(array_static) failed. Error 4006
      */
    //--- another attempt to swap an array and a matrix
      double array_dynamic[][10];    // dynamic array
      ArrayResize(array_dynamic, 3); // set the first dimension size
      ArrayCopy(array_dynamic, array_static);
    //--- now use a dynamic array for swap
      if(m.Swap(array_dynamic))
       {
        Print("array_dynamic after Swap:");
        ArrayPrint(array_dynamic);
        Print("matrix after Swap: \n", m);
       }
      else //  no error
       {
        Print("m.Swap(array_dynamic) failed. Error ", GetLastError());
       }
      /*
      array_dynamic after Swap:
            [,0]    [,1]    [,2]    [,3]    [,4]    [,5]    [,6]    [,7]    [,8]    [,9]
      [0,] 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000
      matrix after Swap:
      [[1,2,3,4,5,6,7,8,9,10,2,4,6,8,10,12,14,16,18,20,3,6,9,12,15,18,21,24,27,30]]
      */
     }
  9. MQL5: Added LossGradient method for vectors and matrices. This method calculates a vector or matrix of partial derivatives of the loss function on predicted values. In linear algebra, such a vector is referred to as a gradient and is used in machine learning.
    vector vector::LossGradient(const vector &expected,ENUM_LOSS_FUNCTION loss) const;
    matrix matrix::LossGradient(const matrix &expected,ENUM_LOSS_FUNCTION loss) const;
  10. MQL5: Enabled use of FOREIGN KEYS in SQLite to enforce relationships between tables in SQL queries.   Example:
    CREATE TABLE artist(
      artistid    INTEGER PRIMARY KEY, 
      artistname  TEXT
    );
    
    CREATE TABLE track(
      trackid     INTEGER, 
      trackname   TEXT, 
      trackartist INTEGER,
      FOREIGN KEY(trackartist) REFERENCES artist(artistid)
    );

  11. MQL5: Fixed selection of the appropriate class method depending on the method and object constness.

  12. MetaEditor: Increased allowable length of comments in commits to MQL5 Storage. Detailed comments when committing changes to the repository are considered good practice when working in large projects, but previously the comment length has been limited to 128 characters. The allowed length is now up to 260 characters.
  13. MetaTester: Increased sensitivity of the testing speed switch in visual mode.
  14. Fixed errors reported in crash logs.


The update will be available through the Live Update system.

New WebTerminal — fast, modern and secure
New WebTerminal — fast, modern and secure
  • 2022.10.12
  • MetaQuotes
  • www.metatrader5.com
MetaQuotes has released a completely new web terminal for MetaTrader 5. The web terminal enables trading from any web browser as it works in all operating systems without extra software installations. It is safe to use since all transmitted information is securely encrypted. The new web terminal has become faster and more efficient while it...
 

I am a bit confused du to the behaviour of scripts in b 3476:

My little script which is started on a H1 timeframe but deals with M! and an indicator (MACD) in H1 tries to get the data of the MACD as of 2019 (on a MQ demo acct).

First the times are set

void OnStart()
  {
//---

      datetime start = D'2019.09.21 00:00:00';
      int   iB       = iBarShift(_Symbol,PERIOD_M1,start,false), 
            iAll     = Bars( _Symbol,PERIOD_M1); //

      
      datetime tNull = iTime(_Symbol,PERIOD_M1,0),
               tAll  = iTime(_Symbol,PERIOD_M1,iAll),
               tChck = iTime(_Symbol,PERIOD_M1,iB);
       

      Print("tCheck[",iB,"] ",TimeToString(tChck,TIME_DATE|TIME_MINUTES),"  tNull[0] ",TimeToString(tNull),"  tAll[",iAll,"] ",TimeToString(tAll));

This prints out:

(USDJPY,H1)    tCheck[500596] 1970.01.01 00:00  tNull[0] 2022.10.27 21:39  tAll[500597] 1970.01.01 00:00

I learned and expected that at 0 I can find the oldest value.

Anyway I start the loop at iB=500597 down to 0:

      int hMacd = iCustom(_Symbol,PERIOD_H1,"Examples\\MACD");                          // get the handle of the MACD
      double Macd0[],Macd1[],Macd2[],Macd3[];

      for(iB=500597;iB>0;iB--) {

         datetime tC = iTime(_Symbol,PERIOD_M1,iB);      // get the actual time of iB
         int nCopy = CopyBuffer(hMacd,0,tC,5,Macd0);     // get the values of the MACD
             if (nCopy<3) continue;                      // if there weren't enough values: next iB
             nCopy = CopyBuffer(hMacd,1,tC,5,Macd0);     // get the values of the MACD
             if (nCopy<3) continue;                      // if there weren't enough values: next iB
             nCopy = CopyBuffer(hMacd,2,tC,5,Macd0);     // get the values of the MACD
             if (nCopy<3) continue;                      // if there weren't enough values: next iB
             nCopy = CopyBuffer(hMacd,3,tC,5,Macd0);     // get the values of the MACD
             if (nCopy<3) continue;                      // if there weren't enough values: next iB

         Print("first indicator values at [",iB,"] ",TimeToString(tC,TIME_DATE|TIME_MINUTES) ); 
         return;

And what do I get:

(USDJPY,H1)    first indicator values at [499999] 2021.06.28 17:39
  • WHY first values of the MACD only as of 2021?
  • WHY the circle of time => iB => time fails?
  • WHY is the direction of the iTime and iBarShift are just the other way around?

Here is this little script that spoiled my day.

Please tell me if I am missing anything.

Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
CopyBuffer - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
Files:
 
By the way what will happen to SendNotification() which send the message to the mobile app if these are replaced by the web terminal?
 
Carl Schreiber #: By the way what will happen to SendNotification() which send the message to the mobile app if these are replaced by the web terminal?

I guess users will just have to fall back on using the older SendMail() instead for now until web push notifications are implemented by MetaQuotes.

 

Is there any chance that the web terminal could be built inside some type of desktop app, using electron or something?

Also is there any chance to create custom indicators and expert advisors in JavaScript for the web terminal?

 
Daniel Erncliff Harding #: Is there any chance that the web terminal could be built inside some type of desktop app, using electron or something? Also is there any chance to create custom indicators and expert advisors in JavaScript for the web terminal?

Why? There is already a MetaTrader desktop application, which has custom indicators, EAs, etc.

 

MT5 and Ubuntu/wine isn't the best. Some of the UI elements aren't supported correctly. Also JavaScript is a more popular language with a lot of apps moving to HTML5 for true portability.

 
Daniel Erncliff Harding #: MT5 and Ubuntu/wine isn't the best. Some of the UI elements aren't supported correctly. Also JavaScript is a more popular language with a lot of apps moving to HTML5 for true portability.

TradingView is a web based trading platform, yet they didn't go the JavaScript route. In fact, I don't know of any popular trading platform that uses JavaScript for algorithmic trading. Do you know of any?

 
Fernando Carreiro #:

TradingView is a web based trading platform, yet they didn't go the JavaScript route. In fact, I don't know of any popular trading platform that uses JavaScript for algorithmic trading. Do you know of any?

TradingView is no good for some brokers because you can't write to the broker's API if it's not supported by TradingView. Also it's a subscription software when MT5 does the same thing for free.

A Web trader is built on JavaScript, it requires JavaScript to be web based. It wouldn't be too difficult to export some of the libraries to JavaScript for a web based app.

 
Daniel Erncliff Harding #A Web trader is built on JavaScript, it requires JavaScript to be web based. It wouldn't be too difficult to export some of the libraries to JavaScript for a web based app.

I'm well aware of how a web application is coded, I made my living doing just that for many years.

That was however not my question. My question was — do you know of any popular platform that offers a JavaScript API for algorithmic trading?

 
Fernando Carreiro #:

I'm well aware of how a web application is coded, I made my living doing just that for many years.

That was however not my question. My question was — do you know of any popular platform that offers a JavaScript API for algorithmic trading?

That's why I asked if the idea was considered to be implemented. JavaScript is native to the browser and doesn't even need to be compiled or decoded by the platform. Obviously the functions used by indicators already exist or the native indicators wouldn't work. They simply need to expose the API to the browser, the browser takes care of the rest.

Reason: