#property copyright "Alexandr Sokolov" #property link "https://www.mql5.com/en/users/asokolov7" #property version "1.00" #property description "Market Change Cycles" #property indicator_separate_window #property indicator_buffers 9 #property indicator_plots 4 //--- Первое графическое построение индикатора ---------------------- #property indicator_style1 STYLE_SOLID #property indicator_label1 "K line" //--- Второе графическое построение индикатора ---------------------- #property indicator_type2 DRAW_LINE //Тип графического построения №2 #property indicator_style2 STYLE_DOT //Стиль линии графического построения №2 #property indicator_width2 1 //Толщина линии графического построения №2 #property indicator_color2 clrBlack //Цвет линии графического построения №2 #property indicator_label2 "D line" //Всплывающее описание линии графического построения №2 //--- Третье графическое построение индикатора ---------------------- #property indicator_type3 DRAW_LINE #property indicator_style3 STYLE_SOLID #property indicator_width3 1 #property indicator_color3 clrBlue #property indicator_label3 "High value" //--- Четвёртое графическое построение индикатора ------------------- #property indicator_type4 DRAW_LINE #property indicator_style4 STYLE_SOLID #property indicator_width4 1 #property indicator_color4 clrBlue #property indicator_label4 "Low value" //--- Буферы -------------------------------------------------------- double KV[], CI[], //Для основного значения индикатора DV[], //Для сигнальной линии индикатора VHigh[], //Для высшей линии индикатора VLow[], //Для низшей линии индикатора Open[], High[], Low[], Close[]; //Для получения цен //--- Статические переменные ---------------------------------------- static double vhigh, //Для передачи высшей цены High в рамках периода vlow; //Для передачи низшей цены Low в рамках периода //--- ВП для указания режима индикатора ----------------------------- enum I_MODE { m1, //Difference m2 //Ratio }; //--- ВП для выбора визуализируемых параметров ---------------------- enum I_SHOW { s1, //Show s2 //Not show }; //--- Входные параметры --------------------------------------------- input I_MODE mode = m1; //Mode input uint kperiod = 5; //K period input I_SHOW sline = s1; //Signal line input uint dperiod = 3; //D period input I_SHOW levels = s2; //Levels input double ulevel = 80, //Upper level llevel = 20; //Lower level //------------------------------------------------------------------------------------------------- int OnInit() { //--- Проверка на корректность входных параметров ----------------- if(kperiod < 1) {Print("Main period can not be less than 1"); return(INIT_PARAMETERS_INCORRECT);}; if(dperiod < 1) {Print("Signal period can not be less than 1"); return(INIT_PARAMETERS_INCORRECT);}; if(mode == m2 && levels == s1 && (ulevel > 100 || ulevel < 0)) {Print("Upper level cannot be greater than 100 or less than 0"); return(INIT_PARAMETERS_INCORRECT);}; if(mode == m2 && levels == s1 && (llevel > 100 || llevel < 0)) {Print("Lower level cannot be more than 100 or less than 0"); return(INIT_PARAMETERS_INCORRECT);}; //--- Устанавливаем свойства первого графического построения в зависимости от выбранного режима индикатора PlotIndexSetInteger(0,PLOT_DRAW_TYPE,(mode == m1 ? DRAW_COLOR_HISTOGRAM : DRAW_LINE)); //Тип первого графического построения PlotIndexSetInteger(0,PLOT_LINE_WIDTH,(mode == m1 ? 2 : 1)); //Толщина линии первого графического построения PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,(mode == m1 ? 2 : 1)); //Количество цветов линии первого графического построения PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,(mode == m1 ? clrLime : clrBlack)); //Первый цвет линии первого графического построения if(mode == m1) {PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrRed);}; //Второй цвет линии первого графического построения //--- Нюансы визуализации ----------------------------------------- string window_name = "MCC " + (mode == m1 ? "D(" : "R(") + (sline == s1 ? (string)kperiod+","+(string)dperiod : (string)kperiod) + ")"; IndicatorSetString(INDICATOR_SHORTNAME,window_name); IndicatorSetInteger(INDICATOR_DIGITS,(mode == m1 ? 0 : 2)); if(levels == s1) { IndicatorSetInteger(INDICATOR_LEVELS,2); IndicatorSetDouble(INDICATOR_LEVELVALUE,0,ulevel); IndicatorSetDouble(INDICATOR_LEVELVALUE,1,llevel); }; if(mode == m2) { IndicatorSetDouble(INDICATOR_MAXIMUM,100); IndicatorSetDouble(INDICATOR_MINIMUM,0); }; PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,kperiod); if(sline == s1) {PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,kperiod+dperiod);}; if(mode == m1) {PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,kperiod-1);}; if(mode == m1) {PlotIndexSetInteger(3,PLOT_DRAW_BEGIN,kperiod-1);}; //--- Привязываем некоторые буферы к графическим построениям и указываем их предназначение SetIndexBuffer(0,KV,INDICATOR_DATA); SetIndexBuffer((mode == m1 ? 1 : 2),CI,(mode == m1 ? INDICATOR_COLOR_INDEX : INDICATOR_CALCULATIONS)); SetIndexBuffer((mode == m1 ? 2 : 1),DV,(sline == s1 ? INDICATOR_DATA : INDICATOR_CALCULATIONS)); SetIndexBuffer(3,VHigh,(mode == m1 ? INDICATOR_DATA : INDICATOR_CALCULATIONS)); SetIndexBuffer(4,VLow,(mode == m1 ? INDICATOR_DATA : INDICATOR_CALCULATIONS)); SetIndexBuffer(5,Open,INDICATOR_CALCULATIONS); SetIndexBuffer(6,High,INDICATOR_CALCULATIONS); SetIndexBuffer(7,Low,INDICATOR_CALCULATIONS); SetIndexBuffer(8,Close,INDICATOR_CALCULATIONS); //--- Указываем направление индексации буферов -------------------- ArraySetAsSeries(KV,true); ArraySetAsSeries(CI,true); ArraySetAsSeries(DV,true); ArraySetAsSeries(VHigh,true); ArraySetAsSeries(VLow,true); ArraySetAsSeries(Open,true); ArraySetAsSeries(High,true); ArraySetAsSeries(Low,true); ArraySetAsSeries(Close,true); //----------------------------------------------------------------- return(INIT_SUCCEEDED); } //------------------------------------------------------------------------------------------------- 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[]) { //--- 1) Копируем цены -------------------------------------------- int count = rates_total - prev_calculated, copied = 0; if(count < (int)kperiod) {count = (int)kperiod;}; if(mode == m1) {copied = CopyOpen(_Symbol,PERIOD_CURRENT,0,count,Open); if(copied != count) {return(0);};}; copied = CopyHigh(_Symbol,PERIOD_CURRENT,0,count,High); if(copied != count) return(0); copied = CopyLow(_Symbol,PERIOD_CURRENT,0,count,Low); if(copied != count) return(0); copied = CopyClose(_Symbol,PERIOD_CURRENT,0,count,Close); if(copied != count) return(0); //--- 2) Инициализируем буферы ------------------------------------ if(prev_calculated == 0) { ArrayInitialize(KV,EMPTY_VALUE); ArrayInitialize(CI,EMPTY_VALUE); ArrayInitialize(DV,EMPTY_VALUE); ArrayInitialize(VHigh,EMPTY_VALUE); ArrayInitialize(VLow,EMPTY_VALUE); }; //--- 3) Расчитываем значения ------------------------------------- int limit = rates_total - prev_calculated - (int)kperiod; if(limit < 0) {limit = 0;}; for(int i = limit; i >= 0; i--) { KValues(i); KV[i] = (mode == m1 ? (Close[i] - Open[i+(int)kperiod-1]) * MathPow(10,_Digits) : 100 * ((Close[i]-vlow) / (vhigh-vlow))); CI[i] = (mode == m1 ? (KV[i] >= 0 ? (KV[i] > KV[i+1] ? 0 : 1) : (KV[i] < KV[i+1] ? 0 : 1)) : EMPTY_VALUE); if(sline == s1 && (prev_calculated != 0 || (prev_calculated == 0 && i < limit - (int)dperiod))) {DV[i] = (mode == m1 ? DValue(i) * MathPow(10,_Digits) : DValue(i));} else {DV[i] = EMPTY_VALUE;}; VHigh[i] = (mode == m1 ? (vhigh - Open[i+(int)kperiod-1]) * MathPow(10,_Digits) : EMPTY_VALUE); VLow[i] = (mode == m1 ? (vlow - Open[i+(int)kperiod-1]) * MathPow(10,_Digits) : EMPTY_VALUE); }; //----------------------------------------------------------------- return(rates_total); } //--- Функция для получения максимального High и минимального Low в рамках периода ---------------- void KValues(int i) { vhigh = 0; vlow = High[i]; int limit = i + (int)kperiod; for(int a = i; a < limit; a++) { vhigh = (High[a] > vhigh ? High[a] : vhigh); vlow = (Low[a] < vlow ? Low[a] : vlow); }; } //--- Функция для расчёта сигнальной линии -------------------------------------------------------- double DValue(int i) { double value = 0; int limit = i + (int)dperiod; for(int a = i; a < limit; a++) { value += (mode == m1 ? Close[a] - Open[a+(int)kperiod-1] : KV[a]); }; //----------------------------------------------------------------- return(value/(int)dperiod); }