Errores, fallos, preguntas - página 1931

 

Siempre es mejor por la mañana... :)

 
Aleksey Vyazmikin:

En el servicio de asistencia

MT4:

Para objetos con tamaño fijo: las propiedades OBJ_BUTTON, OBJ_RECTANGLE_LABEL y OBJ_EDIT OBJPROP_XDISTANCE y OBJPROP_YDISTANCE establecen la posición del punto superior izquierdo del objeto respecto a la esquina del gráfico (OBJPROP_CORNER), a partir de la cual se contarán las coordenadas X e Y en píxeles.


MT5:

Para los objetos con tamaño fijo: OBJ_BUTTON, OBJ_RECTANGLE_LABEL, OBJ_EDIT y OBJ_CHART, las propiedades OBJPROP_XDISTANCE y OBJPROP_YDISTANCE establecen la posición del punto superior izquierdo del objeto con respecto a la esquina del gráfico (OBJPROP_CORNER), desde la cual se medirán las coordenadas X e Y en píxeles.

La cuestión es que la versión antigua de MT4 que utiliza ObjectSet permite colocar los objetos en relación con sus bordes (esquinas) - para los objetos de la parte izquierda el cálculo de los píxeles se realiza a partir del primer símbolo, para los objetos de la parte derecha - a partir del último símbolo, mientras que la nueva versión siempre realiza el cálculo a partir del primer símbolo, lo que dificulta el posicionamiento de las etiquetas con texto, porque no siempre se sabe cuántos símbolos de texto habrá. Pido a los desarrolladores que añadan la posibilidad de elegir el método de alineación del texto.


¡Si alguien sabe cómo obtener la alineación izquierda y derecha en MT5, por favor comparta la función correspondiente!

Y no te enfades, pero lee la ayuda con atención:

Para los objetos OBJ_LABEL, OBJ_BITMAP_LABEL y OBJ_RECTANGLE_LABEL se puede establecer el ángulo del gráfico, en relación con el cual se posiciona el punto de anclaje del objeto. Este ángulo se establece mediante la propiedad del objeto OBJPROP_CORNER, que puede tener uno de los cuatro valores de la enumeración ENUM_BASE_CORNER:

Identificador

Descripción

ESQUINA_IZQUIERDA_SUPERIOR

Coordenadas del punto de anclaje relativas a la esquina superior izquierda del gráfico

ESQUINA_IZQUIERDA_INFERIOR

Las coordenadas del punto de anclaje se dan en relación con la esquina inferior izquierda del gráfico

ESQUINA_DERECHA_INFERIOR

Las coordenadas del punto de anclaje se fijan en relación con la esquina inferior derecha del gráfico

ESQUINA_DERECHA_SUPERIOR

Las coordenadas del punto de anclaje se establecen en relación con la esquina superior derecha del gráfico

La posición del punto de anclaje del objeto se especifica mediante la propiedad OBJPROP_ANCHOR y puede ser uno de los 9 valores de la enumeración ENUM_ANCHOR_POINT:

Identificador

Descripción

ANCHOR_LEFT_UPPER

Punto de anclaje en la esquina superior izquierda

ANCHOR_LEFT

Punto de anclaje a la izquierda en el centro

ANCHOR_LEFT_LOWER

Punto de anclaje en la esquina inferior izquierda

ANCHOR_INFERIOR

Punto de anclaje por debajo del centro

ANCHOR_RIGHT_LOWER

Punto de anclaje en la esquina inferior derecha

ANCHOR_DERECHO

Punto de anclaje a la derecha en el centro

ANCHOR_RIGHT_UPPER

Punto de anclaje en la esquina superior derecha

ANCHOR_UPPER

Punto de anclaje en el centro superior

CENTRO DE ANCLAJE

Punto de anclaje exactamente en el centro del objeto

 
Artyom Trishkin:

¿Avanzo el elemento de la lista que intentas etiquetar con el número 4, que no está ahí? Se convierte en cero - y todo está en su lugar.

Por supuesto que he movido todo - tal vez soy estúpido...



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:

Y no te enfades, lee la ayuda con atención:

Para los objetos OBJ_LABEL, OBJ_BITMAP_LABEL y OBJ_RECTANGLE_LABEL se puede establecer el ángulo del gráfico, en relación con el cual se posiciona el punto de anclaje del objeto. Este ángulo se establece mediante la propiedad del objeto OBJPROP_CORNER, que puede tener uno de los cuatro valores de la enumeración ENUM_BASE_CORNER:

Identificador

Descripción

ESQUINA_IZQUIERDA_SUPERIOR

Coordenadas del punto de anclaje relativas a la esquina superior izquierda del gráfico

ESQUINA_IZQUIERDA_INFERIOR

