Как определить количество знаков после запятой?

 
 Всем доброго дня! 
 Подскажите пожалуйста 
 Как определить количество знаков в котировке после запятой?
 
Highlander9:
 Всем доброго дня! 
 Подскажите пожалуйста 
 Как определить количество знаков в котировке после запятой?
_Digits
Это для текущего символа.
 

Остальные

MarketInfo(Symbol(),MODE_DIGITS)
 

Разрядность брокера можно так определить

   if (Digits==5 || Digits==3)
      {
         // 5-разрядный брокер
       }
      else
      {
         // 4-разрядный брокер
       }
 
Vadim Zotov:

Разрядность брокера можно так определить

   if (Digits==5 || Digits==3)
      {
         // 5-разрядный брокер
       }
      else
      {
         // 4-разрядный брокер
       }

Ога.

Хороший пример, когда на инструменте будет разрядность 2.

Подобные умолчания (что у брокера обязательно на евродолларе будет 4 или 5 символов, а на иенадолларе при этом обязательно соответсвенно 2 или 3 символа, а остальных инструментов у ДЦ просто нет) - приводят к трудно вычисляемым ошибкам. Это опасный стиль программирования (даже не программирования а построения алгоритма).

Выше даны правильные методы выяснения разрядности.

 
George Merts:

Ога.

Хороший пример, когда на инструменте будет разрядность 2.

Подобные умолчания (что у брокера обязательно на евродолларе будет 4 или 5 символов, а на иенадолларе при этом обязательно соответсвенно 2 или 3 символа, а остальных инструментов у ДЦ просто нет) - приводят к трудно вычисляемым ошибкам. Это опасный стиль программирования (даже не программирования а построения алгоритма).

Выше даны правильные методы выяснения разрядности.

Ну вот ещё один вариант когда можно обойтись без MarketInfo

if(_Digits % 2 == 0) // если остаток от деления на 2 равен нулю
// будет 4 или 2
else
// будет 5 или 3
 
Alexey Viktorov:

Ну вот ещё один вариант когда можно обойтись без MarketInfo

Не, такой вариант - это вариант, годящийся для победы в каких-нибудь конкурсах программистов. Как пример хитрых приемов, позволяющих сократить обращения к MarketInfo(), или совместить несколько проверок в одной. Очень даже интересная возможность.

Но, для рабочего кода советника, считаю, такой алгоритм - категорически не годится.

Во-первых, такой код учитывает группы совершенно несвязанных сущностей - 4 и 2 разряда или 5 и 3 разряда. Что способствует неверному пониманию работы алгоритма.

Во-вторых, такой код требует небольшого времени для осмысления, и прикидок, в каком случае какая ветка будет задействована. Что также способствует ошибкам в понимании.

В-третьих, функция MarketInfo() - функция непереносимая, в результате код не будет одинаково работать на МТ4 и МТ5 - что я считаю огромным минусом кода.

На мой взгляд, единственно правильный способ разделения вариантов по разрядности - это запрос через bool SymbolInfoInteger() и прямое разделение через несколько if'ов или через switch:

...

string strSymbol = Symbol();  // Здесь получаем текущий символ, или любой другой.
long lDigits = WRONG_VALUE;  

if(SymbolInfoInteger(strSymbol,SYMBOL_DIGITS,lDigits) != true)
   {
   // Ошибка получения данных - возвращаем признак ошибки
   return(WRONG_VALUE);
   };
  
switch(lDigits)
   {
   case 2:
      // Действия с двухразрядными котировками
      ....
   break;
  
   case 3:
      // Действия с трехразрядными котировками
      ....
   break;
  
   case 4:
      // Действия с четырехразрядными котировками
      ....
   break;
  
   case 5:
      // Действия с пятиразрядными котировками
      ....
   break;
  
   default:
      // Действия в случае обнаружения неизвестной разрядности котировок.
      ....
   break;
   };     
...  

 
George Merts:

Не, такой вариант - это вариант, годящийся для победы в каких-нибудь конкурсах программистов. Как пример хитрых приемов, позволяющих сократить обращения к MarketInfo(), или совместить несколько проверок в одной. Очень даже интересная возможность.

Но, для рабочего кода советника, считаю, такой алгоритм - категорически не годится.

Во-первых, такой код учитывает группы совершенно несвязанных сущностей - 4 и 2 разряда или 5 и 3 разряда. Что способствует неверному пониманию работы алгоритма.

Во-вторых, такой код требует небольшого времени для осмысления, и прикидок, в каком случае какая ветка будет задействована. Что также способствует ошибкам в понимании.

В-третьих, функция MarketInfo() - функция непереносимая, в результате код не будет одинаково работать на МТ4 и МТ5 - что я считаю огромным минусом кода.

На мой взгляд, единственно правильный способ разделения вариантов по разрядности - это запрос через bool SymbolInfoInteger() и прямое разделение через несколько if'ов или через switch:

...

string strSymbol = Symbol();  // Здесь получаем текущий символ, или любой другой.
long lDigits = WRONG_VALUE;  

if(SymbolInfoInteger(strSymbol,SYMBOL_DIGITS,lDigits) != true)
   {
   // Ошибка получения данных - возвращаем признак ошибки
   return(WRONG_VALUE);
   };
  
switch(lDigits)
   {
   case 2:
      // Действия с двухразрядными котировками
      ....
   break;
  
   case 3:
      // Действия с трехразрядными котировками
      ....
   break;
  
   case 4:
      // Действия с четырехразрядными котировками
      ....
   break;
  
   case 5:
      // Действия с пятиразрядными котировками
      ....
   break;
  
   default:
      // Действия в случае обнаружения неизвестной разрядности котировок.
      ....
   break;
   };     
...  

Если учесть что говорим о форексе, где котировки могут быть 2 и 4 или 3 и 5, то получается в твоём варианте будет по два одинаковых блока.

Поленился я расписывать с SymbolInfoInteger(). А лучший вариант наверное будет если совместить наши варианты в один.

 
Alexey Viktorov:

получается в твоём варианте будет по два одинаковых блока.

Тут - надо глядеть конкретно по ситуации.

Если два реально одинаковых блока - их разумнее запихнуть в функцию, и вызывать ее.

Плюс сам оператор switch() допускает синтаксис с несколькими выборами для одного блока.

Возможно, конечно, и совмещение в условии. Но, лично для себя я давно уже понял, что код должен быть как можно "прямолинейнее" и "прозрачнее". Всякие "хитрые приемчики" - всегда выходят боком при дальнейшей необходимости в поддержке.

В частности, из-за этого я совсем перестал использовать оператор "вопросик" - оператор if выглядит гораздо проще и логичнее, а эффективность кода получается та же.

 
Highlander9:
 Всем доброго дня! 
 Подскажите пожалуйста 
 Как определить количество знаков в котировке после запятой?

Лучше использовать новые функции одинаково работает в МТ4 и МТ5

   int digits = _Digits; // Для текущего символа
   int digits=(int)SymbolInfoInteger("EURUSD",SYMBOL_DIGITS); // для любого другого

 ...

 

Скрипт для анализа - сколько символов имеют какое количество разрядов:

//+------------------------------------------------------------------+
//|                                             AllSymbolsDigits.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   Print(AccountInfoString(ACCOUNT_SERVER));
//---
//+------------------------------------------------------------------+
//| arr_count_digits[6][2]                                           |
//| [SYMBOL_DIGITS] 0  1  2  3  4  5                                 |
//| [Count]         1  3  1  0  0  34                                |
//| arr_count_digits[5][0] == "5"                                    |
//| arr_count_digits[5][1] == "34"                                   |
//+------------------------------------------------------------------+
   int arr_count_digits[][2];
//ArrayResize(arr_count_digits,1,10);
//---
   int count=SymbolsTotal(false); // false - all symbols
   for(int i=0;i<count;i++)
     {
      string name=SymbolName(i,false);
      //ResetLastError();
      //while(!SymbolSelect(name,true))
      //  {
      //   Print("Symbol ",name," SymbolSelect error# ",GetLastError());
      //   Sleep(100);
      //  }
      long digits=-1;
      ResetLastError();
      if(!SymbolInfoInteger(name,SYMBOL_DIGITS,digits))
        {
         Print("Symbol ",name," SymbolInfoDouble  SYMBOL_DIGITS error# ",GetLastError());
         return;
        }
      //---
      int size=ArrayRange(arr_count_digits,0);
      bool result=false; // find flags
      for(int j=0;j<size;j++)
        {
         if(arr_count_digits[j][0]==digits)
           {
            arr_count_digits[j][1]++;
            result=true;
            break;
           }
        }
      if(!result)
        {
         ArrayResize(arr_count_digits,size+1,10);
         arr_count_digits[size][0]=(int)digits;
         arr_count_digits[size][1]=1;
        }
     }
//---
   int size=ArrayRange(arr_count_digits,0);
   for(int i=0;i<size;i++)
     {
      Print("SYMBOL_DIGITS ",arr_count_digits[i][0]," count ",arr_count_digits[i][1]);
     }
  }
//+------------------------------------------------------------------+

И результат для двух серверов:

2017.01.13 14:05:40.548 AllSymbolsDigits (EURUSD,M15)   RoboForex-MetaTrader 5
2017.01.13 14:05:40.548 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 5 count 57
2017.01.13 14:05:40.548 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 3 count 9
2017.01.13 14:05:40.548 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 4 count 22
2017.01.13 14:05:40.548 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 2 count 8
2017.01.13 14:06:07.414 AllSymbolsDigits (EURUSD,M15)   MetaQuotes-Demo
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 5 count 47
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 3 count 51
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 2 count 262
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 1 count 110
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 0 count 124
2017.01.13 14:06:07.417 AllSymbolsDigits (EURUSD,M15)   SYMBOL_DIGITS 4 count 30

Другое дело, что нужно смотреть, что это за символы с SYMBOL_DIGITS==0 или 2 или 4...

Файлы:
Причина обращения: