Язык программирования MQL5: Продвинутое использование торговой платформы MetaTrader 5 - Страница 10
PlotIndexSetDouble (1,PLOT_EMPTY_VALUE,0);
PlotIndexSetInteger (1,PLOT_ARROW_SHIFT,10);
Свяжем массивы с буферами индикатора:
SetIndexBuffer (0,IKBuyBuffer, INDICATOR_DATA);
SetIndexBuffer (1,ColorIKBuyBuffer, INDICATOR_COLOR_INDEX);
SetIndexBuffer (2,IKSellBuffer, INDICATOR_DATA);
SetIndexBuffer (3,ColorIKSellBuffer, INDICATOR_COLOR_INDEX);
SetIndexBuffer (4,EMA34HBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (5,EMA34LBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (6,EMA125Buffer, INDICATOR_CALCULATIONS);
SetIndexBuffer (7,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);
В функции OnCalculate () произведем проверку размера доступной истории для расчета используемых индикаторов, определим количество копируемых значений используемых индикаторов и определим стартовую позицию расчета индикатора:
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;
}
Переменную bars_calculated определим как глобальную int bars_calculated=0; в свойствах индикатора.
Далее произведем копирование из буферов используемых индикаторов в массивы буферов нашего индикатора:
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);
Здесь FillArrayFromMABuffer и FillArrayFromPSARBuffer – пользовательские функции, определенные вне функции OnCalculate ():
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
bool FillArrayFromPSARBuffer (
double &sar_buffer [], // индикаторный буфер значений Parabolic SAR
int ind_handle, // хэндл индикатора iSAR
int amount // количество копируемых значений
)
{
ResetLastError ();
if (CopyBuffer (ind_handle,0,0,amount, sar_buffer) <0)
{
return (false);
}
return (true);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
bool FillArrayFromMABuffer (
double &values [], // индикаторный буфер значений Moving Average
int shift, // смещение
int ind_handle, // хэндл индикатора iMA
int amount // количество копируемых значений
)
{
ResetLastError ();
if (CopyBuffer (ind_handle,0, -shift, amount, values) <0)
{
return (false);
}
return (true);
}
Далее в функции OnCalculate () заполним буфера индикатора данными и цветом:
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 [],