Las coordenadas del punto de anclaje se dan en relación con la esquina inferior izquierda del gráfico

ESQUINA_DERECHA_INFERIOR

Las coordenadas del punto de anclaje se fijan en relación con la esquina inferior derecha del gráfico

ESQUINA_DERECHA_SUPERIOR

Las coordenadas del punto de anclaje se establecen en relación con la esquina superior derecha del gráfico

La posición del punto de anclaje del objeto se especifica mediante la propiedad OBJPROP_ANCHOR y puede ser uno de los 9 valores de la enumeración ENUM_ANCHOR_POINT:

Identificador

Descripción

ANCHOR_LEFT_UPPER

Punto de anclaje en la esquina superior izquierda

ANCHOR_LEFT

Punto de anclaje a la izquierda en el centro

ANCHOR_LEFT_LOWER

Punto de anclaje en la esquina inferior izquierda

ANCHOR_INFERIOR

Punto de anclaje por debajo del centro

ANCHOR_RIGHT_LOWER

Punto de anclaje en la esquina inferior derecha

ANCHOR_DERECHO

Punto de anclaje a la derecha en el centro

ANCHOR_RIGHT_UPPER

Punto de anclaje en la esquina superior derecha

ANCHOR_UPPER

Punto de anclaje en el centro superior

CENTRO DE ANCLAJE

Punto de anclaje directamente en el centro del objeto

Gracias, intentaré pensar en algo mañana...

 
prostotrader:

Siempre es mejor por la mañana... :)

Suele ser así :)
 
La SD dice que es lo correcto en este caso

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Bichos, errores, preguntas

fxsaber, 2017.07.18 09:51

Una pregunta casi infantil: ¿por qué es así?
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
}

Por alguna razón estaba seguro de que DoubleToString no tenía sentido después de la normalización. Pero no, como muestra el guión. ¿Por qué es así?

Parece que la conversión doble -> cadena no funciona correctamente.


Este ejemplo es bastante complicado de entender, así que te doy otro.

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

Esto es lo que quiero decir.

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

Es decir, tomó la cadena "8,905", la convirtió en doble e inmediatamente en cadena, obteniendo 8,904999999999999. Pero la primera línea de OnStart muestra que (doble) "8,905" == 8,905. Es decir, debería imprimirse 8,905.

Por supuesto, la situación obvia del extremo cero no debería funcionar:

Si se cumple la condición(doble)"8,9050" == 8,9050, entonces también debería cumplirse la condición(cadena)(doble) "8,9050" == "8,9050".

Tras investigar un poco el asunto, he llegado a la siguiente situación

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

Por favor, explique por qué la conversión doble -> cadena se sigue considerando correcta. El último ejemplo me deja completamente boquiabierto.

 
fxsaber:

Por favor, explique por qué la conversión doble -> cadena se sigue considerando correcta. El último ejemplo es completamente alucinante.

Comentario sobre el último ejemplo

Los números reales pueden considerarse idénticos si han sufrido las mismas conversiones. Incluso conversiones aparentemente idénticas -num*0,5 y num/2,0- conducen a resultados diferentes. Lo mismo puede decirse de las operaciones espejo. num*=num2, num/=num2. El número resultante no será igual al número original. Bienvenido al mundo de los números reales.

Durante el proceso de normalización, en esta muestra se realizaron 3 operaciones con un número real - num*=1000, num+=0,5, num/=1000.

Puedes comprobar los pasos en el depurador

 
fxsaber:
SD dice que es correcto en este caso.

¿Por qué es confuso?

La gran mayoría de los números reales decimales no son representables como fracción binaria sin resto. Si encima le pones un formato de almacenamiento doble, te quedas con lo más feo.

En realidad, el tipo decimal estaría bien, es práctico.

 
Slava:

Comentario sobre el último ejemplo

Los números reales pueden considerarse idénticos si se realizan sobre ellos las mismas conversiones. Incluso conversiones aparentemente idénticas -num*0,5 y num/2,0- conducen a resultados diferentes. Lo mismo puede decirse de las operaciones espejo. num*=num2, num/=num2. El número resultante no será igual al número original. Bienvenido al mundo de los números reales.

En este ejemplo, se realizaron 3 operaciones - num*=1000, num+=0,5, num/=1000 - sobre un número real durante la normalización.

Puedes comprobar los pasos en el depurador


Una explicación muy constructiva, ¡gracias!


Pero este contraejemplo me deja boquiabierto.

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

¿Es así como se supone que funciona la normalización?

 
Комбинатор:

¿Por qué es confuso?

Después de la explicación de Slava no es confuso, pero luego hay un ejemplo que nos hace cuestionar la corrección del propio NormalizeDouble.

Razón de la queja: