0

我能够获得从 Shift 1 到 Shift n 的移动平均线的值(n = 条形图的数量),并每 5 分钟条形图显示它们的值,但是当我添加了 'if (Direction == "Up") ' 以此类推,代码仅显示最后一个移位值并点击 ' break'。最重要的是,我不能将它们用于布尔运算。

我希望代码显示Alert()的值何时EMA有序上升,反之亦然(对于 a "Trend Down")。每当其中一个值发生变化(一个或多个柱的值高于或低于其他柱)时,它就是."No trend"

假设数量TrendBar超过 5 条;[] 数组是 Bar Shift。

算法为"Trend Up"

如果慢 [n] <= 慢 [...] <= 慢 [3] <= 慢 [2] <= 慢 [1] 则为真

否则为假

int TrendBar    = 5,
    SlowPeriod  = 14;

void OnTick()
{
    if (NewBar(PERIOD_M5) == true) 
    {
        if (MA("Up", PERIOD_M5) == true) Alert ("Trend Up good");
        else if (MA("Up", PERIOD_M5) == false) Alert ("Trend Up bias");
        else Alert ("No Trend");
    }
}

bool MA(string Direction, int TF)
{
    double Slow[];
    ArrayResize(Slow, TrendMinDurationBar + 1);

    for (int i = TrendBar; i > 1; i--)
        {
            Slow[i] = NormalizeDouble(iMA(Symbol(), TF, SlowPeriod, 0, MODE_EMA, PRICE_OPEN, i), Digits);
            Alert("DataSlow" + (string)i + ": " + DoubleToStr(Slow[i], Digits));
            if (Direction == "Up")
            {
                if (Slow[i] <= Slow[i-1]) return(true);
                else if (Slow[i] > Slow[i-1]) {return(false); break;}
            }
        }
    return(false);
}

bool NewBar(int TF)
{
    static datetime lastbar = 0;
    datetime curbar = iTime(Symbol(), TF, 0);

    if (lastbar != curbar)
        {
            lastbar = curbar; 
            return(true);
        }
    else return(false);
}

当我运行代码时,它只显示Alert( "Trend Up bias" ). break这意味着当迭代开始时代码总是点击' '。它不关心趋势是否处于真正的向上趋势(Slow[]数组中的所有 MA 值都是有序向上的)。

Q1:如何使代码工作?

Q2:如何编写正确的代码以在迭代中使用布尔运算访问数组?

Q3:请问有什么解决办法?

4

1 回答 1

0

概括:

Q1:如何使代码工作?

A1:重写迭代循环for,以免在第一个循环中立即退出
(参考下图所示的迭代流程/障碍)

Q2:如何编写正确的代码以在迭代中使用布尔运算访问数组?

A2:完全没有这样的问题。如果可能,请始终避免在分配某个值之前测试数组值
(参考下面的陷阱)

Q3:请问有什么解决办法?

A3 : 修复格式错误的for循环 + 始终将有意义的值分配给变量,然后再将其值用于进一步处理或比较。


算法化如何处理特征的明确部分:

//+------------------------------------------------------------------+
//|                                                      MQL4 strict |
//+------------------------------------------------------------------+ 
#property strict              // MQL4 compilation mode { strict }

//+------------------------------------------------------------------+
//|                                                   a global-scope |
//+------------------------------------------------------------------+
bool     aTrendUpGTprev[],    // MQL4 dynamic array
         aTrendDnLTprev[];    // MQL4 dynamic array

int      TrendBar    =  5,
         SlowPeriod  = 14;

void     OnInit()
{        ArraySetAsSeries( aTrendDnLTprev, True );  // MQL4 Reference / Array Functions / ArraySetAsSeries 
         ArraySetAsSeries( aTrendUpGTprev, True );
}

bool     isNewBar( const int TF = PERIOD_CURRENT )
{        
         static datetime lastBar = EMPTY;
                datetime currBar = iTime( _Symbol, TF, 0 );

         if (    lastBar != currBar )               // .TEST
         {       lastBar  = currBar;                // .UPD
                 updateMA( TF );                    // .UPD
                 return( true );                    // .RET .T.
         }
         return( false );                           // .RET .F.
}

void     updateMA( const int TF = PERIOD_CURRENT )
{
         static bool    isFirstCall = True;
         static double  SlowMA_0,
                        SlowMA_1;

         if (  isFirstCall )                    // .TEST
         {     isFirstCall = False;             // .SET / LOCK FOREVER
            // --------------------------------------------------------------------------------------------------------
            // INITIAL PRE-FILL FOR ANY-DEPTH TREND-CALCULUS
            // SHUFFLE-LOGIC LATCH-MOV PRINCIPALLY AVOIDS ANY-DEPTH RE-CALCULATION(S) - COMPUTATIONALLY EFFICIENT

               SlowMA_0 = NormalizeDouble( iMA( _Symbol,
                                                TF,
                                                SlowPeriod,
                                                0,
                                                MODE_EMA,
                                                PRICE_OPEN, // OPEN ?
                                                TrendBar
                                                ),
                                           Digits           // no need to Normalize here, as the values do not enter any XTO
                                           );
               for ( int iii = TrendBar - 1; iii > 0, iii-- )
               {     SlowMA_1 = SlowMA_0;
                     SlowMA_0 = SlowMA_0 = NormalizeDouble( iMA( _Symbol, TF, SlowPeriod, 0, MODE_EMA, PRICE_OPEN, iii ), Digits ); // no need to Normalize here, as the values do not enter any XTO
                     aTrendUpGTprev[iii] = (  SlowMA_0 >= SlowMA_1 );   // bi-state { True | False }
                     aTrendDnLTprev[iii] = (  SlowMA_0 <= SlowMA_1 );   // bi-state { True | False }
               }
         }

      // -------------------------------------------------------------------------------------------------------------
      // SHUFFLE-LOGIC LATCH-MOV PRINCIPALLY AVOIDS ANY-DEPTH RE-CALCULATION(S)  - COMPUTATIONALLY EFFICIENT
      // PROTECTED FROM DESYNC/ARTIFACTS FROM RE-ENTRY(-IES) WITHIN THE SAME BAR - SAFE-MODE

         static datetime lastBar = EMPTY;
                datetime currBar = iTime( _Symbol, TF, 0 );

         if (    lastBar != currBar )              // .TEST
         {       lastBar  = currBar;               // .UPD
                 SlowMA_1 = SlowMA_0;              // .MOV [1] << [0]
                 SlowMA_0 = SlowMA_0 = NormalizeDouble( iMA( _Symbol, TF, SlowPeriod, 0, MODE_EMA, PRICE_OPEN, 0 ), Digits ); // .NEW [0]
                 aTrendUpGTprev[0] = (  SlowMA_0 >= SlowMA_1 );         // bi-state { True | False }
                 aTrendDnLTprev[0] = (  SlowMA_0 <= SlowMA_1 );         // bi-state { True | False }
         }

      // -------------------------------------------------------------------------------------------------------------
      // MQL4 ( "new" MQL4 ) requirement to return even from a void fun() >>> MQL4 Reference / Updated MQL4
         return( NULL );
}

void     OnTick()
{
         if (  isNewBar( PERIOD_M5 ) )              // returns bool value per-se
         {  
            // if       (   MA( "Up", PERIOD_M5 ) ) Alert ( "Trend Up good" );   // Either this
            // else if  (  !MA( "Up", PERIOD_M5 ) ) Alert ( "Trend Up bias" );   // or this.
            // else                                 Alert ( "No Trend" );        // This is an un-reachable state within above defined logic
            // ----------------------------------------------------------------- // --------------------------------------------------------
                                                    // There is no principal chance
                                                    // to get a tri-state logic
                                                    // under one boolean var

               bool  isUP = aTrendUpGTprev[TrendBar];
               bool  isDN = aTrendDnLTprev[TrendBar];

               for ( int iii = TrendBar - 1; iii > 0; iii-- )
               {
                     isUP &= aTrendUpGTprev[iii];
                     isDN &= aTrendDnLTprev[iii];
               }
               if (  isUP )  Alert ( "Trend Up good" );  // if Slow[n] <= Slow[...] <= Slow[3] <= Slow[2] <= Slow[1] then true
               if (  isDN )  Alert ( "Trend Dn good" );

         }
}

问题不是cell[i]从内部for循环访问 Array

如上所述,您的代码原样不符合您的目标。

bool MA( const string Direction, const int TF )
{
     double       Slow[];
     ArrayResize( Slow, TrendMinDurationBar + 1 );

     for ( int  i  = TrendBar; i > 1; i-- )
     {     Slow[i] = NormalizeDouble( iMA( _Symbol, TF, SlowPeriod, 0, MODE_EMA, PRICE_OPEN, i ),
                                      Digits
                                      );
        // Alert( "DataSlow" + (string)i + ": " + DoubleToStr( Slow[i], Digits ) );

           if (  Direction == "Up" )
           {
                 if      ( Slow[i] <= Slow[i-1] ) return( true  );
                 else if ( Slow[i] >  Slow[i-1] ) return( false );
           }
    }
    return( false );
}

它开始迭代i-range ( 5, 4, 3, 2 )in并测试一系列比较: 仅在-case: , _____________ this , _____________ or this is & must be a reason for 中。. . . . . . . . . . . . . . . . . . . . . _ _ _ _ _ _ _ _ _ 代码永远不会超过这个 , , , bool MA()

"Up"
[5]<=[4] |-> RET .T.
[5]> [4] |-> RET .F.RET {.T. | .F.}

[4]<=[3] |-> RET .T.
[4]> [3] |-> RET .F.
[3]<=[2] |-> RET .T.
[3]> [2] |-> RET .F.

您可能已经注意到,动态数组中的MQL4初始化值不知道,在ArrayResize().

这使得条件{ [5]<=[4] | [5]> [4] }很容易受到您无法控制的问题的影响,因为您的代码已将值分配给Slow[5]尚未分配给[4]您,然后就可以了。

动态数组内存分配/调整大小抽奖的副作用将您的代码暴露给一个主要不可控的值[4]在两个比较中都可以访问{ [5]<=[4] | [5]> [4] },原则上它不是iMA(...).

由于您的观察表明该值[4]低于已分配的iMA()[5]因此您很幸运,未初始化的内存(包含无法控制的残留二进制值)的随机性没有其他方式包含,只是偶然一些残留位图,即愉快地被解释为 IEEE-float32 数字,低于iMA()单元格中比较的计算和存储值[5]


更新:

如果我要实施这个想法,我会怎么做?

在该领域工作了数百人*年之后MQL4Technical Indicators已经教会我们宁愿花一些时间将计算上昂贵的部分与算法的便宜部分分开,并将设计调整集中在更昂贵的部分上。

所以:

而是考虑避免浪费重新计算已经计算过的值 astatic double Slow[]将允许您保存在NewBar()事件上计算过的值或使用相同的想法向前一步来保存而不是“尾部” Slow[5..2],并在决定时重新比较它们in [0],但生成和重用的不是iMA()4B 值,而是它们已经进行的成对比较,它们仅决定实际的返回值:

static bool aTrendUpPrevGT[];
static bool aTrendDnPrevLT[];
这将重新阐明if MA()仅更新最近的条形步骤和

return (  aTrendUpPrevGT[5]
       && aTrendUpPrevGT[4]
       && aTrendUpPrevGT[3]
       && aTrendUpPrevGT[2]
          )

正确使用ArraySetAsSeries()和正确的索引步骤是显而易见的

于 2015-11-03T16:39:21.433 回答