Соблюдайте призывные подписи:
Индикатор { iMAOnArray | iStdDevOnArray() | ... }
рассчитывается слева направо. Для доступа к элементам массива как к массиву серий (т.е. справа налево) необходимо использовать функцию ArraySetAsSeries()
.
double iMAOnArray( double array[], // array with data <--------------
int total, // number of elements <-----------
int ma_period, // MA averaging period
int ma_shift, // MA shift
int ma_method, // MA averaging method
int shift // shift
)
double iStdDevOnArray( double array[], // array with data <--------------
int total, // number of elements <-----------
int ma_period, // MA averaging period
int ma_shift, // MA shift
int ma_method, // MA averaging method
int shift // shift
)
Второй раздел был крайне неэффективным:
Терминал MT4 известен тем, что имеет одно центральное узкое место. Общий одиночный поток всех графов для каждого экземпляра CustomIndicator
. Так что будьте в разы внимательнее внутри кода CustomIndicator
:
Counted_bars = IndicatorCounted();
i = Bars - Counted_bars - 1;
while( i > 0 )
{ Moving_Average_Close = iMA( _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_CLOSE, i );
Moving_Average_Low = iMA( _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_LOW, i );
Moving_Average_High = iMA( _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_HIGH, i );
ATR = iATR( _Symbol, PERIOD_CURRENT, 14, i );
if ( close[i] < Moving_Average_Close )
{ ATREx[i] = ( ( ( low[i] - Moving_Average_Low ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
// ATREx_200[i] = ( ( ( low[i] - Moving_Average_Low_200 ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
}
else ATREx[i] = ( ( ( high[i] - Moving_Average_High ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
i--;
}
int nBARs = 40; // //?40 vvv // NEVER LEAVE ANY FULL-DEPTH PROCESSING aFeasibleDEPTH WILL SUITE ENOUGH
double aCPY[]; // ||
ArraySetAsSeries(); // ||
// ||
j = Bars - Counted_bars - 1; // ||
while( j > 0 ) // || ?40 // OUGHT BE 40?
{ ArrayCopy( aCPY, ATREx, 0, j, nBARs );// vv vvv
double aStDev = iStdDevOnArray( aCPY, nBARs, 200, 0, MODE_EMA, 0 ), // NEVER LEAVE ANY EXTENSIVE PROCESSING PIECE OF CODE IN INDICATOR (a blocking solo-thread for *ALL* MT4.Graphs !!! )
aMeanL = iMAOnArray( aCPY, nBARs, 40, 0, MODE_EMA, 0 ); // NEVER LEAVE ANY EXTENSIVE PROCESSING PIECE OF CODE IN INDICATOR ( a blocking solo-thread for *ALL* MT4.Graphs !!! )
ATREx_Upper[j] = aMean + aStDev; // REUSE VALUEs NEVER RE-PROCESS THE SAME THING, THAT HAS ALREADY BEEN COMPUTED
ATREx_Lower[j] = aMean - aStDev; // REUSE VALUEs NEVER RE-PROCESS THE SAME THING, THAT HAS ALREADY BEEN COMPUTED
// *******************************************************************************************************************
// WAS 4x MORE EXPENSIVE:
// *******************************************************************************************************************
// ATREx_Upper[j] = iMAOnArray( ATREx, 0, 40, 0, MODE_EMA, j ) + iStdDevOnArray( ATREx, 0, 200, 0, MODE_EMA, j );
// ATREx_Lower[j] = iMAOnArray( ATREx, 0, 40, 0, MODE_EMA, j ) - iStdDevOnArray( ATREx, 0, 200, 0, MODE_EMA, j );
// *******************************************************************************************************************
j--;
}
Эпилог и исправления:
double aCPY[]; // best put MEM .ALLOC in file-scope declarations
ArraySetAsSeries( aCPY, True ); // lock a TimeSeries ordering right there
Хотя nBARs
может потребоваться некоторое количественное моделирование для достижения наилучшего баланса между точностью и вычислительными_затратами, настоятельно рекомендуется не копировать WHOLE_ARRAY
, за исключением случаев, когда действительно (математически подтверждено) полное обратное преобразование -ступенчатая свертка (где любое изменение в [0] должно получить вычислительное обратное распространение по принципу домино, более глубокое назад в историю aTimeDOMAIN - что по очевидным причинам является совершенно противоположным типом поведения, прямо противоположным потребности, с которыми технический анализ, основанный на количественных показателях, счастлив работать). Так что скорее копируйте, как Альберт ЭЙНШТЕЙН так прекрасно придумал для современной физики: «КОПИРУЙТЕ СКОЛЬКО ПОЛОС НАЗАД, СКОЛЬКО НЕОБХОДИМО, НО НЕ НИ ОДНИМ БОЛЬШЕ» — тогда вы получите наилучшие результаты.
Хотя повторное использование iMAOnArray()
и iStdDevOnArray()
не так эффективно в числовом и вычислительном отношении, как при использовании вычислений со скользящим окном, при котором никогда не выполняется повторный расчет какого-либо значения, но повышается скорость за счет повторного использования всех уже однажды вычисленных значений — iMAOnArray( ATTREx, WHOLE_ARRAY, 3, 0, MODE_SMA, j);
один из примеров, повторно зацикленный в [j]
автором while(){...}
.
person
user3666197
schedule
27.06.2017