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 будет установлено в нулевое значение самим терминалом.
Если изменилась история, тогда сработает проверка prev_calculated==0 и проверка последнего условия будет излишней.
Теперь, если срабатывает первое или второе условие, тогда количество рассчитываемых значений – это размер входных таймсерий или количество рассчитанных данных для запрашиваемого индикатора, на основе которого рассчитывается данный индикатор, что из них меньше.
Если же первое или второе условие не срабатывают, тогда количество рассчитываемых значений:
values_to_copy= (rates_total-prev_calculated) +1;
Опять же, тут есть излишний код, так как, судя по справочнику, переменная prev_calculated может принимать значение либо 0, либо rates_total.
Поэтому, values_to_copy=1.
Таким образом, при поступлении нового тика, будет рассчитываться только одно значение индикатора для этого нового тика.
Рассмотрим другую реализацию вычисления размера данных, которые необходимо рассчитать в вызове функции OnCalculate ().
Для индикатора MACD это реализовано следующим образом:
// – - we can copy not all data
int to_copy;
if (prev_calculated> rates_total || prev_calculated <0) to_copy=rates_total;
else
{
to_copy=rates_total-prev_calculated;
if (prev_calculated> 0) to_copy++;
}
Опять же, судя по справочнику, здесь будет работать только код:
to_copy=rates_total-prev_calculated;
if (prev_calculated> 0) to_copy++;
Т.е. при загрузке индикатора to_copy=rates_total, а затем to_copy=1.
После вычисления размера данных, которые необходимо рассчитать в вызове функции OnCalculate (), производится их вычисление и заполнение ими буферов индикатора.
Если индикатор рассчитывается на основе хэндла другого индикатора, тогда производится копирование из буферов используемого индикатора в динамические массивы данного индикатора.
Читать дальше
Конец ознакомительного отрывка
Купить книгу