Ошибки, баги, вопросы - страница 1931

 

Утро вечера мудреннее... :)

 
Aleksey Vyazmikin:

В хелпе

MT4:

Для объектов с фиксированными размерами: OBJ_BUTTON, OBJ_RECTANGLE_LABEL и OBJ_EDIT свойства OBJPROP_XDISTANCE и OBJPROP_YDISTANCE задают положение левой верхней точки объекта относительно угла графика (OBJPROP_CORNER), от которого будут отсчитываться координаты X и Y в пикселях.

 


MT5:

Для объектов с фиксированными размерами: OBJ_BUTTON, OBJ_RECTANGLE_LABEL, OBJ_EDIT и OBJ_CHART свойства OBJPROP_XDISTANCE и OBJPROP_YDISTANCE задают положение левой верхней точки объекта относительно угла графика (OBJPROP_CORNER), от которого будут отсчитываться координаты X и Y в пикселях.

Казалось бы одно и то же, вот только в MT4 нет левой точки объекта для OBJ_LABEL - есть правая, но не это вызвало мой гнев, дело в том, что старый код MT4 с использованием ObjectSet позволял разместить объекты относительно краев (углов) - для объектов в левой части расчет пикселей шел от первого символа, для правой части - от последнего символа, а новый вариант всегда делает расчет отступа от первого символа, что затрудняет позиционирование лейблов с текстом, так как не всегда известно, сколько будет текстовых символов. Прошу разработчиков добавить выбор способа выравнивания текста!


Если кто знает, как в MT5 получать выравнивание по правому и левому краю, то прошу Вас поделиться соответствующей функцией!

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

Для объектов OBJ_LABEL, OBJ_BITMAP_LABEL и OBJ_RECTANGLE_LABEL можно задавать угол графика, относительно которого позиционируется точка привязки объекта. Этот угол устанавливается через свойство объекта OBJPROP_CORNER, которое может иметь одно из четырех значений перечисления ENUM_BASE_CORNER:

Идентификатор

Описание

CORNER_LEFT_UPPER

Координаты точки привязки заданы относительно левого верхнего угла графика

CORNER_LEFT_LOWER

Координаты точки привязки заданы относительно левого нижнего угла графика

CORNER_RIGHT_LOWER

Координаты точки привязки заданы относительно правого нижнего угла графика

CORNER_RIGHT_UPPER

Координаты точки привязки заданы относительно правого верхнего угла графика

Положение самой точки привязки объекта задается свойством OBJPROP_ANCHOR и может быть одним из 9-ти значений перечисления ENUM_ANCHOR_POINT:

Идентификатор

Описание

ANCHOR_LEFT_UPPER

Точка привязки в левом верхнем углу

ANCHOR_LEFT

Точка привязки слева по центру

ANCHOR_LEFT_LOWER

Точка привязки в левом нижнем углу

ANCHOR_LOWER

Точка привязки снизу по центру

ANCHOR_RIGHT_LOWER

Точка привязки в правом нижнем углу

ANCHOR_RIGHT

Точка привязки справа по центру

ANCHOR_RIGHT_UPPER

Точка привязки в правом верхнем углу

ANCHOR_UPPER

Точка привязки сверху по центру

ANCHOR_CENTER

Точка привязки строго по центру объекта

 
Artyom Trishkin:

Мне за вас передвинуть вверх пункт списка, который вы пытаетесь обозначить цифрой 4, которой там нету? Он становится нулевым - и всё на местах.

 

Конечно я всё передвинул - может туплю..



void OnStart()
  {
      Label("0",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "0 - Центр координат в левом верхнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            0        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );     
      Label("1",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "1 - Центр координат в левом нижнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            1        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );     
      Label("2",//Название
            0,       //Окно
            10,      //X
            32,      //Y
            "2 - Центр координат в правом нижнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            2        //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            );
      Label("3",//Название
            0,       //Окно
            10,     //X
            32,      //Y
            "3 - Центр координат в правом верхнем углу графика",
            10,//Размер шрифта
            Yellow,//Цвет шрифта
            3      //Выбор угла: 3 - нижний правый, 1 - верхний правый. 2 - нижний левый, 4 - верхний левый                   
            ); 

  }

//+------------------------------------------------------------------+
//|Функция вывода информации на экран -- Старый вариант              |
//+------------------------------------------------------------------+
void Label(string _name,int _window,int _x,int _y,string _text,int _font,color _color,int corner)
  {
   ObjectDelete(_name);
   ObjectCreate(_name,OBJ_LABEL,_window,0,0);
   ObjectSet(_name,OBJPROP_CORNER,corner);
   ObjectSet(_name,OBJPROP_XDISTANCE,_x);
   ObjectSet(_name,OBJPROP_YDISTANCE,_y);
   ObjectSetText(_name,_text,_font,"Arial",_color);
  }
/*
//+------------------------------------------------------------------+
//|Функция вывода информации на экран -- Новый вариант               |
//+------------------------------------------------------------------+
void Label(string _name,int _window,int _x,int _y,string _text,int _font,color _color,int corner)
  {
   //corner=4;
   ObjectDelete(0,_name);
   ObjectCreate(0,_name,OBJ_LABEL,_window,0,0);
   ObjectSetInteger(0,_name,OBJPROP_CORNER,corner);
   ObjectSetInteger(0,_name,OBJPROP_XDISTANCE,_x);
   ObjectSetInteger(0,_name,OBJPROP_YDISTANCE,_y);
   ObjectSetText(_name,_text,_font,"Arial",_color);
  }
*/   
 
Artyom Trishkin:

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

Для объектов OBJ_LABEL, OBJ_BITMAP_LABEL и OBJ_RECTANGLE_LABEL можно задавать угол графика, относительно которого позиционируется точка привязки объекта. Этот угол устанавливается через свойство объекта OBJPROP_CORNER, которое может иметь одно из четырех значений перечисления ENUM_BASE_CORNER:

Идентификатор

Описание

CORNER_LEFT_UPPER

Координаты точки привязки заданы относительно левого верхнего угла графика

CORNER_LEFT_LOWER

Координаты точки привязки заданы относительно левого нижнего угла графика

CORNER_RIGHT_LOWER

Координаты точки привязки заданы относительно правого нижнего угла графика

CORNER_RIGHT_UPPER

Координаты точки привязки заданы относительно правого верхнего угла графика

Положение самой точки привязки объекта задается свойством OBJPROP_ANCHOR и может быть одним из 9-ти значений перечисления ENUM_ANCHOR_POINT:

Идентификатор

Описание

ANCHOR_LEFT_UPPER

Точка привязки в левом верхнем углу

ANCHOR_LEFT

Точка привязки слева по центру

ANCHOR_LEFT_LOWER

Точка привязки в левом нижнем углу

ANCHOR_LOWER

Точка привязки снизу по центру

ANCHOR_RIGHT_LOWER

Точка привязки в правом нижнем углу

ANCHOR_RIGHT

Точка привязки справа по центру

ANCHOR_RIGHT_UPPER

Точка привязки в правом верхнем углу

ANCHOR_UPPER

Точка привязки сверху по центру

ANCHOR_CENTER

Точка привязки строго по центру объекта

 

Спасибо, завтра постараюсь сообразить...

 
prostotrader:

Утро вечера мудреннее... :)

 

Обычно так и есть :)
 
В СД говорят, что все правильно в этом случае

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

fxsaber, 2017.07.18 09:51

Почти детский вопрос: почему так?
void OnStart()
{
  const double Norm = NormalizeDouble(8905 / 1000.0, 3);
  Print(Norm); // 8.904999999999999
  Print(DoubleToString(Norm, 3)); // 8.905
  
  const double Norm2 = (double)DoubleToString(Norm, 3);
  Print(Norm2); // 8.904999999999999
  Print(Norm == Norm2); // true
}

По какой-то причине был уверен, что после нормализации DoubleToString лишен смысла. Ан нет, как показывает скрипт. Почему так?

Похоже, что неправильно работает приведение double -> string.


Пример довольно сложен для понимания, поэтому привел другой

void OnStart()
{
  Print((double)"8.905" == 8.905); // true
  Print(((string)(double)"8.905")); // 8.904999999999999
}

Речь вот о чем

Строковая в double переводится без проблем. Обратно - получаем другой результат.

Т.е. взял строку "8.905", преобразовал ее в double и сразу в string, получив 8.904999999999999. Но первая строка OnStart показывает, что (double)"8.905" == 8.905. Т.е. должно было выводиться 8.905.

Конечно, очевидная ситуация с нулем на конце не должна работать:

Если выполняется условие (double)"8.9050" == 8.9050, то должно выполняться и условие (string)(double)"8.9050" == "8.9050".

Немного исследовав вопрос, пришел к такой ситуации

void OnStart()
{
  const double Num = 8.274;
  const double Norm = NormalizeDouble(Num, 3);
  
  Print(Num);  // 8.273999999999999
  Print(Norm); // 8.274000000000001
}

Прошу объяснить, почему все равно считается, что преобразование double -> string происходит корректно. Последний пример так совсем выносит мозг.

 
fxsaber:

Прошу объяснить, почему все равно считается, что преобразование double -> string происходит корректно. Последний пример так совсем выносит мозг.

Комментарий по последнему примеру

Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num.  Добро пожаловать в мир вещественных чисел.

В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000

Можете проверить по шагам в отладчике

 
fxsaber:
В СД говорят, что все правильно в этом случае

А почему смущает?

Подавляющее большинство десятичных вещественных чисел непредставимы в виде двоичной дроби без остатка. Накладываем на это формат хранения числе double и получаем такие некрасивости.

Вообще тип decimal не помешал бы, удобная штука.

 
Slava:

Комментарий по последнему примеру

Вещественные числа могут считаться одинаковыми, если над ними производили одни и те же преобразования. Даже вроде бы одинаковые преобразования - num*0.5 и num/2.0 приводят к разным результатам. То же самое можно сказать про зеркальные операции. num*=num2, num/=num2. Полученный num не будет равен исходному num.  Добро пожаловать в мир вещественных чисел.

В данном примере в процессе нормализации с вещественным числом были произведены 3 операции - num*=1000, num+=0.5, num/=1000

Можете проверить по шагам в отладчике


Очень конструктивное объяснение, Спасибо!


Но вот такой контрпример выносит несколько мозг

void OnStart()
{
  const double Num = 8.274;
  const double Norm = NormalizeDouble(Num, 3);
   
  Print(Num);  // 8.273999999999999
  Print(Norm); // 8.274000000000001
  
  Print((double)DoubleToString(Num, 3) == Num);     // true - без нормализации все замечательно
  Print((double)DoubleToString(Norm, 3) == Norm);   // false - а после нормализации полный облом!
}

Разве должна так работать нормализация?

 
Комбинатор:

А почему смущает?

После объяснения Славы уже не смущает, но далее возник пример, который заставляет усомниться в правильности работы теперь уже самой NormalizeDouble.

Причина обращения: