总结:
Q1:如何让代码工作?
A1:重写迭代for-loop,以免在第一个循环中立即退出
(参考下图所示的迭代流程/障碍)
Q2:如何编写正确的代码以在迭代中使用布尔运算访问数组?
A2:完全没有这个问题。如果可能,请始终避免在分配某个值之前测试数组值
( 参考下面的陷阱 )
Q3:请问有什么解决办法?
A3:修复格式不正确的for-loop + 在将其值用于进一步处理或比较之前,始终将有意义的值分配给变量。
算法如何处理特征的明确部分:
//+------------------------------------------------------------------+
//| 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" );
}
}
问题不是从 for 循环内部访问数组 cell[i]
如上所述,您的代码原样不符合您的目标。
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 );
}
它开始在 bool MA() 中迭代 i-range ( 5, 4, 3, 2 )
并测试一系列比较:
仅在 "Up"-case 中:
[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],然后就可以了。
动态数组内存分配/调整大小彩票副作用暴露您的代码为一个主要不可控的值,在两个比较{ [5]<=[4] | [5]> [4] } 中访问[4],这原则上除了iMA(...) 之外的其他任何东西。
由于您的观察表明 [4] 低于已分配给 [5] 的 iMA() 值,您有点幸运未初始化内存的随机性(包含不可控残留二进制值)包含没有其他方式,只是偶然一些残留位图,很高兴地被解释为IEEE-float32数字,低于单元格@中比较计算和存储的iMA()值987654350@与。
更新:
如果我要实现这个想法,我会怎么做?
在MQL4 域中经历了数百人*年之后,Technical Indicators 教会我们宁愿花一些时间将计算成本高昂的部分与算法的廉价部分分开,并将设计调整集中在更昂贵的部分上。
所以:
而是考虑避免浪费重新计算已经计算过的值 static double Slow[] 将允许您保存在 NewBar() 事件上计算过的值,或者使用相同的想法向前一步来保存而不是“尾部”的Slow[5..2],并在决定[0] 时重新比较它们,但生成和重复使用的不是iMA() 4B 值,而是它们已经进行的成对比较,这仅决定实际返回值:
static bool aTrendUpPrevGT[];
static bool aTrendDnPrevLT[];
这将重新表达if MA() 以仅更新最近的栏步骤
和
return ( aTrendUpPrevGT[5]
&& aTrendUpPrevGT[4]
&& aTrendUpPrevGT[3]
&& aTrendUpPrevGT[2]
)
ArraySetAsSeries()的正确使用和正确的索引步骤显然可以适应