移动平均线(和任何其他指标)和误差的比较

 

大家好!

我正在写一个基于SMA交叉的EA(或者说我认为我已经写了,因为它看起来很简单)。但是...我遇到了一个问题。专家顾问的工作原理如下:当一个新的条形图出现时,它分析最后两个条形图的均线,不计入我刚刚出现的最后一个条形图(倒数第二条和前一条)。我比较数值似乎是正确的,如这里 所述。唯一的例外是,在调用iMA时,最后一个参数(以条为单位的偏移)分别为1和2。大约是这样的(如果通过类比引证来重写代码)。

// берем два соседних значения Быстрой МА
double fast0=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double fast1=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// берем два значения Медленной МА
double slow0=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1);
double slow1=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>slow1) Print("Пересечение ВНИЗ");

专家顾问在有交叉信号的情况下以原始形式运作,其原则是关闭前一个交易 - 开启一个新的交易。当然,如果所有的交叉点都被检测到,那么交易将总是一个接一个地被执行(卖出-买入-卖出-买入-...)。也就是说,专家顾问在任何时候都只有一个开放的交易(好吧,除了进入第一个交易前的那一刻)。所以问题的关键在这里......在17.02.2015的01:24,我发现了一个有趣的情况,在策略测试器中,分钟时间框架和均线周期5和34为关闭。具有这些特征的运动在收盘时直接整齐地交叉。这里是图片。

17.02.2015 01:24

为了调试的目的,我输出了这些信息。与给出的代码相比,日志中的对应情况如下。

SMAFastCurrent =fast0

SMASlowCurrent =slow0

SMAFastPrevious =fast1

SMASlowPrevious=slow1 并且

SMACurDifference = SMAFastCurrent - SMASlowCurrent

SMAPrevDifference = SMAFastPrevious - SMASlowPreviousc(即分别为fast0、slow0fast1、slow1 的差值)。

因此,当这些差异改变符号时,意味着这是一个摩拜单车的信号。但在这个特殊的例子中,对多或少的检查不起作用。这些差异的数值会显示在日志中。红色的矩形显示了问题后的下一个条形图上的差异值(在1:25),橙色 - 在下一个条形图上(在1:26)。很明显,前一栏的SMACurDifference值和当前栏的SMAPrevDifference值必须相等(当前栏成为前一栏,新栏取代它)。因此,由于Mooving交叉点发生在1:24的问题栏收盘时,在下一个栏(1:25)SMAFastCurrent和SMASlowCurrent的值相等(大约)。调试器打印出来的数据一般等于5位以内(SMAFastCurrent = 1.13371 SMASlowCurrent = 1.13371见图)。它们的差异是无限小的,但不是0(SMACurDifference = 2.220446049250313e-016)。在下一个条形图上,它们在相同的精确值上的差异正好为零(比较红色的SMACurDifference和橙色矩形的SMAPrevDifference)。实际上,不清楚如何切断这些误差,如果即使是看似相同的数值也会产生不同的差异。因此,有两个问题。

1.为什么在相邻两根柱子交替出现的时候,仅仅计算同一羽翼的差异,就能得到不同的结果?

2.我正在考虑引入一些ε,并与之进行比较,而不是与零进行比较。但它通常是为了将一个无限小数与0进行比较。当我需要确定这个无限小数的符号变化时,情况又如何呢?

当然,我可以分析三个相邻的柱子,但理论上仍有可能在它们关闭的价格上,机动性将以无限小的距离相互接触。我意识到这种情况很少发生(特别是如果我们采取更大的时间框架),但它仍然可能发生。而且应该以某种方式抓到它,在这种情况下也应该检测到Mouveins的穿越。

提前感谢任何帮助

Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
  • www.mql5.com
Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
 

试着进行标准化和比较。

MQL4参考手册(MQL5也一样)说,在"实数类型 (双数、浮点数)" 上打开。

"......你不能比较两个实数是否相等。在大多数情况下,两个看似相同的数字可能因为小数点后15位的差异而变成不相等。为了正确地比较两个实数,你必须将这些数字的归一化差值与一个零值进行比较...."

"......强烈建议不要将两个实数相互比较,以确定是否相等,因为这样的比较是不正确的。

..............


然而,如果有必要比较两个实数是否相等,可以用两种不同的方式进行。第一种方法是将两个数字之间的差异与一些定义了比较准确性的小数值进行比较。

.............


第二种方法是将两个实数的归一化差值与一个零值进行比较。将归一化数字的差值与零进行比较是没有用的,因为对归一化数字的任何数学运算都会产生非归一化的结果。

...."

 
rosomah:

试着进行标准化和比较。

MQL4参考手册(MQL5也一样)说,在"实数类型 (双数、浮点数)" 上打开。

"......你不能比较两个实数是否相等。在大多数情况下,两个看似相同的数字可能因为小数点后15位的差异而变成不相等。为了正确地比较两个实数,你必须将这些数字的归一化差值与一个零值进行比较...."

"断然不建议将两个实数相互比较,以求得相等,因为这种比较是无效的。

..............


然而,如果有必要比较两个实数是否相等,可以用两种不同的方式进行。第一种方法是将两个数字之间的差异与一些定义了比较准确性的小数值进行比较。

.............


第二种方法是将两个实数的归一化差值与零进行比较。将归一化数字的差值与零进行比较是没有用的,因为对归一化数字的任何数学运算都会产生非归一化的结果。

...."

我很清楚,比较实数是否平等是不可能的。在我引用的代码中没有平等的比较。而且也没有必要这样做。我们在这里遇到的情况是,我们需要捕捉一个很可能达到0的无限小的符号的变化。在这种情况下,简单地把所有东西都比作多或等于0也是危险的。而正常化在这里可能更加危险......MA的初始值被归一化为一个未知数(时间范围越小,MA的值越小)。如果对小数点后的常数进行归一化处理,可能会导致MA的所有值都正好为0。说实话,我不太明白两个MA值的差别会是什么......

 

gammaray:

我很清楚,在平等的基础上比较真实的数字是不可能的。在我引用的代码中,没有平等的比较。而且也没有必要这样做。我们在这里遇到的情况是,我们需要抓住一个无限小的符号的变化,这很可能会打到0。在这种情况下,简单地把所有东西都比作多或等于0也是危险的。而正常化在这里可能更加危险......MA的初始值被归一化为一个未知数(时间范围越小,MA的值越小)。如果对小数点后的常数进行归一化处理,可能会导致MA的所有值都正好为0。说实话,我不太明白两个MA值之间会有什么区别......

为什么正常化会更危险?

所以。

...

如果你确实需要比较两个实数是否相等,你可以用两种不同的方法来做。第一种方法是将两个数字之间的差值与一些设定了比较精度的小数值进行比较。

...

第二种方式是将两个实数的归一化差值与一个零值进行比较。将归一化的数字之差与零进行比较是没有用的,因为对归一化的数字进行的任何数学运算都会产生一个未归一化的结果。

例子。

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }
void OnStart()
  {
   double d_val=0.3;
   float  f_val=0.3;
   if(CompareDoubles(d_val,f_val)) Print(d_val,"equals",f_val);
   else Print("Different: d_val = ",DoubleToString(d_val,16),
              "  f_val = ",DoubleToString(f_val,16));
// Результат: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }
  • 而我个人的实践经验(谦虚地说,就对程序运行的细致检查数量而言,它并不小,在那里我应用并仍然应用于用双数 进行比较 在这种比较的基础上触发条件的正确性)。
这使我能够认为这种比较不仅没有威胁性。
if(NormalizeDouble(number1-number2,dig)==0)
if(NormalizeDouble(number1-number2,dig)>0)
if(NormalizeDouble(number1-number2,dig)<0)

// dig=Digits();

恰恰相反,这是两种 方法 中的一种 变化,正如文件中所说,可以 适用于双数 的比较。

因为

你不能比较两个实数 是否相等。在大多数情况下,两个看似相同的数字可能会因为数值相差15位小数而变成不相等。为了正确比较两个实数,这些数字的归一化差值必须与零进行比较。



P./S.: 碰巧的是,文件中的第一种方法对我来说使用起来不太方便,也是基于任务,一般来说,我自己解决。因此,我对第一种方式没有很多经验。

但当使用第二种方式(即比较两个实数的归一化差值与条件运算符表达式中的零值)时,没有出现问题。

但是如果我做了非标准化数字的比较(这里我指的是,包括我没有使用第一种方法 所做的),那么是的,有,我发现在比较双倍 类型的数字的基础上,有不正确的条件触发。

 
gammaray:

这些是文件 中的短语。

第二种方法是将两个实数的归一化差值与零进行比较。 将归一化的数字之差与零进行比较是没有用的,因为对归一化数字的任何数学运算都会产生非归一化的结果。

对我来说,从简单的角度看,在数学运算(包括各种变换)中,不应该做这样的事情。

// dig=Digits();

double delta=NormalizeDouble(number1-number2,dig);

if (delta>0)


也就是说,在上面的前一篇文章 中,我给出了两个实数的归一化差值与零值 比较的例子。而在这篇文章中,将归一化后的数字之差与零 进行比较(按照我对文档中上述短语文字的理解)。

概括地说,就是这些了。

 

gammaray:

...

说实话,两个MA值之间的差异的正常化将起到什么作用,我并不真正理解。

P./S.: 关于这一点,你可以把Print()放在你的代码中一段时间,看看在大量的数据上会有什么输出。在打印中打印从数学运算中得到的非正常化和正常化的(直到某个小数位,包括比你要做实验的图表上的大)数值。包括简单的非正常化和正常化的iMA值,因为它们是在数学运算的基础上形成的。

为了以防万一,我还要说明,在打印非正常化和正常化的双倍类型的值时,应该另外进行转换,当然是用DoubleToString 从数值转换为文本值(并在DoubleToString中实验小数位数)。

 
gammaray:

P./S.: 我还想补充一点,我认为在为那些想学习MQL4编程的人写的任何方案的例子中,数学计算值的规范化可能没有规定或/和没有直接规定。

  • 为了便于理解形成任何条件的计划。
  • 可能并不总是和/或不是所有地方都需要归一化(包括它可能被认为适用于不同的任务的可容忍误差水平,并相应地对一些个别任务的小数位数的数学运算结果进行不同的进一步归一化(或缺乏它))。
  • 和/或,最可能的是,假设开发者熟悉文档 和/或阅读过文档,以澄清他们的问题。
类似这样的事情。
 
这更准确。
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<=slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>=slow1) Print("Пересечение ВНИЗ");

我的意思是,它没有考虑到玛值也可能是相等的。

сравнивать вещественные числа на равенство нельзя

略有不同。
 
Aleksey Lebedev:
关于其他事情的一点看法。

这取决于你有什么想法,为了什么任务/目标。

因此,在写这个主题的帖子时,我的依据是。

  • 第一个帖子中的截图和问题。
  • 该主题作者的第二个帖子(关于正常化的危险)。

因此,从这里开始,简而言之,就是我上面帖子的意思。

在规范化的帮助下,可以设置/调整所需的比较(和/或输出值)的准确度和/或对某些任务和目标的错误的容忍度,这反过来又允许在代码中规定特定条件时,在确切的位置和方式上触发程序条件。而归一化的差值与零的比较,不仅允许调整/调整使用关系操作的比较。"==".


P./S.: 因此,在任何情况下,我将再次说明,用这里列出的两种 方法中的 第一种方法比较实数,由于比较任何小数值的数字差异,我不能说比应用归一化更糟糕,当有必要调整比较的水平时(包括,因为对我来说,第二种方法似乎更方便,第一种和没有考虑自己的实际应用更详细)


 

这与mql在原则上没有关系。让我们来看看一种抽象的编程语言。在我给出的这个特定的例子中,主要问题是在一个和同一个条形图中的缪翼之差的值不相等(在第一个计算中为2e-16,而在第二个计算中正好为0)。在这种情况下,这个交叉点可能不会以任何方式确定。如果我们回到mql,规范化意味着对数字进行四舍五入(或者说,简单地去掉某个符号之后的所有数字,就像在Sish函数floor中一样,但要达到某个小数位)。那么,我如何知道要归一化到哪一位数?如果选择了错误的数字,所有的值都可能被四舍五入到0的位置。因此,正常化在这里是危险的,一般来说不能解决问题。

至于阿列克谢-列别杰夫写的东西。是的,我正朝着这个方向思考。但是,如果我们将两者的差异多于或等于0进行比较,就有可能得到一个错误的信号(例如,理论上可能出现的情况,即相邻条形图之间的μwings具有完全相同的值)。那么他们的差异不会改变符号(没有交叉),但交叉的信号将通过程序确定。你可以像你建议的那样,只把一个比较放在更多或相等上。但问题是,在这种情况下的计算中,首先它将不等于0(2e-16),而在下一栏中,它将正好是0,但它将是一个严格的比较。

重要的是要理解为什么同样的差异,在不同的条形图上计算,会产生不一样的结果。如果结果是一样的,问题总是通过引入一个非严格的比较来解决的

 

gammaray:

但问题是,这种情况下的计算首先不会等于0(2e-16),而在下一个条形图上,它已经正好是0,但会有一个严格的比较。

重要的是要理解为什么同样的差异,在不同的条形图上计算,会产生不一样的结果。如果结果是一样的,问题总是通过引入一个非严格的比较来解决的

最有可能的是对iMA函数的计算进行了优化。第一个值=sum(close)/N,第二个值=以前的MA值+(新收盘-旧收盘)/N。