Можно ли в MQL5 задать тип decimal

 
Очень нужен тип decimal, это тот который double, но не такой плавающий :)

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

Или хотя бы, может есть возможность задания своего типа в MQL5, о которой я не знаю? Например, как-то так или через макросы :
typedef decimal NormalizeDouble(double, 2);
Дальше будет много буков с пояснением, зачем.
 
Как минимум в двух случаях я такое замечал, когда писал расчет виртуальных ордеров, дублирующих неттинг исполнение МТ5 и вот сейчас в советнике, пример ниже.
И если с ордерами расчетов было много и погрешность double была предсказуема + кривизна моих рук, то боюсь, что из-за подобных ошибок в советнике я мог пару годных стратегий спустить на мусорку, в частности тех, которые работают с пересчетом лотов на сделку.

Вот кусок банального, неприметного кода, MT5 hedging mode :
double buyAlignment = sizeSell - sizeBuy; // check if lot of Sell > lot of Buy
double sellAlignment = sizeBuy - sizeSell; // check if lot of Buy > lot of Sell

if (buyAlignment > 0) // if Sell > Buy, make positions equal by size
{
    Print("################## BUY : " + buyAlignment + " = " + sizeSell + " - " + sizeBuy);
    openSimplePosition(symbol, 1, buyAlignment);
}

if (sellAlignment > 0) // if Buy > Sell, make positions equal by size
{
    Print("################## SELL : " + sellAlignment + " = " + sizeBuy + " - " + sizeSell);
    openSimplePosition(symbol, -1, sellAlignment);
}
Результат выполнения этого кода в нормальном случае выглядит так :
2016.12.17 03:04:58.657    2016.01.06 16:00:00   ################## SELL : 0.01 = 0.02 - 0.01
Но потом случается чудо ...
2016.12.17 03:05:47.736    2016.01.06 18:00:00   ################## SELL : 0.009999999999999998 = 0.03 - 0.02  //  WTF ???
Ну ок, допустим, у МТ какие-то свои мысли по поводу того, как представлять число, но тогда логично предположить, что код везде сьедает double в меньшую сторону, НО ... тут проиходит второе чудо и МТ решает, что 0 это вовсе не 0, а 0.0000000000000000000036453265234832582365325, ну что ж логично, и в результате этого "логично" я получаю такое :)
2016.12.17 03:08:33.094    2016.01.06 19:54:01   ################## BUY : 2.775557561562891e-17 = 0.15 - 0.15
2016.12.17 03:08:33.094    2016.01.06 19:54:01   failed market buy 0.00 EURUSD.m [Invalid volume]
Сразу отвечу "умникам", которые попытаются указать на то, что я делаю неявную конвертацию double в строку при выводе сообщения ... я то делаю, но вот факт, что в самом коде проверка (0 > 0.15 - 0.15) проходит, меня пугает ...
Для воспроизведения ошибки, напишите советника, которые, на каждом баре открывает позицию, рандомно, а через каждые, допустим, 5 баров делает позиции равными, как в коде выше.
 
#define ND(A) NormalizeDouble(A, 2)

Поможет это

Price_Compare
Price_Compare
  • голосов: 18
  • 2016.08.25
  • fxsaber
  • www.mql5.com
Изящное и шустрое сравнение double-значений "цены".
 
fxsaber:
#define ND(A) NormalizeDouble(A, 2)
Спасибо, этот макрос выглядит симпатичней и короче, но хотелось бы все же статический тип, чтобы при любой операции с переменной быть уверенным в точности округления, на случай, если в каком-то месте в коде я забуду вызвать нормализацию
 
Andy Sanders:
Ну ок, допустим, у МТ какие-то свои мысли по поводу того, как представлять число, но тогда логично предположить, что код везде сьедает double в меньшую сторону, НО ... тут проиходит второе чудо и МТ решает, что 0 это вовсе не 0, а 0.0000000000000000000036453265234832582365325, ну что ж логично, и в результате этого "логично" я получаю такое :)


Сразу отвечу "умникам", которые попытаются указать на то, что я делаю неявную конвертацию double в строку при выводе сообщения ... я то делаю, но вот факт, что в самом коде проверка (0 > 0.15 - 0.15) проходит, меня пугает ... 
Для воспроизведения ошибки, напишите советника, которые, на каждом баре открывает позицию, рандомно, а через каждые, допустим, 5 баров делает позиции равными, как в коде выше.

Строите из себя умного...
но при этом нет понимания принципов сравнения  doulbe вообще.
печаль... 

Особенности работы с числами типа double в MQL4
Особенности работы с числами типа double в MQL4
  • 2009.11.02
  • MetaQuotes Software Corp.
  • www.mql5.com
В данной заметке собраны советы по решению наиболее часто возникающих ошибок при работе с числами типа double в программах на MQL4.
 
ALXIMIKS5:

Строите из себя умного...
но при этом нет понимания принципов сравнения  doulbe вообще.
печаль... 

1. я спросил про decimal, а не то, как сравниваются double
2. ты действительно в упор не видишь ошибки? 

Если вот эту чепуху еще можно списать на представление числа
0.15 - 0.15 = 0.000000...277
... то вот такое выглядит уж точно бредово. Раз уж есть неявное преобразование типов в проверке, то в нормальных языках оно делается по первому параметру, который в моем случае вообще INT. Теперь условие выглядит так
if (0 < sellAlignment)

вот только изменений все нет и нет :)

0 < 0.15 - 0.15
Печально, что кое-кто этого не знает, а "умничает", была раньше реклама, там говорилось "иногда лучше жевать" ...
 
Лол, даже в статье указано на то, как правильно, а интерпритатор все равно по-другому поступает :)

В разделе 6. Приведение типов - integer и double

А вообще, наличие этой статьи и соответствующих библиотек говорит о том, что decimal реально нужен, и это не пожелание ничтожества вроде меня, а фактическая необходимость

 
Andy, представьте, что вы неправы по причине незнания вещественной арифметики.

У нас все абсолютно правильно считается и полностью соответствует C/C++. И покрыто несколькими тысячами постоянно повторяемыми тесткейсами.

Вы просто совершаете банальные ошибки и не понимаете способа представления вещественных чисел.

Decimal вводить не будем.
 
Andy Sanders:
Очень нужен тип decimal, это тот который double, но не такой плавающий :)

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

Или хотя бы, может есть возможность задания своего типа в MQL5, о которой я не знаю? Например, как-то так или через макросы :
typedef decimal NormalizeDouble(double, 2);
Дальше будет много буков с пояснением, зачем.

Если Вам нужен тип decimal, то Вы можете сами его сделать.

class decimal
{
   ...
  
public:
   decimal( double val );
   decimal( int val );
   decimal( string val );
  
   void operator=( const decimal& val );
   void operator=( const double val );
   void operator=( const int val );
   void operator+=( const decimal& val );
   void operator+=( const double val );
   void operator+=( const int val );
   void operator-=( const decimal& val );
   void operator-=( const double val );
   void operator-=( const int val );
   bool operator==( const decimal& val);
   bool operator!=( const decimal& val );
  
   decimal operator+( const decimal& val );
   decimal operator+( const double val );
   decimal operator+( const int val );
   decimal operator-( const decimal& val );
   decimal operator-( const double val );
   decimal operator-( const int val );
   decimal operator*( const decimal& val );
   decimal operator*( const double val );
   decimal operator*( const int val );
   decimal operator/( const decimal& val );
   decimal operator/( const double val );
   decimal operator/( const int val );
  
   string toString() const;
   double toDouble() const;
};

Работать будет в точности так, как Вы сами захотите.

Помещаете этот класс в файл decimal.mqh и включаете его везде, где нужно:

#include <decimal.mqh>
 
Koldun Zloy:

Если Вам нужен тип decimal, то Вы можете сами его сделать.

К сожалению, например, выражение double + decimal работать не будет (слагаемые наоборот - будет).
 

Ладно, фразу про другие языки забираю обратно, был неправ, в C# воспроизводится.
Но тем не менее, decimal был бы полезен.

double x1 = 0.01;
double x2 = 0.02;
double x3 = 0.03;
double x4 = 0.01;
double x5 = 0.01;
double x6 = 0.01;
double x7 = 0.01;
double x8 = 0.05;

double x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8;
double y = 0.15;
double z = x - y;

if (z != 0) Print(x - y);

// 2016.12.17 16:01:04.983    Index (GBPAUD.m,H1)    -2.775557561562891e-17
Причина обращения: