简体   繁体   English

如何在MQL4中量化指标?

[英]How to Quantise an indicator in MQL4?

I am failing over and over trying to get this indicator to run quantised with 2 buffers in . 我一遍又一遍地尝试使该指标运行在 2个缓冲区中进行 After a long time reading I have put 2 extra buffers in to squish it :/ because: 经过长时间的阅读,我放入了2个额外的缓冲区来压缩它:/因为:

the indicator is sitting between 0.1430-0.1427 at present but doesn't have a fixed top and bottom . 该指标目前位于0.1430-0.1427之间,但没有固定的顶部和底部

I can't seem to suss it; 我似乎没什么好怀疑的。 cool indicator but won't play fair! 很酷的指标,但不能公平竞争!

#property indicator_separate_window
#property indicator_buffers   4
#property indicator_color1    Lime
#property indicator_color2    Red
#property indicator_color3    CLR_NONE
#property indicator_color4    CLR_NONE
//#property indicator_minimum 0
//#property indicator_maximum 100
extern int    P   =   13;
extern int    T   = 3000;
extern double P2  =    0.001;
//int         MIN =    0;
//int         MAX =  100;
double G[];
double R[];
double B3[];
double B4[];

int init(){
   IndicatorBuffers(4);
   SetIndexBuffer( 0, G  );SetIndexStyle( 0, DRAW_LINE, STYLE_SOLID, 1, Lime );
   SetIndexBuffer( 1, R  );SetIndexStyle( 1, DRAW_LINE, STYLE_SOLID, 1, Red  );
   SetIndexBuffer( 2, B3 );SetIndexStyle( 2, DRAW_NONE );
   SetIndexBuffer( 3, B4 );SetIndexStyle( 3, DRAW_NONE );
   return(0);
}
int start(){
      if (  T >= Bars ) T = Bars;

      SetIndexDrawBegin( 0, Bars - T + P + 1 );
      SetIndexDrawBegin( 1, Bars - T + P + 1 );
      SetIndexDrawBegin( 2, Bars - T + P + 1 );
      SetIndexDrawBegin( 3, Bars - T + P + 1 );

      int Z, C, Opt = IndicatorCounted();

      if (  Bars <= 38 ) return(0);

      if (  Opt  <  P ){
         for ( Z = 1; Z <= 0; Z++ ) G[T-Z] = 0.0;
         for ( Z = 1; Z <= 0; Z++ ) R[T-Z] = 0.0;
      }

      Z = T - P - 1;

      while( Z >= 0 ){
         double A, S1, S2;
         S1 = 0.0; for ( C = 0; C <= P - 1; C++ ){ S1 = S1 + (   High[Z+C] + Low[Z+C] ) / 2;}
         S2 = 0.0; for ( C = 0; C <= P - 1; C++ ){ S2 = S2 + ( ( High[Z+C] + Low[Z+C] ) * ( C+1 ) / 2 );}
         A  = S1 / S2;
         // if (  A < MIN ){ MIN = A;}
         // if (  A > MAX ){ MAX = A;}
         // A = ( MIN / MAX ) * 100;
         G[Z] = A;
         if (  Z > 0 ){ R[Z-1] = A;}
         Z--;
      }
      for ( int N = T-P-2; N >= 0; N-- ){
         if (  N > 0 ){
               if ( G[N-1] > G[N] ){ R[N] = EMPTY_VALUE; continue;}
               if ( G[N-1] < G[N] ){ G[N] = R[N];        continue;}
         }
         B3[0] = G[0] + P2;
         B4[0] = G[0] - P2; //forced quantise using 2 extra buffers
      }
      return(0);
   }

Let´s split the task first 让我们先分割任务

0 ) indicator logic 0 )指示器逻辑
1 ) indicator quantisation step 1 )指标量化步骤
2 ) indicator performance 2 )指标表现

MQL4 Custom Indicator programming relies on deeper understanding of underlying MetaTrader4 Terminal platform. MQL4自定义指标编程依赖对底层MetaTrader4终端平台的更深入了解。 Each external Market Event, changing a traded instrument price, is signalled to a lcoalhost by a network delivery of a QUOTE ... message from MetaTrader4 Server . 通过从MetaTrader4服务器通过网络传递QUOTE ...消息将每个更改的交易工具价格的外部市场事件通知给lcoalhost。 This is aka Tick and it triggers a call to a function originally called start() , in newer New - MQL4.56789 renamed to OnTick() . 这就是Tick,它会触发对最初名为start()的函数的调用,在较新的New - MQL4.56789重命名为OnTick()

The below modified MQL4 listing contains remarks for core-logic disambiguation, which must precede all the below listed steps. 下面修改后的MQL4清单包含有关核心逻辑歧义消除的注释,这些注释必须在以下所有列出的步骤之前。


1 ) indicator quantisation step 1 )指标量化步骤

While the code is still very inefficient ( as per [2] below ) the logic does not include any straight hurdle form having the output quantised to any form thereof { binary | 虽然代码仍然非常低效(按照下面的[2]所述),但逻辑不包括任何直接的障碍形式,其输出被量化为其任何形式。 ternary | 三元| arbitrary-number-of-states }-quantised system. 状态的任意数量}的系统。 Whence the indicator core-logic is cleared, the quantisation step is just a trivial conversion from R(1) to I(1) . 一旦清除了指示符核心逻辑,量化步骤就是从R(1)I(1)的简单转换。


2 ) indicator performance 2 )指标表现

Any Tick arrival may, but need not modify either High[0] or Low[0] , which are the only variable parts of the proposed Custom Indicator calculus. 任何滴答声到达都可以但不必修改High[0]Low[0] ,这是建议的“自定义指标”演算的唯一可变部分。

This is the core idea on how to reduce the scope of re-calculations, that the MQL4 code has to realise per tick. 这是关于如何减少重新计算范围的核心思想,即MQL4代码必须在每个滴答中实现。 In recent versions of MT4, all Custom Indicators share a single thread , the more stress has been put on efficient algorithmisation of Custom Indicators, at these may block the platform's trading decisions on poor, inefficient code-loops and convolution/recursion re-executions. 在最新版本的MT4中, 所有自定义指标共享一个线程 ,对自定义指标的高效算法施加了更大的压力,因为这可能会阻止平台在不良,低效的代码循环和卷积/递归重新执行方面的交易决策。

#property indicator_separate_window
#property indicator_buffers   4
#property indicator_color1    Lime
#property indicator_color2    Red
#property indicator_color3    CLR_NONE
#property indicator_color4    CLR_NONE

extern int    P   =   13;
extern int    T   = 3000;
extern double P2  =    0.001;

double G[];                                                         // 0: LINE
double R[];                                                         // 1: LINE
double B3[];                                                        // 2: BUT NEVER PAINTED, NEVER CONSUMED _?_
double B4[];                                                        // 3: BUT NEVER PAINTED, NEVER CONSUMED _?_

int init(){
   IndicatorBuffers(4);
   SetIndexBuffer( 0, G  );SetIndexStyle( 0, DRAW_LINE, STYLE_SOLID, 1, Lime );
   SetIndexBuffer( 1, R  );SetIndexStyle( 1, DRAW_LINE, STYLE_SOLID, 1, Red  );
   SetIndexBuffer( 2, B3 );SetIndexStyle( 2, DRAW_NONE );
   SetIndexBuffer( 3, B4 );SetIndexStyle( 3, DRAW_NONE );
   return(0);
}
int start(){

    if (  Bars <= 38 ) return(0);                                   // JIT/RET in case Bars < 39 --^ --^ --^ --^

    if (  T >= Bars ) T = Bars;                                     // (TRIM´d) T < Bars .OR. = Bars

    int aDrawBegins     = Bars - T + P + 1;                         // ( extern P = 13 ) + 1 + ( Bars - ( extern T = 3000 if T < Bars else Bars ) )
    //tIndexDrawBegin( 0, Bars - T + P + 1 );                       // PREF: ( reused 4x )
    SetIndexDrawBegin( 0, aDrawBegins );                            // Draw  14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
    SetIndexDrawBegin( 1, aDrawBegins );                            // Draw  14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
    SetIndexDrawBegin( 2, aDrawBegins );                            // Draw  14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?
    SetIndexDrawBegin( 3, aDrawBegins );                            // Draw  14+ last candles -- PREF: why a per tick hard-coded SHIFTING / enforced re-draw?

    double A, S1, S2;                                               // auxiliary var for bar-mid-price calculi
    int    Z;                                                       // auxiliary stepper
    int    Opt = IndicatorCounted();                                // Opt ( NEVER RE-USED )

    if (  Opt  <  P ){                                              // if ( ( extern P = 13 ) > IndicatorCounted() )
       // ----------------------- ??? ----------------------------------------------------- NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
       for ( Z = 1; Z <= 0; Z++ ) G[T-Z] = 0.0;                     // .STO G[T-Z], 0., BUT NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
       for ( Z = 1; Z <= 0; Z++ ) R[T-Z] = 0.0;                     // .STO R[T-Z], 0., BUT NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
       // ----------------------- ??? ----------------------------------------------------- NEVER EXEC´d: for( Z = 1++ v/s Z <= 0 )
    }

    Z = T - P - 1;                                                  // .STO Z, ( T = Bars (TRIM´d) ) - ( extern P = 13 ) - 1

    while( Z >= 0 ){                                                // .DEC Z
       //        !!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PERF: very inefficient to RE-calc STATIC ( ( extern P = 13 ) - 1 )-DEEP CONVOLUTIONS per tick !!
       S1 = 0.0; for ( int C = 0; C <= P - 1; C++ ){ S1 = S1 + (   High[Z+C] + Low[Z+C] )           / 2;  }
       S2 = 0.0; for ( int C = 0; C <= P - 1; C++ ){ S2 = S2 + ( ( High[Z+C] + Low[Z+C] ) * ( C+1 ) / 2 );}
       //        !!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PERF: very inefficient to RE-calc STATIC ( ( extern P = 13 ) - 1 )-DEEP CONVOLUTIONS per tick !!
       A  = S1 / S2;
       G[Z] = A;                                                    // .STO G[Z],   A if Z >= 0
       if (  Z > 0 ){ R[Z-1] = A;}                                  // .STO R[Z-1], A if Z >  0
       Z--;
    }

    for ( int N = T - P - 2; N >= 0; N-- ){                         // .STO N, ( T = Bars (TRIM´d) ) - ( extern P = 13 ) - 2
       if (   N > 0 ){                                              // N > 0:
              if ( G[N-1] > G[N] ){ R[N] = EMPTY_VALUE; continue;}  // .BLNK R[N], EMPTY if G[N-1] > G[N]
              if ( G[N-1] < G[N] ){ G[N] = R[N];        continue;}  // .SET  G[N], R[N]  if G[N-1] < G[N]
       }
    // ?? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // WHY MANY-TIMES RE-ASSIGNED A CONST. VALUE HERE, INSIDE A FOR(){...}-loop body? -------------- ??
       B3[0] = G[0] + P2;                                           // .STO B3[0], G[0] + ( extern P2 = 0.001 )
       B4[0] = G[0] - P2;                                           // .STO B4[0], G[0] - ( extern P2 = 0.001 )
                                                                    // forced quantise using 2 extra buffers
    // ?? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // WHY MANY-TIMES RE-ASSIGNED A CONST. VALUE HERE, INSIDE A FOR(){...}-loop body? -------------- ??
    }
    return(0);
}

New - MQL4.56789 syntax 新增 MQL4.56789语法

The OnCalculate() function is called only in custom indicators when it's necessary to calculate the indicator values by the Calculate event . 仅在需要通过Calculate事件计算指标值时,才在自定义指标中调用OnCalculate()函数。 This usually happens when a new tick is received for the symbol, for which the indicator is calculated. 这通常发生在为该符号接收到新的价格变动时,为此计算指标。 This indicator is not required to be attached to any price chart of this symbol. 不需要将该指标附加到该符号的任何价格图表上。

The first rates_total parameter contains the number of bars , available to the indicator for calculation, and corresponds to the number of bars available in the chart. 第一rates_total参数包含的数bars ,提供给用于计算指标,并且对应于图表中可用的条的数量。

We should note the connection between the return value of OnCalculate() and the second input parameter prev_calculated . 我们应该注意OnCalculate()的返回值和第二个输入参数prev_calculated During the OnCalculate() function call, the prev_calculated parameter contains a value returned by OnCalculate() during previous call. OnCalculate()函数调用期间, prev_calculated参数包含上一次调用期间OnCalculate()返回的值。 This allows for economical algorithms for calculating the custom indicator in order to avoid repeated calculations for those bars that haven't changed since the previous run of this function. 这允许使用经济的算法来计算自定义指标,以避免重复计算自该函数上一次运行以来未发生变化的柱线。

For this, it is usually enough to return the value of the rates_total parameter, which contains the number of bars in the current function call. 为此,通常返回rates_total参数的值就足够了,其中包含当前函数调用中的柱数。 If since the last call of OnCalculate() the price data has changed (a deeper history downloaded or history blanks filled), the value of the input parameter prev_calculated will be set to zero by the terminal. 如果自从上次调用OnCalculate()以来价格数据已更改(下载了更深的历史记录或填充了历史记录空白),则prev_calculated 将把输入参数prev_calculated的值设置为零。

//+------------------------------------------------------------------+ 
//| Custom indicator iteration function                              | 
//+------------------------------------------------------------------+ 
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[]
                  )
  {
  // Get the number of bars available now for the current Symbol and chart period 
     int barsNow = Bars( _Symbol, PERIOD_CURRENT );

  // .RET value of prev_calculated for a next call
     return( rates_total );
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM