概括:
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]
。
更新:
如果我要实施这个想法,我会怎么做?
在该领域工作了数百人*年之后MQL4
,Technical 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()
和正确的索引步骤是显而易见的