for (int i=start; i { IKBuyBuffer [i-1] =0; ColorIKBuyBuffer [i-1] =1; IKSellBuffer [i-1] =0; ColorIKSellBuffer [i-1] =1; if (close [i-1]> open [i-1] &&close [i-1]> EMA34HBuffer [i-1] &&close [i-1]> EMA34LBuffer [i-1] &&low [i-1]> EMA125Buffer [i-1] &&low [i-1]> PSARBuffer [i-1] &&EMA125Buffer [i-1] IKBuyBuffer [i-1] =high [i-1]; ColorIKBuyBuffer [i-1] =0; } if (close [i-1] IKSellBuffer [i-1] =low [i-1]; ColorIKSellBuffer [i-1] =0; } } bars_calculated=calculated; // – - return value of prev_calculated for next call return (rates_total); } Здесь мы рассчитываем индикатор на предыдущем баре, так как на текущем баре цена close – это текущая цена тика. Откомпилируем код и присоединим индикатор к графику: Мы увидим, что, в общем и целом, индикатор дает верные сигналы на продажу и покупку, хотя в некоторых случаях он запаздывает и дает ложные сигналы: Как мы видим, происходит это из-за трендовой линии EMA125. Попробуем отвязать ее от текущего периода и попробуем определять тренд, скажем по дневному графику: EMA125Handle=iMA (NULL, PERIOD_D1,125,0,MODE_EMA, PRICE_CLOSE); При этом запаздывание, конечно, сократится, но количество ложных сигналов увеличится: Видимо для улучшения данной стратегии, нужно привлекать дополнительные индикаторы. Попробуем сделать этот же самый индикатор, но не с помощью графических построений, а помещая графические объекты на график символа. В свойствах индикатора теперь не нужно объявлять буфера данных и цвета индикатора и графические серии для них. Оставим только буфера индикатора для промежуточных расчетов и хэндлы используемых индикаторов: #property indicator_chart_window #property indicator_buffers 4 double EMA34HBuffer []; double EMA34LBuffer []; double EMA125Buffer []; double PSARBuffer []; int EMA34HHandle; int EMA34LHandle; int EMA125Handle; int PSARHandle; int bars_calculated=0; В функции OnInit соответственно оставим только привязку массивов к буферам промежуточных расчетов и получение хэндлов используемых индикаторов: int OnInit { // – - indicator buffers mapping SetIndexBuffer (0,EMA34HBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer (1,EMA34LBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer (2,EMA125Buffer, INDICATOR_CALCULATIONS); SetIndexBuffer (3,PSARBuffer, INDICATOR_CALCULATIONS); EMA34HHandle=iMA (NULL,0,34,0,MODE_EMA, PRICE_HIGH); EMA34LHandle=iMA (NULL,0,34,0,MODE_EMA, PRICE_LOW); EMA125Handle=iMA (NULL,0,125,0,MODE_EMA, PRICE_CLOSE); PSARHandle=iSAR (NULL,0,0.02, 0.2); // – — return (INIT_SUCCEEDED); } В функции 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 start; int calculated=BarsCalculated (EMA34HHandle); if (calculated <=0) { return (0); } if (prev_calculated==0 || calculated!=bars_calculated) { start=1; if (calculated> rates_total) values_to_copy=rates_total; else values_to_copy=calculated; } else { start=rates_total-1; values_to_copy=1; } if (!FillArrayFromMABuffer (EMA34HBuffer,0,EMA34HHandle, values_to_copy)) return (0); if (!FillArrayFromMABuffer (EMA34LBuffer,0,EMA34LHandle, values_to_copy)) return (0); if (!FillArrayFromMABuffer (EMA125Buffer,0,EMA125Handle, values_to_copy)) return (0); if (!FillArrayFromPSARBuffer (PSARBuffer, PSARHandle, values_to_copy)) return (0); for (int i=start; i { if (close [i-1]> open [i-1] &&close [i-1]> EMA34HBuffer [i-1] &&close [i-1]> EMA34LBuffer [i-1] &&low [i-1]> EMA125Buffer [i-1] &&low [i-1]> PSARBuffer [i-1] &&EMA125Buffer [i-1] if (!ObjectCreate (0,«Buy»+i, OBJ_ARROW,0,time [i-1],high [i-1])) { return (false); } ObjectSetInteger (0,«Buy»+i, OBJPROP_COLOR, clrGreen); ObjectSetInteger (0,«Buy»+i, OBJPROP_ARROWCODE,233); ObjectSetInteger (0,«Buy»+i, OBJPROP_WIDTH,2); ObjectSetInteger (0,«Buy»+i, OBJPROP_ANCHOR, ANCHOR_UPPER); ObjectSetInteger (0,«Buy»+i, OBJPROP_HIDDEN, true); ObjectSetString (0,«Buy»+i, OBJPROP_TOOLTIP,»»+close [i-1]); } if (close [i-1] if (!ObjectCreate (0,«Sell»+i, OBJ_ARROW,0,time [i-1],low [i-1])) { return (false); } ObjectSetInteger (0,«Sell»+i, OBJPROP_COLOR, clrRed); ObjectSetInteger (0,«Sell»+i, OBJPROP_ARROWCODE,234); ObjectSetInteger (0,«Sell»+i, OBJPROP_WIDTH,2); ObjectSetInteger (0,«Sell»+i, OBJPROP_ANCHOR, ANCHOR_LOWER); ObjectSetInteger (0,«Sell»+i, OBJPROP_HIDDEN, true); ObjectSetString (0,«Sell»+i, OBJPROP_TOOLTIP,»»+close [i-1]); } } bars_calculated=calculated; // – - return value of prev_calculated for next call return (rates_total); } Здесь функцией ObjectCreate создаются объекты стрелка, привязанные ко времени и максимальной или минимальной цене. Функцией ObjectSetInteger со свойством OBJPROP_COLOR определяется цвет стрелки. Функцией ObjectSetInteger со свойством OBJPROP_ARROWCODE определяется направление стрелки вверх или вниз. Функцией ObjectSetInteger со свойством OBJPROP_WIDTH определяется размер объекта. Функцией ObjectSetInteger со свойством OBJPROP_ANCHOR определяется привязка к цене сверху или снизу по центру. Функцией ObjectSetInteger со свойством OBJPROP_HIDDEN – true определяется отсутствие созданных объектов в списке объектов графика символа. Функцией ObjectSetString со свойством OBJPROP_TOOLTIP определяется содержание всплывающей подсказки при наведении указателя на объект. В функции OnDeinit уберем все добавленные графические объекты: void OnDeinit (const int reason) { ObjectsDeleteAll (0, -1, -1); } Более подробно о создании объектов на графике символа мы поговорим далее.