新人对MQL4和MQL5的任何问题,对算法和代码的帮助和讨论 - 页 1900

 
Vitaly Muzichenko #:


这里是最好的方法。
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
  int H=100;
  double b, a;
  if(prev_calculated==0) {
    ArrayInitialize(Buffer1,EMPTY_VALUE);
    ArrayInitialize(Buffer2,EMPTY_VALUE);
  }

  b=SymbolInfoDouble(Symbol(),SYMBOL_BID);
  a=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

  if(rates_total-prev_calculated==1) {
    Buffer1[H+1]=EMPTY_VALUE;
    Buffer2[H+1]=EMPTY_VALUE;
  }
  else if (rates_total == prev_calculated) { // сдвигаем данные только когда количество баров не поменялось (в случае появления нового бара они сдвигаются системой терминала)
    for(int j=H; j>0; j--) { 
      Buffer1[j]=Buffer1[j-1];
      Buffer2[j]=Buffer2[j-1];
    }
  }
  // записываем новые данные
  Buffer1[0]=b;
  Buffer2[0]=a;
  return(rates_total);
}
 
JRandomTrader 一个循环缓冲区,记住第一个元素的当前位置,如何?

多么聪明的想法啊!谁提出来的,其实际应用是什么?我怀疑它是专门用于滑动窗口图表的...

 
Mihail Matkovskij #:

多么聪明的想法啊!谁提出来的,其实际应用是什么?我怀疑它是专门用于滑动窗口图表的...

的确,知道你能回滚多少数据并不是不合理的。因为这个圆形缓冲区是 "踩在自己的脚趾上",由于其长度有限...

 
Mihail Matkovskij #:
这里是最好的方法。

检查了一下,是的,这是一个很好的解决方案--我要保留它。

但我仍然想检查ArrayCopy 是否有效

---

我决定这样做,因为撕掉图形并不好看。

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_label1  "Bid"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_label2  "Ask"

double Buffer1[];
double Buffer2[];
int H;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
{
  SetIndexBuffer(0,Buffer1);
  ArraySetAsSeries(Buffer1,true);
  SetIndexBuffer(1,Buffer2);
  ArraySetAsSeries(Buffer2,true);
  ArrayInitialize(Buffer1,EMPTY_VALUE);
  ArrayInitialize(Buffer2,EMPTY_VALUE);
  IndicatorSetInteger(INDICATOR_DIGITS,Digits());
  IndicatorSetString(INDICATOR_SHORTNAME,"Tick:");
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
  H=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);
  if(prev_calculated==0) {
    ArrayInitialize(Buffer1,EMPTY_VALUE);
    ArrayInitialize(Buffer2,EMPTY_VALUE);
  }

  double b=SymbolInfoDouble(Symbol(),SYMBOL_BID);
  double a=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

  if(rates_total-prev_calculated==1) {
    Buffer1[H+1]=EMPTY_VALUE;
    Buffer2[H+1]=EMPTY_VALUE;
  } else if(rates_total == prev_calculated) { // сдвигаем данные только когда количество баров не поменялось (в случае появления нового бара они сдвигаются системой терминала)
    for(int j=H; j>0; j--) {
      Buffer1[j]=Buffer1[j-1];
      Buffer2[j]=Buffer2[j-1];
    }
  }
// записываем новые данные
  Buffer1[0]=b;
  Buffer2[0]=a;
  return(rates_total);
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // идентификатор события
                  const long& lparam,   // параметр события типа long
                  const double& dparam, // параметр события типа double
                  const string& sparam  // параметр события типа string
                 )
{
  if(id==CHARTEVENT_CHART_CHANGE) {
    H=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);
    int B=Bars(Symbol(),0);
    for(int j=H; j<B; j++) {
      Buffer1[j]=EMPTY_VALUE;
      Buffer2[j]=EMPTY_VALUE;
    }
  }
}
//+------------------------------------------------------------------+
 
JRandomTrader 一个环形缓冲器,记住第一个元素的当前位置,那会怎么样?

在维塔利的例子中,你可以使用这个想法。但没有办法避免循环(这对它来说是至关重要的)。在任何情况下,我们都必须使用循环或ArrayCopy函数将数据从环形缓冲区转移到指标缓冲区。那么什么会改变呢?

 
Mihail Matkovskij #:

多么聪明的想法啊!谁提出来的,其实际应用是什么?我怀疑它是专门用于滑动窗口图表的...

谁想出来的--没有尽头,我想它已经被重新发明过很多次了,这个想法很明显。

例如,我用它来计算没有储存在历史中的数据的移动平均数,而只有一个瞬时值。

自古以来,这一直被用于数据传输。

 
Mihail Matkovskij #:

在维塔利的例子中,你可以使用这个想法。但没有办法避免循环(这对它来说是至关重要的)。在任何情况下,我们都必须使用循环或ArrayCopy函数将数据从环形缓冲区转移到指标缓冲区。那么有什么不同呢?

即可以插入一个新的值,并立即从所需的地方复制。复制周期仍然存在,但没有移位周期。

 
Vitaly Muzichenko #:

检查了一下,是的,这是一个很好的解决方案--我要保留它。

但我还是想看看ArrayCopy 是如何工作的。

使用ArrayCopy,你只能从另一个阵列中传输数据。但你不能转移它们。你可以使用一个环形缓冲器,并从它那里转移数据...但是,如果ArrayCopy有循环运动,你怎么能用它来做呢...我不明白。而且,原则上,它不需要被理解。通常使用循环的位移,在速度方面并不那么关键。至少,我不知道有多快。有什么可以更快,只有汇编程序?总之,让它保持现状。它将发挥作用。

 
JRandomTrader #:

即一个新的值可以立即从正确的地方插入和复制。复制周期仍然存在,但没有移位周期。

让我们举一个例子,这将是在

升级的代码

Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам
Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам
  • 2022.02.13
  • www.mql5.com
В этой ветке я хочу начать свою помощь тем, кто действительно хочет разобраться и научиться программированию на новом MQL4 и желает легко перейти н...
 
Mihail Matkovskij #:

使用ArrayCopy,你只能从另一个阵列中传输数据。但不可能转移它们。你可以使用一个循环缓冲器,并从它那里传输数据...但是,如果ArrayCopy有圆周运动,如何用它来做呢...我不明白。而且,原则上,它不需要被理解。通常使用循环的位移,在速度方面并不那么关键。至少,我不知道有多快。还有什么能更快呢?"汇编"?总之,让它保持现状。会成功的。

现在,该代码可以工作,但由于循环的原因,速度值得怀疑。

将会是什么呢?

我想测试一些套件的套利能力,该指标将画出数值的差异,每100ms在一个定时器上运行一次。代码执行延迟对于这种情况至关重要。

原因: