Librerías: CDouble & CDoubleVector - página 2

 
Alain Verleyen:
Buena captura. Sin embargo, desde un punto de vista comercial, necesita 1,70060 o 1,70061, ambos son correctos. Así que tal vez usted querrá elegir el mejor de acuerdo a su operación comercial, en lugar de confiar en un esquema de redondeo matemático.

En este caso, si su tamaño de paso == 0,00001, sólo debería obtener 1,70061 como resultado, y un valor de 1,70060 está cerca pero es incorrecto.

 
nicholishen:

En este caso, si el tamaño del paso == 0,00001, sólo debería obtener 1,70061 como resultado, y un valor de 1,70060 es aproximado pero incorrecto.

Lo siento, pero no entiendo su razonamiento. ¿Qué es "step-size"?

 
Alain Verleyen:

Lo siento, pero no entiendo su razonamiento. ¿Qué es "step-size"?

step-size es el valor del paso al que se redondea. ej. lot_step = 0.01 (2 dígitos), o tick_size = 0.00005...


En este caso de ejemplo, estamos trabajando con un símbolo de 5 dígitos con un tick-size == 0.00001

 
nicholishen:

step-size es el valor del paso al que se redondea. p.ej. lot_step = 0.01 (2 dígitos), o tick_size = 0.00005...


En este caso de ejemplo, estamos trabajando con un símbolo de 5 dígitos con un tick-size == 0.00001

De acuerdo, el tamaño del paso es el tamaño del tick. Sin embargo, esto no me explica por qué , desde el punto de vista de la negociación, un precio calculado como 1,700605 no puede "redondearse" (sea cual sea la forma matemática o de codificación) a 1,70060.
 
Alain Verleyen: De acuerdo, el tamaño del paso es el tamaño del tick. Eso sigue sin explicarme por qué , desde un punto de vista comercial, un precio calculado como 1,700605 no puede "redondearse" (sea cual sea la forma matemática o de codificación) a 1,70060.

Por favor, comprenda que un "punto de vista comercial" no es relevante aquí. Se trata de una cuestión puramente matemática para la que @amrali ha proporcionado una solución.

No hay necesidad de discutir el "punto de vista comercial" aquí, ya que está fuera de tema para este hilo y, en última instancia escalar en otro acalorado debate que termina en alguien que está prohibido de nuevo. Así que, por favor, ¡intenta evitarlo!

 
Fernando Carreiro:

Por favor, comprenda que un "punto de vista comercial" no es relevante aquí. Se trata de una cuestión puramente matemática para la que @amrali ha proporcionado una solución.

No hay necesidad de discutir el "punto de vista comercial" aquí, ya que está fuera del tema de este hilo y, en última instancia, se convertirá en otro acalorado debate que terminará con alguien expulsado de nuevo. Así que, por favor, ¡intentad evitarlo!

Sólo estoy tratando de entender lo que dijo @nicholishen. No hay razón para un debate acalorado o lo que sea. Este es un foro sobre trading, ¿no?

Por favor, explícame por qué de un precio calculado de 1,700605, un precio real de 1,70060 es "incorrecto". Si me estoy perdiendo algo me gustaría entenderlo.

 
Alain Verleyen:

Sólo intento entender lo que ha dicho @nicholishen. No hay razón para un debate acalorado o lo que sea. Este es un foro sobre el comercio, ¿no?

Por favor, explícame por qué a partir de un precio calculado de 1,700605, un precio real de 1,70060 es "incorrecto". Si me estoy perdiendo algo me gustaría entenderlo.

Como ha dicho Fernando, "se trata de una cuestión puramente matemática", y en el sentido matemático el resultado esperado es que el 5 se redondee hacia arriba al dígito más cercano en lugar de hacia abajo. La función MathRound está produciendo resultados inconsistentes y si quieres evitar inconsistencias te aconsejo que uses ND en su lugar, como sabiamente sugiere @amrali. Para volver al tema, la librería CDouble ya no utiliza la función MathRound en favor de resultados más consistentes.

 
Alain Verleyen:

Sólo intento entender lo que ha dicho @nicholishen. No hay razón para un debate acalorado o lo que sea. Este es un foro sobre el comercio, ¿no?

Por favor, explícame por qué a partir de un precio calculado de 1,700605, un precio real de 1,70060 es "incorrecto". Si me estoy perdiendo algo me gustaría entenderlo.

Hola Alain Verleyen, tienes razón en lo que dices. Para un solo cálculo, puede que no haya mucha diferencia. Sin embargo, a medida que realice más cálculos que impliquen el redondeo en cada paso, el error final se magnificará. Consideremos una estrategia de martingala, en la que cada tamaño de lote calculado se deriva del anterior (que se envió al servidor de negociación como un valor redondeado). El problema que consideramos aquí se llama "Propagación de errores". Por lo tanto, creo que sería más seguro utilizar NormalizeDouble() con el fin de mantener los errores intermedios lo más bajo posible.

En segundo lugar, también existe un punto más técnico aquí. Usando la función MathRound(number * power) / power con edge numbers, obtendrá el valor redondeado superior algunas veces, o el valor redondeado inferior, las otras veces dependiendo de la entrada. Esta inconsistencia en el redondeo puede no importar desde un punto de vista comercial, como usted mencionó en su comentario, siempre y cuando se obtiene un valor redondeado final (ya sea hacia arriba o hacia abajo), por lo que el servidor de comercio no se quejará. Sin embargo, como afirma Mark Watkin, tal inconsistencia en el redondeo puede introducir errores difíciles de detectar en el código cliente que utiliza la librería "CDouble".

Por cierto, utilizando otra variante de la función anterior como MathRound(number / point) * point con números de arista, se obtiene un número redondeado (hacia arriba o hacia abajo), o lo que es más interesante ¡no se obtiene un número redondeado exacto! (el resultado difiere del valor esperado en 1 Epsilon, pero está bien para funciones comerciales)

El siguiente script ayuda a demostrar estos problemas con mayor claridad:

#property strict

#define  PRINT(A) Print(#A + " = ", (A))

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
// resultados inconsistentes de MathRound() con números de borde

void OnStart()
{
    // redondea los precios a la mitad, a los 5 dígitos decimales más próximos

    PRINT(MathRound(1.248825 * 100000) / 100000 == 1.24883);    // verdadero, ese precio se redondea (como era de esperar)
    PRINT(MathRound(1.248835 * 100000) / 100000 == 1.24883);    // cierto, que el precio se redondea hacia abajo esta vez
    PRINT(MathRound(1.248845 * 100000) / 100000 == 1.24885);    // verdadero, ese precio se redondea de nuevo hacia arriba

    // la segunda variante de MathRound()

    PRINT(MathRound(1.248825 / 0.00001) * 0.00001 == 1.24883);   // verdadero, que el precio se redondea (como era de esperar)
    PRINT(MathRound(1.248835 / 0.00001) * 0.00001 == 1.24883);   // cierto, que el precio se redondea hacia abajo esta vez
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24885);   // falso, ¡¡ese precio no se redondea exactamente!!
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24884);   // falso, ¡¡¡el mismo precio no se redondea hacia abajo exactamente!!!
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.2488400000000001);   // cierto, pero está bien para las funciones comerciales. 
}

Por lo tanto, sería mejor reemplazar MathRound(number) con NormalizeDouble(number, 0) para evitar resultados inconsistentes cuando se indica el redondeo aritmético (punto medio).

La otra buena alternativa para el redondeo de punto medio: utilizar MathRound() + aplicar la corrección de semiepsilon.

(Esto se implementó en la funciónMathRoundCorrect() como se publicó antes).

double MathRoundCorrect(double num, int precision) {
        double c = 0.5 * DBL_EPSILON * num;
// double p = MathPow(10, precisión); //lento
        double p = 1; while (precision--> 0) p *= 10;
        if (num < 0)
                p *= -1;
        return MathRound((num + c) * p) / p;
}

De acuerdo con este artículo de wikipedia, hay muchos otros modos de redondeo que sirven para diferentes propósitos. Usted es libre de elegir el que se adapte a sus necesidades. Saludos cordiales.

https://en.wikipedia.org/wiki/Rounding

Rounding - Wikipedia
Rounding - Wikipedia
  • en.wikipedia.org
Graphs of the result, y, of rounding x using different methods. For clarity, the graphs are shown displaced from integer y values. In the SVG file, hover over a method to highlight it and, in SMIL-enabled browsers, click to select or deselect it. Rounding a numerical value means replacing it by another value that is approximately equal but has...