Errors, bugs, questions - page 1931

 

It's always better in the morning... :)

 
Aleksey Vyazmikin:

In the helpdesk

MT4:

For objects with fixed size: OBJ_BUTTON, OBJ_RECTANGLE_LABEL and OBJ_EDIT properties OBJPROP_XDISTANCE and OBJPROP_YDISTANCE set position of the upper left object point relative to the chart corner (OBJPROP_CORNER), from which X and Y coordinates in pixels will be counted.


MT5:

For objects with fixed size: OBJ_BUTTON, OBJ_RECTANGLE_LABEL, OBJ_EDIT and OBJ_CHART, properties OBJPROP_XDISTANCE and OBJPROP_YDISTANCE set the position of the upper left point of the object relative to the chart corner (OBJPROP_CORNER), from which X and Y coordinates in pixels will be measured.

The matter is that the old version of MT4 using ObjectSet allows placing objects relative to their edges (corners) - for objects in the left part the calculation of pixels is performed from the first symbol, for objects in the right part - from the last symbol, while the new version always performs the calculation from the first symbol, which makes positioning of labels with text difficult, because you don't always know how many text symbols will be. I ask the developers to add a choice of text alignment method!


If anyone knows how to get left and right alignment in MT5, please share the corresponding function!

And don't get angry, but read the help carefully:

For OBJ_LABEL, OBJ_BITMAP_LABEL and OBJ_RECTANGLE_LABEL objects you can set the chart angle, relative to which the object anchor point is positioned. This angle is set via the object property OBJPROP_CORNER, which can have one of the four values of the ENUM_BASE_CORNER enumeration:

Identifier

Description

CORNER_LEFT_UPPER

Coordinates of the anchor point relative to the upper left corner of the chart

CORNER_LEFT_LOWER

Anchor point coordinates are given relative to the lower left corner of the chart

CORNER_RIGHT_LOWER

Anchor point coordinates are set relative to the lower right corner of the chart

CORNER_RIGHT_UPPER

The coordinates of the anchor point are set relative to the upper right corner of the chart

The position of the object's anchor point is specified by the OBJPROP_ANCHOR property and can be one of 9 values of the ENUM_ANCHOR_POINT enumeration:

Identifier

Description

ANCHOR_LEFT_UPPER

Anchor point in the upper left corner

ANCHOR_LEFT

Anchor point to the left in the centre

ANCHOR_LEFT_LOWER

Anchor point at the lower left corner

ANCHOR_LOWER

Anchor point below centre

ANCHOR_RIGHT_LOWER

Anchor point at the lower right corner

ANCHOR_RIGHT

Anchor point to the right in the centre

ANCHOR_RIGHT_UPPER

Anchor point at the upper right corner

ANCHOR_UPPER

Anchor point at the upper centre

ANCHOR_CENTER

Anchor point exactly in the centre of the object

 
Artyom Trishkin:

Shall I move up the list item you're trying to label with the number 4, which isn't there? It becomes zero - and everything is in place.

Of course I've moved everything - maybe I'm stupid...



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:

And don't get angry, read the help carefully:

For OBJ_LABEL, OBJ_BITMAP_LABEL and OBJ_RECTANGLE_LABEL objects you can set the chart angle, relative to which the object anchor point is positioned. This angle is set via the object property OBJPROP_CORNER, which can have one of the four values of ENUM_BASE_CORNER enumeration:

Identifier

Description

CORNER_LEFT_UPPER

Coordinates of the anchor point relative to the upper left corner of the chart

CORNER_LEFT_LOWER

Anchor point coordinates are given relative to the lower left corner of the chart

CORNER_RIGHT_LOWER

Anchor point coordinates are set relative to the lower right corner of the chart

CORNER_RIGHT_UPPER

The coordinates of the anchor point are set relative to the upper right corner of the chart

The position of the object's anchor point is specified by the OBJPROP_ANCHOR property and can be one of 9 values of the ENUM_ANCHOR_POINT enumeration:

Identifier

Description

ANCHOR_LEFT_UPPER

Anchor point in the upper left corner

ANCHOR_LEFT

Anchor point to the left in the centre

ANCHOR_LEFT_LOWER

Anchor point at the lower left corner

ANCHOR_LOWER

Anchor point below centre

ANCHOR_RIGHT_LOWER

Anchor point at the lower right corner

ANCHOR_RIGHT

Anchor point to the right in the centre

ANCHOR_RIGHT_UPPER

Anchor point at the upper right corner

ANCHOR_UPPER

Anchor point at the upper centre

ANCHOR_CENTER

Anchor point directly in the centre of the object

Thank you, I will try to think of something tomorrow...

 
prostotrader:

It's always better in the morning... :)

It usually is :)
 
The SD says it's the right thing to do in this case

Forum on trading, automated trading systems and trading strategy testing

Bugs, bugs, questions

fxsaber, 2017.07.18 09:51

Almost a childish question: why is it like that?
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
}

For some reason I was sure that DoubleToString was meaningless after normalisation. But no, as the script shows. Why is this the case?

It seems that the double -> string conversion doesn't work correctly.


This example is rather complicated to understand, so I gave you another one.

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

Here's what I mean.

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

I.e. took the string "8.905", converted it to double and immediately to string, getting 8.90499999999999999. But the first line of OnStart shows that (double) "8.905" == 8.905. That is, 8.905 should be printed.

Of course, the obvious zero-end situation shouldn't work:

If the condition(double) "8.9050" == 8.9050is met, then the condition(string)(double) "8.9050" == "8.9050"should also be met.

Having investigated the issue a bit, I've come to the following situation

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

Please explain why conversion double -> string is still considered correct. The last example is so completely blowing my mind.

 
fxsaber:

Please explain why the double -> string conversion is still considered to be correct. The last example is so completely mind blowing.

Comment on the last example

Real numbers can be considered identical if they underwent the same conversions. Even seemingly identical conversions - num*0.5 and num/2.0 lead to different results. The same can be said about mirror operations. num*=num2, num/=num2. The resulting num will not equal the original num. Welcome to the world of real numbers.

During the normalization process, 3 operations were performed in this sample with a real number - num*=1000, num+=0.5, num/=1000.

You can check the steps in the debugger

 
fxsaber:
SD says it is correct in this case.

Why is it confusing?

The vast majority of decimal real numbers are not representable as a binary fraction without a remainder. Put a double storage format on top of that and you get such ugly stuff.

Actually, the decimal type would be nice, it's handy.

 
Slava:

Comment on the last example

Real numbers can be considered identical if the same conversions are performed on them. Even seemingly identical conversions - num*0.5 and num/2.0 lead to different results. The same can be said about mirror operations. num*=num2, num/=num2. The resulting num will not equal the original num. Welcome to the world of real numbers.

In this example, 3 operations - num*=1000, num+=0.5, num/=1000 - were performed on a real number during normalization.

You can check the steps in the debugger


Very constructive explanation, thanks!


But this counterexample blows my mind.

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 - а после нормализации полный облом!
}

Is this how normalization is supposed to work?

 
Комбинатор:

Why is it confusing?

After Slava's explanation it is not confusing, but then there is an example that makes us question the correctness of NormalizeDouble itself.