程序库: CDouble & CDoubleVector - 页 2

 
Alain Verleyen:
接得好。不过,从交易的角度来看,您需要的是 1.70060 或 1.70061,它们都是正确的。因此,您可能需要根据自己的交易操作 选择一个最佳方案,而不是依赖于数学四舍五入方案。

在这种情况下,如果您的步长 == 0.00001,那么您只能得到 1.70061 的结果,而 1.70060 的值虽然接近,但并不正确。

 
nicholishen:

在这种情况下,如果你的步长 == 0.00001,那么你只能得到 1.70061 的结果,而 1.70060 的值是接近但不正确的。

对不起,我不明白你的推理。什么是 "步长"?

 
Alain Verleyen:

对不起,我不明白你的理由。什么是 "步长"?

例如,lot_step = 0.01(2 位数),或者 tick_size = 0.00005......。


在本例中,我们使用的是 tick-size == 0.00001 的 5 位数符号

 
nicholishen:

例如 lot_step = 0.01(2 位数),或 tick_size = 0.00005...


在本例中,我们使用的是 tick-size == 0.00001 的 5 位数符号

好吧,步长就是刻度大小。但我还是不明白,从交易的角度来看,为什么像 1.700605 这样的计算价格不能 "四舍五入"(不管用什么数学/编码方法)为 1.70060?
 
Alain Verleyen: 好吧,步长就是刻度。但我还是不明白,从交易的角度来看,为什么像 1.700605 这样的计算价格不能 "四舍五入"(不管用什么数学/编码方法)为 1.70060?

请理解,"交易观点 "在这里无关紧要。这纯粹是一个数学问题, @amrali 已经提供了解决方案。

没有必要在这里讨论 "交易观点",因为这与本主题 无关 ,最终会升级为另一场激烈的辩论,导致有人再次被禁言。因此,请尽量避免!

 
Fernando Carreiro:

请理解,"交易观点 "与此无关。这纯粹是一个数学问题, @amrali 已经提供了解决方案。

没有必要在这里讨论 "交易观点",因为这与本主题 无关 ,最终会升级为另一场激烈的辩论,导致有人再次被禁言。因此,请尽量避免!

我只是想理解@nicholishen 所说的话。没有理由进行激烈的辩论或其他什么。这是一个关于交易的论坛,不是吗?

请给我解释一下,为什么 1.700605 的计算价格和 1.70060 的实际价格是 "不正确的"?如果我遗漏了什么,我很想知道。

 
Alain Verleyen:

我只是想理解@nicholishen 所说的话。我们没有理由进行激烈的辩论。这是一个关于交易的论坛,不是吗?

请给我解释一下,为什么 1.700605 的计算价格和 1.70060 的实际价格是 "不正确的"?如果我遗漏了什么,我很想知道。

正如费尔南多所说,"这纯粹是一个数学问题",从数学意义上讲,预期结果是将 5 向上舍入到最接近的数位,而不是向下舍入。MathRound 函数产生了不一致的结果,如果你想避免不一致的结果,我建议使用 ND 代替,@amrali 对此提出了明智的建议。为了让大家回到正题,CDouble 库不再使用 MathRound 函数,以获得更一致的结果。

 
Alain Verleyen:

我只是想理解@nicholishen 所说的话。没有理由进行激烈的辩论或其他什么。这是一个关于交易的论坛,不是吗?

请给我解释一下,为什么 1.700605 的计算价格和 1.70060 的实际价格是 "不正确的"?如果我遗漏了什么,我很想知道。

您好 Alain Verleyen 您的观点是正确的。就单次计算而言,可能不会有太大区别。但是,当你进行更多的计算,每一步都涉及四舍五入时,最终的误差就会被放大。考虑一下鞅策略,其中每次计算的手数都来自于前一次计算的手数(前一次计算的手数以四舍五入值的形式发送到交易服务器)。我们在这里考虑的问题叫做 "误差传播"。因此,我认为使用 NormalizeDouble()更安全,以尽可能减少中间误差。

其次,这里还有一个技术性更强的问题。使用函数 MathRound(number * power) / power 时, 如果使用 边沿数字,有时会得到四舍五入后的上限值,有时会得到四舍五入后的下限值, 具体取决于输入 。从交易角度来看,四舍五入的这种不一致性可能并不重要,正如您在评论中提到的,只要您得到的是最终的四舍五入值(向上或向下),交易服务器就不会抱怨。不过,正如 马克-沃特金(Mark Watkin 所说 四舍五入的这种不一致性可能会在使用 "CDouble "库的客户端代码中引入难以发现的错误。

顺便说一下,使用上述函数的另一个变体, MathRound(number / point) * point 边沿数字, 您会 得到一个四舍五入的数字(向上或向下),或者更有趣的是,您不会得到一个精确的四舍五入数字!(结果与预期值相差 1 Epsilon,但对于交易函数来说没有问题)。

下面的脚本可以更清楚地说明这些问题:

#property strict

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

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
// MathRound() 与边缘数的结果不一致

void OnStart()
{
    // 将价格四舍五入到最接近的小数点后 5 位数

    PRINT(MathRound(1.248825 * 100000) / 100000 == 1.24883);    // 为真,该价格会四舍五入(如预期)
    PRINT(MathRound(1.248835 * 100000) / 100000 == 1.24883);    // 为真,这次价格会向下舍入
    PRINT(MathRound(1.248845 * 100000) / 100000 == 1.24885);    // 为真,该价格再次四舍五入

    // MathRound() 的第二个变体

    PRINT(MathRound(1.248825 / 0.00001) * 0.00001 == 1.24883);   // 为真,价格四舍五入(符合预期)
    PRINT(MathRound(1.248835 / 0.00001) * 0.00001 == 1.24883);   // 为真,这次价格向下舍入
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24885);   // false, that price is not rounded up exactly!
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.24884);   //假,相同的价格不会四舍五入到整数
    PRINT(MathRound(1.248845 / 0.00001) * 0.00001 == 1.2488400000000001);   // 属实,但对于交易函数来说没有问题。 
}

因此, 最好 NormalizeDouble(number,0) 代替 MathRound(number), 以避免算术(中点)四舍五入时出现不一致的结果

中点四舍五入的另一个好办法是:使用 MathRound() + 应用半epsilon 修正。

(这已在 之前发布的MathRoundCorrect() 函数 中实现 )。

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;
}

根据维基百科上的这篇文章,还有许多其他四舍五入模式,用途各不相同。您可以根据需要自由选择。致以最诚挚的问候。

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