在MQL4中编写SMA自定义指标而不使用iMA()

时间:2016-07-27 17:31:12

标签: mql4

作为学习 MQL4 的练习,我正在编写一个自定义指标,它只复制简单移动平均线,但不使用内置iMA()函数。下面的代码将指标绘制到图表上,但除结尾外的每一行都显示极低的值。例如,在 AUD/CAD 图表上,通常在0.80-0.90范围内,SMA线在0.20-0.30附近。

这条线与价格同步上下移动,最后一根柱子似乎有一个准确的读数(因为SMA在那个时候达到当前价格),但其他一切都很低。我已经用尽了可能发生这种情况的每一个可能的原因,并没有改变它。有人可以帮我弄清楚出了什么问题吗?

/*
   SELF-CODED 5-DAY SMA
   Set up buffer with style, indexbegin, and color
   for each bar:
       calculate closing price of last 4 bars and current price
       use to find SMA value at that bar
   update last value after every tick
   lock each bar's SMA value once the bar has close
*/
#property strict
#property indicator_chart_window
#property indicator_buffers 1

double buffer[];

int OnInit() 
   {
   IndicatorBuffers(1);
   SetIndexBuffer(0, buffer);
   SetIndexStyle(0, DRAW_LINE);

   return(INIT_SUCCEEDED);
   }

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 limit = rates_total - prev_calculated;

   buffer[0] = iClose(NULL, 0, 0); 

   for(int b = 1; b<5; b++)
      {
      buffer[0] = buffer[0] + iClose(NULL, 0, b);
      }
   buffer[0] = buffer[0]/5;   

   for(int i = 1; i<limit; i++)
      {
      buffer[i] = iClose(NULL, 0, i); // Placeholder in first for loop interation
      for(int a = 1; a<4; a++) {
         {
         buffer[i] = buffer[i] + iClose(NULL, 0, i+a);
         }
      buffer[i] = buffer[i]/5.0;
      }
   }
return(rates_total);   
}

2 个答案:

答案 0 :(得分:0)

一旦决定先写一个自定义指标

,那就更难走了

As there are several, and very different, modes of programming in an MQL4 language, parts of which may and must even interact between themselves Custom Indicator 不是最困难的问题。

那么假设您已经管理了MQL4编程的其他格式,并且对于所述独立的5天SMA只有自定义指标的问题。

仔细研究一下建议的代码就会发现,你的算法浪费了很多CPU周期,这在一般情况下并不是一个好习惯,但对于自定义指标编码来说却是一种致命的做法, MetaTrader Terminal 4 中使用的所有技术指标,是的,所有指标只共享一个线程。因此,性能调优是强大,无阻塞和最快速运行的必要条件。否则,由于等待处理所有相关自定义指标 -s的瓶颈单线程,所有其他编程工作都开始窒息。 不,不,不 - 在生产等级系统中永远不会发生这种情况。

那么,如何攻击呢?

让我们回顾一下事实:

  1. 当前,“热门”栏 [0] 唯一元素,经历任何演变(在酒吧持续时间内)
  2. 一旦当前柱[0]结束,所有相关的技术数据将永久“冻结” - 是的,它们将从不更改
  3. 这对一个微不足道的观察意味着,任何指标值的 none (我重复NONE)应该只计算一次。

    - MQL4.56789 语法也支持此逻辑,其中每个OnCalculate()调用都会收到一对辅助索引值
    - 时间的演变已经走了多远( const int rates_total, ),即图表已经记录了多少条和
    - 多远计算已经与时间流程( const int prev_calculated )一起进行,即当自定义指标处理被中断时,最后已经计算(处理)的数量是多少(是的,微积分)值可以从设计中中断,并允许在 MetaTrader Terminal 4 刚刚开始运行时对所有排队的处理任务进行某种分段处理,并使用图形和指示器进行刷新和同步再次与外汇市场事件的外部流动。

    所以,让我们从这个故事的“结尾”开始,如果您当前的OnCalculate()来电已经收到 int delta_to_process = rates_total - prev_calculated; 从不,< br /> 确实从不作为一个原则,处理任何事情,但最后delta_to_process条。

    从已经计算过的任何一个堆中重新计算bean会使当前任务中的既不是进度(尚未计算的堆),也没有意义花费宝贵的有限线程CPU时钟的数量再次重复计数过程,以便为已经回答的问题接收相同的答案。

    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[]
                     )
       {
       for ( int ii = rates_total - prev_calculated; // from oldest to "hot"[0]
                 ii > EMPTY;                         //                      0 > EMPTY
                 ii--                                // forward [n,n-1,n-2,..0]
                 )
          buffer[ii] = ( iClose( _Symbol, PERIOD_D1, ii+0 ) // an even more brutal form
                       + iClose( _Symbol, PERIOD_D1, ii+1 ) // re-using buffer[ii+1] value
                       + iClose( _Symbol, PERIOD_D1, ii+2 ) // is left for one's
                       + iClose( _Symbol, PERIOD_D1, ii+3 ) // further experimentation
                       + iClose( _Symbol, PERIOD_D1, ii+4 ) // with performance tuning
                       ) / 5.0;                             
       }
       return( rates_total );
    }
    

    并且不要忘记通过格式正确的呼叫来呼叫:

    #define SMA_LINE_NUMBER_1 0                          // self-explanatory buffer-index ( zero-based )
    
    ... =  iCustom( _Symbol,                             // NULL is not so readable
                    PERIOD_D1,                           // 0 is dangerous on a Graph with a "foreign" TimeFrame
                    "aFileNAME_ofYourSMA_MQL4_code",     // yes, the pure FileNAME
                    SMA_LINE_NUMBER_1,                   // yes, use the first buffer data ( .DEF-ed in SetIndexBuffer(0, buffer); )
                    aBarOffsetToReturn_SMA_VALUE_for     // a reversed stepping number/index into automatically managed TimeSeries arrays
                    );
    

答案 1 :(得分:0)

buffer[i] = iClose(NULL, 0, i);        // Placeholder in first for loop iteration
for ( int a = 1; a < 4; a++ ) {
    {
      buffer[i] = buffer[i] + iClose(NULL, 0, i+a);
      }
buffer[i] = buffer[i]/5.0;

这可能不正确 - 如果“ i ”为1,则为buffer[1] = (Close[1]+Close[1+1]+Close[1+2]+Close[1+3]) / 5,当你从i + 0加到i + 3时,4个元素不是5个。

修复:“a&lt; = 4”。

建议检查先前计算的条形数量,以便仅更新最近的条形图,并从 Bars-1 (最早的条形图)开始,稍稍跳过然后计算所有值在路上

sum       += Close[i]; 
Buffer[i]  = sum / 5; 
sum       -= Close[i+4];
i--;                      // inside a loop