有谁知道如何开发一个多货币指标?

 
有谁知道如何开发一个多货币指标

我想选择1到10种不同的货币,每种货币有5个柱子。

但我不知道如何做到这一点。

 

在一个标准的指标中,你会用通过OnCalulate( ...) 事件函数发送的参数数据来建立缓冲阵列。但是,对于多货币 和/或多时间 段,你将不得不使用两种解决方案中的一种。

  • 使用 "iFunction "变体的旧方法,如iTime()iVolumeiOpeniClose 等,但使用不同的符号,如 "EURUSD"、"JPYUSD "等,而不是默认的_SymbolSymbol()
  • 使用ArrayCopyRates() 函数的第一个变体的较新方法,同时使用 MqlRates 的数组指针。 复制 "的数组,实际上不会占用任何空间,只是指向各种符号和时间框架的现有数据的指针。

然而,为了使其发挥作用,多符号和/或多时间段的工作必须存在两个条件之一。

  • 要么符号和时间框架的各自图表已经打开,这样就不会产生错误。
  • 否则,当你第一次请求数据时,你会得到一个错误4066(ERR_HISTORY_WILL_UPDATED),你将不得不编码一个睡眠和重试循环,以便等待数据下载,然后再次请求数据。

我个人建议的解决方案是ArrayCopyRates()MqlRates 方法,我认为这是处理4066错误的最有效也是最简单的方法。

在MQL4文档和帮助文件中有更多关于这个的信息。

PS!NB!当 访问内置的指标函数,如iMA()iATR() 等各种符号和时间框架时,记得也要实现睡眠和重试循环,这样也不会得到4066错误。以下是MQL4文件中的一段话。

Any indicator can be calculated on the data of not only current chart, but also on the data of any available symbol/period. If data (symbol name and/or timeframe differ from the current ones) are requested from another chart, the situation is possible that the corresponding chart was not opened in the client terminal and the necessary data must be requested from the server. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - the requested history data are under updating) will be placed in the last_error variable, and one will has to re-request (see example of ArrayCopySeries())
 
记住,OP问的是一个指标。Sleep()在指标中被忽略
 
GumRai:
记住,OP问的是一个指标。Sleep()在指标中是被忽略的。

对不起,我不知道。我在EA中广泛使用这种方法,但在指标中没有,所以不知道睡眠障碍。

在这种情况下,他将不得不在每次 调用OnCalculate() 函数时建立一个连续的重试循环(其中使用ArrayCopyRates() 是更好的解决方案)。

另外,如果它在OnInit() 函数中起作用,它可能是为指标准备数据的首选方法,对于这种情况,有很长的重试次数(没有睡眠)。

 
FMIC:

...

  • 否则你在第一次请求数据时将得到一个错误4066(ERR_HISTORY_WILL_UPDATED),你将不得不编写一个睡眠和重试循环,以便等待数据下载,然后再次请求数据。

PS!NB!当 访问内置的指标函数,如iMA()iATR() 等各种符号和时间框架时,记得也要实现睡眠和重试循环,这样也不会得到4066错误。以下是MQL4文件中的一段话。


除非他们最近改变了什么,否则每次从第一个函数调用 开始,你都会得到4066错误(而且只从这第一个调用开始),不管条件或历史更新进度如何。它没有任何实际用途。
 
Ovo:
除非他们最近改变了什么,否则每次从第一个函数调用开始(而且只从这第一个调用开始),无论条件或历史更新进度如何,你都会得到4066的错误。它没有任何实际用途。
我的情况不是这样的。当数据已经完全可用时,我不会得到4066错误。然而,如果它不是直接可用的,那么是的,我只在第一次调用该特定符号和时间框架的任何函数 时得到错误。在那之后,任何其他请求该数据的函数都不会再出现错误。
 

FMIC:

在这种情况下,他将不得不在每次调用OnCalculate() 函数时,围绕连续的调用建立一个重试循环(其中使用ArrayCopyRates() 是更好的解决方案)。

另外,如果它在OnInit() 函数中起作用,它可能是为指标准备数据的首选方法,在这种情况下有很长的重试次数(没有睡眠)。

  1. 指标中的循环(长的或其他的)将不会 工作。当指标在运行时,终端中的其他事情 不能发生。这就是为什么睡眠不能在指标中工作。也是为什么ArrayCopyRates是异步的(对于指标。)
  2. 在init中启用费率数组。在OnTick 中测试它,并在那里处理重试。还要记住不同的图表在不同的 时间创建新的条形图。
    string pairs[] = {"EURUSD", "GBPUSD" ...}
    MqlRates pair0[], pair1[], ...
    bool initial;
    OnInit(){ initial=true;
       ArrayCopyRates(pair0, pairs[0], _Period);   
       ArrayCopyRates(pair1, pairs[1], _Period);
       :
    }
    OnCalculate( ... ){
       int count = IndicatorCounted();
       if(initial){
          if(pair1[0].time == 0) return;
          if(pair2[0].time == 0) return;
          :
          initial=false; count = 0; // process all bars
       }
       for(int i = Bars - 1 - MathMax(lookback, count); i >= 0; --i){
          int shift0 = iBarsShift(pairs[0], _Period, Time[i]);
          int shift1 = iBarsShift(pairs[1], _Period, Time[i]);
          buffer[i] = pair0[shift0].close - pair1[shift1].close;

  3. 如果你不想使用ArrayCopyRates,你不必这样做,但你仍然必须通过用iTime() 替换[if(initial)]中的pairN[0].time 来加载其他货币对。
 
   if(pair1[0].time == 0) return;

这将永远不会是真的。

如果该符号和时间框架有任何历史记录,该函数将检索最新的值。

如果没有加载历史记录,你会得到一个Array out of range 的错误。

与iTime等相同

 
GumRai:

这将永远不会是真的。

如果该符号和时间框架有任何历史记录,该函数将检索最新的值。

如果没有加载历史记录,你会得到一个Array out of range的错误。

与iTime等相同

我倾向于同意!

就个人而言,我只是检查 "ArrayCopyRates() "的返回值,之后我只是在访问数组数据之前跟踪数组的大小。

关于 "iTime() "和其他此类函数,我总是先检查 "iBars()"。

 
GumRai:

这将永远不会是真的。

  if(pair1[0].time == 0) return;

如果该符号和时间框架有任何历史记录,该函数将检索最新的值。

如果没有加载历史记录,你会得到一个Array out of range的错误。

与iTime等相同

有许多历史上(建国前600年)看ACR的例子。没有其他办法。随后对ACR或iTime的调用不会返回4066,所以你怎么可能知道数据是否已经被下载。

iTime总是在错误时返回0。

 
WHRoeder:

有许多历史上(建国前600年)的例子可以看一下ACR。没有其他方法可以做到。随后对ACR或iTime的调用不会返回4066,所以你怎么可能知道数据是否已经被下载。

iTime总是在出错时返回0。

你说的 "没有其他方法 "是什么意思?

检查 "ArrayCopyRates "的返回数,并检查数组大小,似乎是一种更稳健的检查方法,而不是做 "pair1[0].time == 0",后者很容易返回一个"数组索引超出范围"的错误。

编辑:在更仔细地重新阅读你的帖子后,删除了我的一些陈述。