Bibliotecas: CDouble & CDoubleVector - página 2

 
Alain Verleyen:
Boa escolha. Entretanto, do ponto de vista comercial, você precisa de 1,70060 ou 1,70061, ambos estão corretos. Portanto, talvez você queira escolher a melhor opção de acordo com sua operação de negociação, em vez de confiar em um esquema de arredondamento matemático.

Nesse cenário, se seu step-size == 0,00001, então você deve obter apenas 1,70061 como resultado, e um valor de 1,70060 é próximo, mas incorreto.

 
nicholishen:

Nesse cenário, se o tamanho da etapa == 0,00001, então você deve obter apenas 1,70061 como resultado, e um valor de 1,70060 é próximo, mas incorreto.

Desculpe-me, mas não entendo seu raciocínio. O que é "step-size"?

 
Alain Verleyen:

Desculpe-me, mas não entendo seu raciocínio. O que é "step-size"?

step-size é o valor do passo para o qual você está arredondando. Por exemplo, lot_step = 0,01 (2 dígitos) ou tick_size = 0,00005...


Neste caso de exemplo, estamos trabalhando com um símbolo de 5 dígitos com um tick-size == 0,00001

 
nicholishen:

step-size é o valor do passo para o qual você está arredondando. Por exemplo, lot_step = 0,01 (2 dígitos), ou tick_size = 0,00005...


Neste caso de exemplo, estamos trabalhando com um símbolo de 5 dígitos com um tick-size == 0,00001

Ok, então step-size é tick-size. Isso ainda não me diz por que , do ponto de vista da negociação, um preço calculado como 1,700605 não poderia ser "arredondado" (seja qual for a forma matemática/codificação) para 1,70060?
 
Alain Verleyen: Ok, então o tamanho da etapa é o tamanho do tick. Isso ainda não me diz por que , do ponto de vista comercial, um preço calculado como 1,700605 não poderia ser "arredondado" (seja qual for a forma matemática/codificação) para 1,70060?

Por favor, entenda que o "ponto de vista comercial" não é relevante aqui. Trata-se de uma questão puramente matemática para a qual @amrali forneceu uma solução.

Não há necessidade de discutir o "ponto de vista comercial" aqui, pois ele está fora do tópico deste tópico e acabará se transformando em outro debate acalorado, terminando com o banimento de alguém novamente. Portanto, tente evitar isso!

 
Fernando Carreiro:

Entenda que um "ponto de vista comercial" não é relevante aqui. Trata-se de uma questão puramente matemática para a qual @amrali forneceu uma solução.

Não há necessidade de discutir o "ponto de vista comercial" aqui, pois ele está fora do tópico deste tópico e acabará se transformando em outro debate acalorado, terminando com alguém sendo banido novamente. Portanto, tente evitar isso!

Estou apenas tentando entender o que @nicholishen disse. Não há motivo para um debate acalorado ou algo do gênero. Este é um fórum sobre negociação, não é?

Por favor, explique-me por que um preço calculado de 1,700605 e um preço real de 1,70060 são "incorretos"? Se estiver faltando alguma coisa, gostaria de entender.

 
Alain Verleyen:

Estou apenas tentando entender o que @nicholishen disse. Não há motivo para um debate acalorado ou qualquer outra coisa. Este é um fórum sobre negociação, não é mesmo?

Por favor, explique-me por que um preço calculado de 1,700605 e um preço real de 1,70060 são "incorretos"? Se estiver faltando alguma coisa, gostaria de entender.

Como Fernando disse, "essa é uma questão puramente matemática" e, no sentido matemático, o resultado esperado é que o 5 seja arredondado para o dígito mais próximo em vez de para baixo. A função MathRound está produzindo resultados inconsistentes e, se o seu objetivo é evitar inconsistências, eu aconselharia usar ND em vez disso, como sabiamente sugerido por @amrali. Para voltarmos ao assunto, a biblioteca CDouble não usa mais a função MathRound em favor de resultados mais consistentes.

 
Alain Verleyen:

Estou apenas tentando entender o que @nicholishen disse. Não há motivo para um debate acalorado ou qualquer outra coisa. Este é um fórum sobre negociação, não é mesmo?

Por favor, explique-me por que um preço calculado de 1,700605 e um preço real de 1,70060 são "incorretos"? Se estiver faltando alguma coisa, gostaria de entender.

Olá , Alain Verleyen, você está correto em relação ao seu ponto. Para um único cálculo, isso pode não fazer muita diferença. Entretanto, se você fizer mais cálculos que envolvam arredondamento em cada etapa, o erro final será ampliado. Considere uma estratégia de martingale, em que cada tamanho de lote calculado é derivado do anterior (que foi enviado ao servidor de negociação como um valor arredondado). A questão que consideramos aqui é chamada de "Propagação de erros". Portanto, acho que seria mais seguro usar NormalizeDouble() para manter os erros intermediários o mais baixo possível.

Em segundo lugar, há também um ponto mais técnico aqui. Ao usar a função MathRound(number * power) / power com números de borda , você obterá o valor arredondado superior algumas vezes ou o valor arredondado inferior outras vezes, dependendo da entrada. Essa inconsistência no arredondamento pode não ser importante do ponto de vista da negociação, como você mencionou em seu comentário, desde que você obtenha um valor final arredondado (para cima ou para baixo), de modo que o servidor de negociação não reclamará. No entanto, conforme afirmou Mark Watkin, essa inconsistência no arredondamento pode introduzir erros difíceis de detectar no código do cliente que usa a biblioteca "CDouble".

A propósito, ao usar outra variante da função acima , como MathRound(number / point) * point com números de borda, você obtém um número arredondado (para cima ou para baixo) ou, o que é mais interessante, não obtém um número arredondado exato! (o resultado difere do valor esperado em 1 Epsilon, mas está OK para funções de negociação)

O script a seguir ajuda a demonstrar esses problemas com mais clareza:

#property strict

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

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
// resultados inconsistentes de MathRound() com números de borda

void OnStart()
{
    // arredondar os preços pela metade para os 5 dígitos decimais mais próximos

    PRINT(MathRound(1.248825 * 100000) / 100000 == 1.24883);    // verdadeiro, esse preço é arredondado para cima (como esperado)
    PRINT(MathRound(1.248835 * 100000) / 100000 == 1.24883);    // verdadeiro, esse preço é arredondado para baixo dessa vez
    PRINT(MathRound(1.248845 * 100000) / 100000 == 1.24885);    // verdadeiro, esse preço é arredondado para cima novamente

    // a segunda variante de MathRound()

    PRINT(MathRound(1.248825 / 0.00001) * 0.00001 == 1.24883);   // verdadeiro, esse preço é arredondado para cima (como esperado)
    PRINT(MathRound(1.248835 / 0.00001) * 0.00001 == 1.24883);   // verdadeiro, esse preço é arredondado para baixo dessa vez
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24885);   // false, esse preço não é arredondado exatamente para cima!!!
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24884);   // false, o mesmo preço não é arredondado exatamente para baixo!!!
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.2488400000000001);   // verdadeiro, mas é adequado para funções de negociação. 
}

Portanto, seria melhor substituir MathRound(number) por NormalizeDouble(number, 0) para evitar resultados inconsistentes quando o arredondamento aritmético (ponto médio) for indicado.

A outra boa alternativa para o arredondamento do ponto médio: use MathRound() + aplique a correção de meio épsilon.

(Isso foi implementado na funçãoMathRoundCorrect(), conforme postado anteriormente).

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

De acordo com este artigo da Wikipedia, há muitos outros modos de arredondamento que servem a diferentes propósitos. Você pode escolher o que melhor se adapta às suas necessidades. Com os melhores cumprimentos.

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...