Скачать MetaTrader 5

Длинные котировки или числа не поддающиеся нормализации.

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Ilya Prozumentov
275
Ilya Prozumentov  
Есть индикатор, он производит сравнение котировок между собой и на основании этого строит линию, по одной из подходящих цен. Изначально последовательность действий была такая:
//RT - rates total
//PC - prevev calculated
{
   RT = iBars(_Symbol, InTimeframe);
   Index = RT - PC - 1;
   if(Index == -1)
      Index = 0;
   
   for(Index = Index; Index > -1; Index--)
   {
      OHLCCorrector();
      LimitZone();
   }   
   PC = RT;
   return(rates_total)
}
и индикатор исправно работал.

Затем я научил его строить Фибоначчи, но для оптимизации рисования потребовалось определять появление нового бара и код стал таким:
{
   RT = iBars(_Symbol, InTimeframe);
   Index = RT - PC - 1;
   if(Index == -1)
      Index = 0;
   
   for(Index = Index; Index > -1; Index--)
   {
      OHLCCorrector();
      LimitZone();
      if((RT - PC) == 1)
         Fibonacci();
      PC = RT - Index;
   }
   return(rates_total);
}
этот код отказался исправно работать, основная линия индикатора обрывалась. При пошаговом изучении происходящего обнаружилось, что теперь ни одно из условий для записи определённого значения в индикаторный буфер не выполнялось. Причиной стала котировка несоответствующей точности. То есть вместо 0,8386  iClose выдавал 0,838599999999. Такие же длинные котировки проскакивают и при печати в журнал. Я попробовал применить нормализацию. Нормализация до 3-х знаков сработала, но до 4-х никак не помогла. Я попробовал преобразование Double - Str - Double с точностью 4, но и это не принесло результата. В архиве котировок, если туда вручную заглянуть, таких длинных котировок нет.
Ilyas
1208
Ilyas  
http://www.softelectro.ru/ieee754.html -  хорошая статья, прочитайте про точность представления вещественных чисел
ksili
14
ksili  

Тут только поможет нормализация. Переменные должны быть типа float. С типом double у меня тоже не всегда нормализовало. А вот с флоатом никаих проблем не возникало.

Ilyas
1208
Ilyas  
Не используйте float!
Этот тип позволяет хранить только очень приблизительные значения.

Пример:
input double d=10.0;
input float  f=10.0f;

void OnStart()
  {
   Print(typename(d),": ",(7/d)*1000.0);
   Print(typename(f),": ",(7/f)*1000.0);
  }

Результат:
float:  699.9998688697815
double: 700.0
ksili
14
ksili  

блин о чем я сказал? о том что нужно нормализовать флоат. если вы приведете нормализацию флоата то будет тоже 700

а переменные типа дабл не всегда правильно нормализуются 

Ilyas
1208
Ilyas  
ksili:

блин о чем я сказал? о том что нужно нормализовать флоат. если вы приведете нормализацию флоата то будет тоже 700

а переменные типа дабл не всегда правильно нормализуются 

Числа нормализуются до нужного знака всегда!

Но вот не всегда вещественное число можно представить в виде конечной двоичной записи и погрешность для float выше, т.к. мантиса значительно меньше(23 бита), чем у double (52 бита).
Slava
Модератор
6918
Slava  
ksili:

блин о чем я сказал? о том что нужно нормализовать флоат. если вы приведете нормализацию флоата то будет тоже 700

а переменные типа дабл не всегда правильно нормализуются 

Вы сначала прочитайте статью, которую Вам порекомендовали.

Топикстартер же даже не подозревает, что 0,838599999999 является нормализованным значением и в дальнейшей нормализации не нуждается. Тоже не читал документацию https://docs.mql4.com/ru/basis/types/double, https://docs.mql4.com/ru/convert/normalizedouble, https://docs.mql4.com/ru/basis/operations/relation

Mislaid
617
Mislaid  
ksili:

блин о чем я сказал? о том что нужно нормализовать флоат. если вы приведете нормализацию флоата то будет тоже 700

а переменные типа дабл не всегда правильно нормализуются 

Если вас интересует равенство двух вещественных чисел, то знания о нормализации являются излишеством.

Я пользуюсь следующим: два вещественных числа считаются равными, если абсолютное значение их разности меньше заданного маленького числа.

noloxe
476
noloxe  
mql5:
http://www.softelectro.ru/ieee754.html -  хорошая статья, прочитайте про точность представления вещественных чисел

А почему бы вам не ввести (в MQL), автоматическую нормализацию всех расчетов?

Можно по указанию при инициализации: 

— по разрядности текущего инструмента, 

— по выбранной разрядности

— при явном указании (иначе по инструменту)

— без нормализцации (как сейчас) 

... 

 

кстати и округление можно было бы разное ввести, чтобы можно было нормализировать "отбрасыванием лишних разрядов" 

Vladimir
332
Vladimir  
noloxe:

А почему бы вам не ввести (в MQL), автоматическую нормализацию всех расчетов?

Можно по указанию при инициализации: 

— по разрядности текущего инструмента, 

— по выбранной разрядности

— при явном указании (иначе по инструменту)

— без нормализцации (как сейчас) 

... 

 

кстати и округление можно было бы разное ввести, чтобы можно было нормализировать "отбрасыванием лишних разрядов


Здесь говорится, что сейчас расчеты идут без нормализации. Это не так. Вне всяких языков уровня MQL само аппаратное представление чисел с плавающей точкой на разных платформах (Стандарт IEEE 754-1985) уже включает такие понятия:

  • как представлять нормализованные положительные и отрицательные числа с плавающей точкой
  • как представлять денормализованные положительные и отрицательные числа с плавающей точкой
  • как представлять нулевые числа
  • как представлять специальную величину бесконечность (Infinity)
  • как представлять специальную величину "Не число" (NaN или NaNs)
  • четыре режима округления

  • Чуть выше mql5 дал ссылку http://www.softelectro.ru/ieee754.html, где это написано. намного подробнее

    Понятие "нормализации вещественных чисел" в MQL отвечает очень специальной задаче, сводится к десятичному округлению до 0-8 значащих цифр и, конечно же, противоречит общепринятому понятию нормализованности вещественных чисел в двоичном представлении. Его лучше не развивать, а назвать иначе. Зачем ему дали название из общеупотребительных, не знаю, но, по-моему, хорошо бы избавиться от возникающих неясностей. Простой путь - число типа "Цена" с теми же свойствами.

    P.S. В своих опусах я использую еще число типа "Объем". Указываю в начале программы единицы измерения объема (0.01 или 0.001 лота, это и минимальный объем, и шаг объемов) и остальные операции с объемами свожу к целым числам (в MT5 так не выходит).

    P.P.S. Думается, в https://docs.mql4.com/ru/basis/operations/relation фразу "Для корректного сравнения двух вещественных чисел необходимо сравнивать нормализованную разницу этих чисел с нулевым значением." необходимо поправить или убрать. Если править, то заменить "двух вещественных чисел" на "двух вещественных чисел ценовой природы (курс, уровень ордера...) "

    Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий