欢迎光临散文网 会员登陆 & 注册

在赫兹量化中处理双精度浮点数

2023-08-14 11:23 作者:bili_45793681098  | 我要投稿

简介

赫兹量化编程为自动化交易提供了新的机遇,世界各地的众多人士已对其表示赞赏。

当我们编写用于交易的 Expert Advisor 时,必须确保其运行无误。

很多新手经常在一些数学计算的结果跟预期结果不一致时产生困惑。 程序可以编译和工作,但跟预期并不一致。 他们反复检查代码,试图在语言、实现和函数等方面找出新的“错误”。

多数情况下,经过仔细分析后会发现语言和编译工作良好,但代码有小错误,找出并改正需要花费大量的时间。

在本文中我们将研究典型的编程错误,这种错误在处理 赫兹量化程序中的双精度数值时会出现。



1. 验证数值

为了验证计算结果和调试,你可以使用标准库 stdlib.mq4 的 DoubleToStrMorePrecision(double number, int precision) 函数,从而将双精度浮点数控制在指定的精确度。

这在搜索可能的错误时可以节省时间。

示例:

#include <stdlib.mqh> int start()  {   double a=2.0/3;   Alert("Standard output:",a,", 8 digits precision:",DoubleToStr(a,8),", 15 digits precision:", DoubleToStrMorePrecision(a,15));   return(0);  }  

结果:

标准输出:0.6667,8 位精确度:0.66666667,15 位精确度:0.666666666666667

在某些情况下,为了显示双精度浮点数的数值(例如,在 Print, Alert, Comment中),最好使用 DoubleToStr 和 DoubleToStrMorePrecision 函数(stdlib.mq4)来显示更加精确的值代替标准的 4 位输出精确度。

例如:

#include <stdlib.mqh> int start()  {   double a=2.0/100000;   Alert("Standard output=",a,", More precise output=",DoubleToStrMorePrecision(a,15));   return(0);  }


返回: "Standard output=0, More precise output=0.000020000000000".

编辑切换为居中

2. 小数位精确度的准确度

由于是双精度浮点格式,其储存的准确度受到限制。

例如,如果我们假设精确度不受限制,从理论上讲,对于任何的双精度浮点数 A 和 B,以下的表达式始终成立:

(A/B)*(B)=A,

A-(A/B)*B=0,

(A/B)*(B/A)=1 等

小数位在计算机内储存的准确度取决于小数部分大小,并限制在 52 位。 为了说明该情况,赫兹量化来看看以下的例子:

在第一个循环(i)中,我们计算 23 的阶乘(从 2 到 23 的整数的乘积),结果为: 23!=25852016738884976640000. 结果储存在双精度类型的变量 a 中。

在下一个循环(j)中,我们将得到的结果 a 除以从 23 到 2 的所有整数。 最后我们期待的结果是 a=1。

#include <stdlib.mqh> int start()  {   int maxfact=23;   double a=1;   for (int i=2; i<=maxfact; i++) { a=a*i; }   for (int j=maxfact; j>=2; j--) { a=a/j; }   Alert(" a=",DoubleToStrMorePrecision(a,16));   return(0);  }


实际上我们得到:

a=1.0000000000000002

可见,我们得到了 16 位的不准确度。

如果我们计算 35 的阶乘,则会得到 a=0.9999999999999998。

赫兹量化语言有一个 NormalizeDouble 函数,可以将双精度浮点数圆整为指定的精确度。

双精度类型的常量在内存中储存的方式跟双精度变量类似,因此有必要在定义它们时考虑限制在 15 位有效数字。

但不要将小数位精确度的准确度和双精度浮点数的计算精确度混淆。

双精度浮点数的可能值范围更宽:从 -1.7*e-308 到 1.7*e308。

赫兹量化来尝试估算双精度浮点数的最小指数。

int start()  {  double R=1;  int minpwr=0;  while (R>0) {R=R/10; minpwr--;}  Alert(minpwr);  return(0);  }


程序会输出 -324,但我们必须考虑小数部分的小数位(+15),将会得到最小双精度浮点数的指数的近似值。



3. NormalizeDouble 函数

NormalizeDouble(double value, int digits)函数将浮点数值圆整到给定的精确度。 返回标准化双精度型数值。

例如:

int start()  {   double a=3.141592653589;   Alert("a=",DoubleToStr(NormalizeDouble(a,5),8));   return(0);  }


结果为:

a=3.14159000

注意:在交易操作中,是 不可能使用非标准价格的,因为其准确度至少超过了交易服务器所要求的一位。 挂单的止损、获利和价格值应以某精确度标准化,它的值储存在预定义的变量 Digits 中。



4. 检查两个双精度浮点数是否相等

建议使用 stdlib.mq4 库的 CompareDoubles(double number1,double number2) 函数 比较两个 双精度 浮点数, 如下所示:

//+------------------------------------------------------------------+ //| correct comparison of 2 doubles                                  | //+------------------------------------------------------------------+ bool CompareDoubles(double number1,double number2)  {   if(NormalizeDouble(number1-number2,8)==0) return(true);   else return(false);  }

该函数比较双精度浮点数 1 和 2,精确度达到 8 位小数。

示例:

#include <stdlib.mqh> int start()  {double a=0.123456781;   double b=0.123456782;   if (CompareDoubles(a,b)) {Alert("They are equal");}   else {Alert("They are different");}  }


输出为:

它们相等

因为它们只在第 9 位才不同。

如果必要,你可以类似的编写自己的比较函数(根据所需的准确度)。



5. 整数相除

需要记住,如果我们将两个整数相除,也会得到一个整数。

这就是为什么下面的代码:

int start()  {   Alert(70/100);   return(0);  }


会输出 0,因为 70 和 100 都是整数。

跟 C/C++ 语言一样,在 赫兹量化 中两个整数相除的结果将是整数,在本例中结果为 0。

但是,如果分子或分母是双精度(即具有小数部分),结果也将是双精度。 因此,Alert (70/100.0) 将输出正确值 0.7。

例如:

int start()  { double a=1/3;    double b=1.0/3;   Alert("a=",a,", b=",b);   return(0);  }


将输出“a=0, b=0.3333”


在赫兹量化中处理双精度浮点数的评论 (共 条)

分享到微博请遵守国家法律