Язык программирования MQL5: Продвинутое использование торговой платформы MetaTrader 5 - страница 13
// – - checking for bars count
if (rates_total return (0); Если же в расчете буфера индикатора участвует хэндл другого индикатора, тогда проверяется количество рассчитанных данных для запрашиваемого индикатора: // – - узнаем количество рассчитанных значений в индикаторе int calculated=BarsCalculated (handle); if (calculated <=0) { PrintFormat («BarsCalculated () вернул %d, код ошибки %d», calculated, GetLastError ()); return (0); } После проверки первоначальной загруженной истории для расчетов, вычисляется размер данных, которые необходимо рассчитать в этом вызове функции OnCalculate (). В качестве примера, разберем блок кода, который приводится в справочнике, в разделе Технические индикаторы: int OnCalculate (const int rates_total, const int prev_calculated, const datetime &time [], const double &open [], const double &high [], const double &low [], const double &close [], const long &tick_volume [], const long &volume [], const int &spread []) { // – - количество копируемых значений из индикатора int values_to_copy; // – - узнаем количество рассчитанных значений в индикаторе int calculated=BarsCalculated (handle); if (calculated <=0) { PrintFormat («BarsCalculated () вернул %d, код ошибки %d», calculated, GetLastError ()); return (0); } // – - если это первый запуск вычислений нашего индикатора или изменилось количество значений в индикаторе // – - или если необходимо рассчитать индикатор для двух или более баров (значит что-то изменилось в истории) if (prev_calculated==0 || calculated!=bars_calculated || rates_total> prev_calculated+1) { // – - если массив больше, чем значений в индикаторе на паре symbol/period, то копируем не все // – - в противном случае копировать будем меньше, чем размер индикаторных буферов if (calculated> rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { // – - значит наш индикатор рассчитывается не в первый раз и с момента последнего вызова OnCalculate ()) // – - для расчета добавилось не более одного бара values_to_copy= (rates_total-prev_calculated) +1; } // – - запомним количество значений в индикаторе bars_calculated=calculated; // – - вернем значение prev_calculated для следующего вызова return (rates_total); } Здесь переменная values_to_copy – количество рассчитываемых значений в вызове функции OnCalculate (). Переменная prev_calculated – сколько было обработано баров функцией OnCalculate () при предыдущем вызове. Таким образом, при загрузке индикатора prev_calculated=0, а при каждом следующем поступлении нового тика prev_calculated= rates_total. Переменная prev_calculated также обнуляется терминалом, если вдруг изменилось значение переменной rates_total. Переменная bars_calculated – предыдущее количество рассчитанных данных для запрашиваемого индикатора, на основе которого рассчитывается данный индикатор. Таким образом, первая проверка здесь: prev_calculated==0 – индикатор только что загрузился или изменилась ценовая история. calculated!=bars_calculated – изменилось количество рассчитанных данных для запрашиваемого индикатора. rates_total> prev_calculated+1 – необходимо рассчитать индикатор для двух или более баров (значит, что-то изменилось в истории). Последнее условие вступает в противоречие с утверждением справочника: Если с момента последнего вызова функции OnCalculate () ценовые данные были изменены (подкачана более глубокая история или были заполнены пропуски истории), то значение входного параметра prev_calculated будет установлено в нулевое значение самим терминалом.