Ещё раз о ЦИКЛАХ

 
int IndicatorCounted( )


Функция возвращает количество баров не измененных после последнего вызова индикатора. В большинстве подсчитанные бары не нуждаются в пересчете. Функция используется для оптимизации вычислений.

Вопрос:А что бары могут изменятся? Когда, кем и при каких условиях?
Правильней сказать:Функция возвращает количество баров просчитанных индикатором в предыдущем его вызове или «функция возвращает указатель на последний бар просчитанный индикатором «.При первом вызове индикатора равна 0.При наличии в индикаторе нескольких буферов, расчитываемых не одновременно ,принимает значение Bars при просчете первого буфера.
Замечание:
В соответствии с декларированным разработчиками соглашением отсчет баров в истории и буферах индикаторов начинается с текущего (нулевого) вглубь истории.Отсчет баров в этой функции почему-то организован "против шерсти" т.е. от Bars к нулевому.Для наглядности второй вызов индикатора

График...................|<Bars--------------------------------------------------------0
буфер индикатора..|<Bars-------просчитанные-бары-----------------|
IndicatorCounted.....0----------------------------------------------------->|
limit=Bars-IndicatorCounted.........................................................|<-----0

При просчете буферов переход к номеру ячейки буфера организован через "горбатое" выражение (limit=Bars-IndicatorCounted) которое не дает представления о направлении отсчета и приводит к ошибкам и то , по моему мнению, значительным .
Рассмотрим Пример приведенный к этой функции:
 int start()
    {
     int limit;
     int counted_bars=IndicatorCounted();
  //---- проверка на возможные ошибки
     if(counted_bars<0) return(-1);
  //---- последний посчитанный бар будет пересчитан
     if(counted_bars>0) counted_bars--;
     limit=Bars-counted_bars;
  //---- основной цикл
     for(int i=0; i<limit; i++)
       {
        //---- ma_shift присваивается 0, потому что SetIndexShift, вызываемый выше
        ExtBlueBuffer[i]=iMA(NULL,0,JawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtRedBuffer[i]=iMA(NULL,0,TeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtLimeBuffer[i]=iMA(NULL,0,LipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
       }
  //----
     return(0);
    } 


Расчет буферов индикатора производится от НУЛЕВОГО бара вглубь истории т.е к limit. Это не есть правильно. Должно быть

limit=Bars-counted_bars;
for(int i=limit;i>0;i--)
{тело цикла
}далее по тексту..


ПОПУТНО при таком указании позиции ячейки в буфере многие индикаторы срывают график на текущем баре в вертикальную линию.При указании позиции

limit=Bars-counted_bars-2;

и убрав предыдущую строку

if(counted_bars>0) counted_bars--

проблема решается (интересно почему?).
ПРЕДЛОЖЕНИЕ 1:
Привести направление отсчета функции IndicatorCounted() в соответствие с принятым соглашением, т.е. функция должна возвращать количество баров непросчитанных индикатором при предыдущем его вызове.При первом вызове индикатора она будет равна Bars, при последующих вызовах IndicatorCounted().
Для наглядности:
График...................|<Bars-------------------------------------------------------0
буфер индикатора..|<Bars-----------------------------------------------|
IndicatorCounted.......................................................................|<-----0

В программе это будет выглядеть так:


int start()
    {
     int counted_bars=IndicatorCounted();
  //---- проверка на возможные ошибки
     if(counted_bars<0) return(-1);
  //---- последний посчитанный бар будет пересчитан
     pos=counted_bars-2;
  //---- основной цикл
     for( ;pos>0;pos--)
       {
        //---- ma_shift присваивается 0, потому что SetIndexShift, вызываемый выше
        ExtBlueBuffer[pos]=iMA(NULL,0,JawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,pos);
        ExtRedBuffer[pos]=iMA(NULL,0,TeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,pos);
        ExtLimeBuffer[pos]=iMA(NULL,0,LipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,pos);
       }
  //----
     return(0);
    }


------------------------------------------------------------------------------
Индикаторы имеют два применения.Первое-графическое отображение на чарте,второе- использование вычисляемых величин в экспертах или других индикаторах. В первом случае необходимо просчитывать и отображать на графике как правило не более 300-500 баров.Во втором необходим просчет на всю глубину истории. А индикатор просчитывает и заполняет буфера на всю длину истории наличной на компьютере не зависимо от необходимости.На мелких временных горизонтах, где длина истории значительна, это нецелесообразно.
ПРЕДЛОЖЕНИЕ 2:Дать возможность передавать функции количество баров на глубину которых необходимо просчитывать индикатор.При этом по умолчанию эта величина равна Bars.Т.е. функция будет иметь вид

int IndicatorCounted(int Bar=BARS);


Тогда если в индикаторе записать

.....
extend int Bar=500;
..


мы будем иметь возможность использовать индикатор на любую необходимую нам глубину истории.

К разработчикам:Понятно, что улучшать можно до бесконечности и что лучшее враг хорошего.Поэтому Ваше право принять или проигнорировать предложения.НО-дать ясное и исчерпывающее описание разработанного Вами языка Вы просто обязаны. Те полторы строчки, которые в Хелпе – это не описание, это отписка.
Без описания и с ошибками в примерах ,которым все следуют и на которых учатся,использование результатов индикаторов а тем более экспертов опасно.
Поправте, если я где-то неправ.

 
Вы провели хорошую теоретическую проверку, но рекомендую еще раз ознакомиться с практической реализацией стандартных индикаторов в MQL4 (все исходники есть в стандартной поставке). К сожалению, в логические рассуждения вкралась ошибка в самом начале на
Отсчет баров в этой функции почему-то организован "против шерсти" т.е. от Bars к нулевому.

что в последствии привело к неправильным выводам.

Загляните в раздел статей по экспертам:
https://www.mql5.com/en/code
 

 int start()
    {
     int limit;
     int counted_bars=IndicatorCounted();
  //---- проверка на возможные ошибки
     if(counted_bars<0) return(-1);
  //---- последний посчитанный бар будет пересчитан
     if(counted_bars>0) counted_bars--;
     limit=Bars-counted_bars;
  //---- основной цикл
     for(int i=0; i<limit; i++)
       {
        //---- ma_shift присваивается 0, потому что SetIndexShift, вызываемый выше
        ExtBlueBuffer[i]=iMA(NULL,0,JawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtRedBuffer[i]=iMA(NULL,0,TeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtLimeBuffer[i]=iMA(NULL,0,LipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
       }
  //----
     return(0);
    } 


Расчет буферов индикатора производится от НУЛЕВОГО бара вглубь истории т.е к limit. Это не есть правильно. Должно быть

limit=Bars-counted_bars;
for(int i=limit;i>0;i--)
{тело цикла
}далее по тексту..


ПОПУТНО при таком указании позиции ячейки в буфере многие индикаторы срывают график на текущем баре в вертикальную линию.



А если сравнить номера баров по которым проходят оба цикла? В первом случае от 0 до limit-1, во втором от 1 до limit. Вот и разрывы в расчетах.


ПРЕДЛОЖЕНИЕ 1:
Привести направление отсчета функции IndicatorCounted() в соответствие с принятым соглашением, т.е. функция должна возвращать количество баров непросчитанных индикатором при предыдущем его вызове.При первом вызове индикатора она будет равна Bars, при последующих вызовах IndicatorCounted().


Вот прелесть будет: перелапачивать кучу уже написанных индикаторов и советников. Это только представить надо!
Причина обращения: