Bug concerning "Digits()" when using indicators in multi-currency

 

Hello,

it seems I found a bug when calling the "Digits()"-function inside of an indicator used in a multi-currency system on the newest platform version. At least inside the backtester it will exclusively return the digits-value of the currency the expert is started on and NOT the value of the currency the indicator, called by the EA, is attached to. To see this, use the following code:

EA:

//+------------------------------------------------------------------+
//|                                                   DigitsTest.mq5 |
//|                                           Copyright 2020, Markus |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Markus"
#property link      ""
#property version   "1.00"



int   ghDigitsTestEURJPY = NULL;
int   ghDigitsTestEURUSD = NULL;



//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---
   Print(Symbol() + ": Digits(): " + (string)(Digits()));
   ghDigitsTestEURJPY = iCustom("EURJPY", PERIOD_H6, "DigitsTest");
   if(ghDigitsTestEURJPY == INVALID_HANDLE)
   {
      Print("ghDigitsTest == INVALID_HANDLE");
      return (INIT_PARAMETERS_INCORRECT);
   }
   ghDigitsTestEURUSD = iCustom("EURUSD", PERIOD_H6, "DigitsTest");
   if(ghDigitsTestEURUSD == INVALID_HANDLE)
   {
      Print("ghDigitsTest == INVALID_HANDLE");
      return (INIT_PARAMETERS_INCORRECT);
   }
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   ExpertRemove();
}
//+------------------------------------------------------------------+

Indicator:

//+------------------------------------------------------------------+
//|                                                   DigitsTest.mq5 |
//|                                           Copyright 2020, Markus |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Markus"
#property link      ""
#property version   "1.00"
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   Print("Indicator DigitsTest: " + Symbol() + ": Digits(): " + (string)(Digits()));
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

In this example you will see that, when the EA is started on "EURUSD", the "Digits()"-value of "EURJPY" will be 5 and when the EA is started on "EURJPY" the "Digits()"-value of "EURUSD" will be 3. This obviously cannot be correct and can lead to problems. Provided I'm not doing somthing wrong, please fix this, dear MetaQuotes developer team. Many thanks in advance.

Testing trading strategies on real ticks
Testing trading strategies on real ticks
  • www.mql5.com
The article provides the results of testing a simple trading strategy in three modes: "1 minute OHLC" using only Open, High, Low and Close prices of minute bars; detailed modeling in "Every tick" mode, as well as the most accurate "Every tick based on real ticks" mode applying actual historical data. Comparing the results allows us to assess...
 

Try these two modes in the tester, and run online on the chart.

I have the following results: when testing on history  Digits () in your example does not work correctly. With a single test  and when you start online - everything works fine.

 
Markus: digits-value of the currency the expert is started on and NOT the value of the currency the indicator, called by the EA,

Perhaps you should read the manual. Digits() has nothing to do with any indicator. It only deals with the current chart symbol.
          Checkup / Digits - Reference on algorithmic/automated trading language for MetaTrader 5
versus
          SymbolInfoIntegerENUM_SYMBOL_INFO_INTEGER → SYMBOL_DIGITS

 

New study:

//+------------------------------------------------------------------+
//|                                                   DigitsTest.mq5 |
//|                                           Copyright 2020, Markus |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Markus"
#property link      ""
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   long dig=SymbolInfoInteger(Symbol(),SYMBOL_DIGITS);
   Print("Indicator DigitsTest: ",Symbol(),", _Digits: ",_Digits,", Digits(): ",Digits(),", ::Digits(): ",::Digits(),", SYMBOL_DIGITS: ",dig);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   long dig=SymbolInfoInteger(Symbol(),SYMBOL_DIGITS);
   Print("Indicator DigitsTest: ",Symbol(),", _Digits: ",_Digits,", Digits(): ",Digits(),", ::Digits(): ",::Digits(),", SYMBOL_DIGITS: ",dig,", close ",close[rates_total-1]);
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


Expert:

//+------------------------------------------------------------------+
//|                                                DigitsTest EA.mq5 |
//|                                           Copyright 2020, Markus |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Markus"
#property link      ""
#property version   "1.00"

int   ghDigitsTestEURJPY = NULL;
int   ghDigitsTestEURUSD = NULL;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   Print(Symbol() + ": Digits(): " + (string)(Digits()));
   ghDigitsTestEURJPY=iCustom("EURJPY",PERIOD_H6,"DigitsTest");
   if(ghDigitsTestEURJPY==INVALID_HANDLE)
     {
      Print("ghDigitsTest == INVALID_HANDLE");
      return(INIT_PARAMETERS_INCORRECT);
     }
   ghDigitsTestEURUSD=iCustom("EURUSD",PERIOD_H6,"DigitsTest");
   if(ghDigitsTestEURUSD==INVALID_HANDLE)
     {
      Print("ghDigitsTest == INVALID_HANDLE");
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   static long counter=0;
   if(counter>=9)
      ExpertRemove();
   counter++;
  }
//+------------------------------------------------------------------+


Result: Please note: the price matches the symbol, and Digits does not match.

2020.01.19 00:00:00   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.163
2020.01.19 00:00:00   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10893
2020.01.20 00:05:00   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.145
2020.01.20 00:05:00   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.1092
2020.01.20 00:05:03   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.15
2020.01.20 00:05:06   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.155
2020.01.20 00:05:06   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10917
2020.01.20 00:05:09   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.154
2020.01.20 00:05:12   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.152
2020.01.20 00:05:13   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10918
2020.01.20 00:05:15   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.155
2020.01.20 00:05:18   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.159
2020.01.20 00:05:20   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10915
2020.01.20 00:05:22   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.151
2020.01.20 00:05:25   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.143
2020.01.20 00:05:26   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10916
2020.01.20 00:05:28   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.142
2020.01.20 00:05:31   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.144
2020.01.20 00:05:33   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10913
2020.01.20 00:05:34   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.128
2020.01.20 00:05:37   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.129
2020.01.20 00:05:40   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10915
2020.01.20 00:05:41   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.113
2020.01.20 00:05:44   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.122
2020.01.20 00:05:47   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.119
2020.01.20 00:05:50   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.122
2020.01.20 00:05:59   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.125
2020.01.20 00:05:59   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10914
2020.01.20 00:06:00   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.118
2020.01.20 00:06:00   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10912
2020.01.20 00:06:00   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.119
2020.01.20 00:06:01   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.121
2020.01.20 00:06:02   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.122
2020.01.20 00:06:03   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10913
2020.01.20 00:06:03   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.124
2020.01.20 00:06:04   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.125
2020.01.20 00:06:05   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.127
2020.01.20 00:06:06   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.128
2020.01.20 00:06:07   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10915
2020.01.20 00:06:07   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.127
2020.01.20 00:06:08   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.128
2020.01.20 00:06:09   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.127
2020.01.20 00:06:10   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.128
2020.01.20 00:06:10   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10916
2020.01.20 00:06:10   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.126
2020.01.20 00:06:11   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.127
2020.01.20 00:06:12   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.129
2020.01.20 00:06:13   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.13
2020.01.20 00:06:14   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10914
2020.01.20 00:06:14   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.132
2020.01.20 00:06:15   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.133
2020.01.20 00:06:16   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.135
2020.01.20 00:06:17   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.10915
2020.01.20 00:06:17   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.136
2020.01.20 00:06:18   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.135
2020.01.20 00:06:19   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.136
Files:
 
Thank you very much for your study which shows my point, I assume. Apropos "point" - I also found a comparable result with "Point()". So, when obviously currently there is no way to get the correct values inside of an indicator, invisibly attached to another symbol than its creating EA, running inside of the backtester, what could one do? Currently I only can think of a workaround like an "input" or glabal variable to get this working, which seems rather cumbersome. Hopefully a MetaQuotes developer reads this and is going to provide a simple solution within a relatively short amount of time. Thanks all.
 
Alain Verleyen:

There is no problem and all of that is normal.

Read the documentation correctly please. William is right.

I misunderstood OPs post/question and now agree with him. The call is an iCustom using symbol (EURUSD) which is different from the chart's (EURJPY.) The indicator running on EURUSD reads correct prices but incorrect digits/point for EURUSD (which has 5 digits.)

2020.01.20 00:05:00   Indicator DigitsTest: EURUSD, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 1.1092
2020.01.20 00:05:03   Indicator DigitsTest: EURJPY, _Digits: 3, Digits(): 3, ::Digits(): 3, SYMBOL_DIGITS: 3, close 122.15
 
William Roeder:

I misunderstood OPs post/question and now agree with him. The call is an iCustom using symbol (EURUSD) which is different from the chart's (EURJPY.) The indicator running on EURUSD reads correct prices but incorrect digits/point for EURUSD (which has 5 digits.)

Yes me too, that's why I deleted my post. Need rest :-D
 
Need to post more after the coffee kicks in. :-D
 
Thanks for reviewing this. I hope you got good rest although it's evening yet again - at least in my timezone :-D.
Reason: