【问题标题】:Writing an SMA custom indicator in MQL4 without iMA()在没有 iMA() 的 MQL4 中编写 SMA 自定义指标
【发布时间】:2016-07-27 17:31:11
【问题描述】:

作为学习 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);   
}

【问题讨论】:

  • 所提出的算法本身效率非常低,需要对算法思维进行一些更改,但 StackOverflow 提倡 MCVE 策略以将所有与代码相关的主题建立在C完整的基础上和 Verifiable(即可重复的,包括与数据相关的值)——所以请按照上面的建议更新您的帖子。不管怎样,欢迎来到 StackOverflowMQL4 的狂野世界
  • 您介意发布一些定量输出吗?类似这样的东西:Print( "SYMBOL:", _Symbol," PERIOD:", PERIOD_CURRENT, " Last 6 Bars Close[i] := [ ", Close[5], ", ", Close[4], ", ", Close[3], ", ", Close[2], ", ", Close[1], ", ", Close[0]," ], SmaToTEST[1] = ", iCustom( _Symbol, PERIOD_CURRENT, "SMA", 0, 1 ), "SmaToTEST[0] = ", iCustom( _Symbol, PERIOD_CURRENT, "SMA", 0, 0 ) ); ?

标签: mql4


【解决方案1】:
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

建议检查之前计算的柱数,以便仅更新最近的柱,并从 Bars-1(最早的柱)开始略略略过,然后计算方式

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

【讨论】:

    【解决方案2】:

    前路艰难,曾经决定先写一个自定义指标

    As there are several, and very different, modes of programming in an MQL4 language, parts of which may and must even interact between themselvesCustom Indicator 是所有问题中最难的。

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

    仔细查看建议的代码表明,您的算法大量浪费 CPU 周期,这通常不是一个好的做法,但对于 Custom Indicator 编码来说是一种致命的做法,因为MetaTrader Terminal 4 中使用的所有技术指标,是的,所有指标共享一个线程。因此,性能调优对于稳健、非阻塞和尽可能快的操作来说是必须的。否则,由于等待处理所有相关 Custom Indicator-s 的瓶颈单线程,您的所有其他编程工作都会开始窒息。 不,不,不 - 这绝不会在生产级系统中发生。


    那么,如何攻击呢?

    让我们回顾一下事实:

    1. 当前,“热”条 [0]唯一的元素,它会经历任何演变(在条持续期间)
    2. 一旦当前柱状图 [0] 结束,所有相关的技术数据都将永远“冻结” - 是的,它们永远不会改变

    这对琐碎的观察意味着,任何指标值的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;
    永远不会,
    确实如此永远不要作为一个原则,
    处理任何东西,但最后一个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
                    );
    

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2021-09-04
      • 1970-01-01
      • 2020-01-28
      相关资源
      最近更新 更多