/*+------------------------------------------------------------------+ | Demark_Trends.mq4 | | Alor Traders Team (c) | | http://www.alorbroker.ru | | Что нового: | | + индикатор переведен на MQL5 | | + полностью переработан движек индикатора, теперь я использую | | только индикаторные буферы, которых стало 12 | | + пробои трендов вместе с целями отображаются в режиме real-time | | + исправлена система построения проекторов, они теперь берутся по| | последней оттяжке | //+------------------------------------------------------------------+*/ #property copyright "Pavel Trofimov(c) special for Alor traders Team" #property link "e-mail: trofimovpp@mail.ru" #property version "1.002" #property description "" #property strict #property indicator_chart_window #property indicator_buffers 12 #property indicator_plots 12 #property indicator_color1 clrRed //цвет нижних точек Демарка 1 уровня #property indicator_type1 DRAW_ARROW #property indicator_color2 clrBlue //цвет верхних точек Демарка 1 уровня #property indicator_type2 DRAW_ARROW #property indicator_color3 clrRed //цвет нижних точек Демарка 2 уровня #property indicator_type3 DRAW_ARROW #property indicator_color4 clrBlue //цвет верхних точек Демарка 2 уровня #property indicator_type4 DRAW_ARROW #property indicator_color5 clrRed //цвет нижних точек Демарка 3 уровня #property indicator_type5 DRAW_ARROW #property indicator_color6 clrBlue //цвет верхних точек Демарка 3 уровня #property indicator_type6 DRAW_ARROW #property indicator_color7 clrGreen //цвет восходящего тренда Демарка 1 уровня #property indicator_type7 DRAW_LINE #property indicator_color8 clrRed //цвет нисходящего тренда Демарка 1 уровня #property indicator_type8 DRAW_LINE #property indicator_color9 clrGreen //цвет восходящего тренда Демарка 2 уровня #property indicator_type9 DRAW_LINE #property indicator_color10 clrRed //цвет нисходящего тренда Демарка 2 уровня #property indicator_type10 DRAW_LINE #property indicator_color11 clrGreen //цвет восходящего тренда Демарка 3 уровня #property indicator_type11 DRAW_LINE #property indicator_color12 clrRed //цвет нисходящего тренда Демарка 3 уровня #property indicator_type12 DRAW_LINE //--- input parameters ----------------------------------------------------------------------------+ input int N1=3;//Значение N1 точек Демарка. Если N1=0, то эти ТД точки не отображаются input int N2=5;//Значение N2 точек Демарка. Если N2=0, то эти ТД точки не отображаются input int N3=8;//Значение N3 точек Демарка. Если N3=0, то эти ТД точки не отображаются //-------------------------------------------------------------------------------------------------+ input bool ShowTargetLine1UpTrends=true; //Отображать цели пробоя ап-тренда 1 уровня input bool ShowTargetLine1DownTrends=true; //Отображать цели пробоя даун-тренда 1 уровня input bool ShowTargetLine2UpTrends=true; //Отображать цели пробоя ап-тренда 2 уровня input bool ShowTargetLine2DownTrends=true; //Отображать цели пробоя даун-тренда 2 уровня input bool ShowTargetLine3UpTrends=true; //Отображать цели пробоя ап-тренда 3 уровня input bool ShowTargetLine3DownTrends=true; //Отображать цели пробоя даун-тренда 3 уровня //-------------------------------------------------------------------------------------------------+ input int UTPriceProjector_Width=2;//Толщина линии ценового проектора при пробое Ап-тренда input int UTPriceProjector_Style=0;//Стиль линии ценового проектора при пробое Ап-тренда input color UTPriceProjector_Color=clrGreen;//Цвет линии ценового проектора при пробое Ап-тренда //-------------------------------------------------------------------------------------------------+ input int DTPriceProjector_Width=2;//Толщина линии ценового проектора при пробое Даун-тренда input int DTPriceProjector_Style=0;//Стиль линии ценового проектора при пробое Даун-тренда input color DTPriceProjector_Color=clrRed;//Цвет линии ценового проектора при пробое Даун-тренда //--- end input parameters ------------------------------------------------------------------------+ //--- Буферы Верхних и нижних точек double TDHighPoints_N1[]; double TDLowPoints_N1[]; double TDHighPoints_N2[]; double TDLowPoints_N2[]; double TDHighPoints_N3[]; double TDLowPoints_N3[]; double Lvl1UpTrend[]; double Lvl1DownTrend[]; double Lvl2UpTrend[]; double Lvl2DownTrend[]; double Lvl3UpTrend[]; double Lvl3DownTrend[]; //--- Прочие глобальные переменные int qBars; //число баров на графике string Str1="", Str2="", Str3="";//глобальные перменные квалификаторов прорыва string Session;//имя сессии, для именования объектов индикатора double High[], Low[], Close[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(void) { int code1=161,code2=164,code3=174;//О! Кружочки )) string Rem1="UpTDPoint",Rem2="LowTDPoint";//марки на точки //--- indicator buffers mapping ----------------------+ for(int n=0;n<=1;n++) PlotIndexSetInteger(n,PLOT_ARROW,code1);//выставляем метки для ТД точек каждого буфера for(int n=2;n<=3;n++) PlotIndexSetInteger(n,PLOT_ARROW,code2); for(int n=4;n<=5;n++) PlotIndexSetInteger(n,PLOT_ARROW,code3); SetIndexBuffer(0,TDHighPoints_N1,INDICATOR_DATA); SetIndexBuffer(1,TDLowPoints_N1,INDICATOR_DATA); SetIndexBuffer(2,TDHighPoints_N2,INDICATOR_DATA); SetIndexBuffer(3,TDLowPoints_N2,INDICATOR_DATA); SetIndexBuffer(4,TDHighPoints_N3,INDICATOR_DATA); SetIndexBuffer(5,TDLowPoints_N3,INDICATOR_DATA); SetIndexBuffer(6,Lvl1UpTrend,INDICATOR_DATA); SetIndexBuffer(7,Lvl1DownTrend,INDICATOR_DATA); SetIndexBuffer(8,Lvl2UpTrend,INDICATOR_DATA); SetIndexBuffer(9,Lvl2DownTrend,INDICATOR_DATA); SetIndexBuffer(10,Lvl3UpTrend,INDICATOR_DATA); SetIndexBuffer(11,Lvl3DownTrend,INDICATOR_DATA); // Устанавливаем доступ к индикаторным массивам как к таймсериям, т.е. [0]-это последний бар ArraySetAsSeries(TDHighPoints_N1,true); ArraySetAsSeries(TDLowPoints_N1,true); ArraySetAsSeries(TDHighPoints_N2,true); ArraySetAsSeries(TDLowPoints_N2,true); ArraySetAsSeries(TDHighPoints_N3,true); ArraySetAsSeries(TDLowPoints_N3,true); ArraySetAsSeries(Lvl1UpTrend,true); ArraySetAsSeries(Lvl1DownTrend,true); ArraySetAsSeries(Lvl2UpTrend,true); ArraySetAsSeries(Lvl2DownTrend,true); ArraySetAsSeries(Lvl3UpTrend,true); ArraySetAsSeries(Lvl3DownTrend,true); ArraySetAsSeries(High,true); ArraySetAsSeries(Low,true); ArraySetAsSeries(Close,true); for(int n=0;n<=5;n=n+2) PlotIndexSetString(n,PLOT_LABEL,Rem1); for(int n=1;n<=5;n=n+2) PlotIndexSetString(n,PLOT_LABEL,Rem2); //----------------------------------------------------+ //--- Инициализация прочих глобальных переменных -----+ qBars=Bars(Symbol(),PERIOD_CURRENT)-1;//помним, что массивы нумеруются с 0 MathSrand(GetTickCount()); //инициализация датчика случайных чисел Session=IntegerToString(MathRand());//присваиваем имени сессии псевдослучайные число. //----------------------------------------------------+ return(INIT_SUCCEEDED); } /*+------------------------------------------------------------------+ | Custom indicator deinitialization function | +------------------------------------------------------------------+*/ void OnDeinit(const int reason){ switch (reason){ case 0://REASON_PROGRAM: DeleteIndicatorObjects(); break; case 1:// REASON_REMOVE: DeleteIndicatorObjects(); break; case 2://REASON_RECOMPILE: DeleteIndicatorObjects(); break; case 3://REASON_CHARTCHANGE: DeleteIndicatorObjects(); break; case 4://REASON_CHARTCLOSE: DeleteIndicatorObjects(); break; case 5://REASON_PARAMETERS: DeleteIndicatorObjects(); break; case 6://REASON_ACCOUNT: DeleteIndicatorObjects(); break; case 7://REASON_TEMPLATE: DeleteIndicatorObjects(); break; case 8://REASON_INITFAILED: DeleteIndicatorObjects(); break; case 9://REASON_CLOSE: DeleteIndicatorObjects(); break; } } //+------------------------------------------------------------------+ //--->Необходимо для корректной отладки под Win7 class CFix { } ExtFix; //---> int OnCalculate (const int rates_total, // размер входных таймсерий const int prev_calculated, // обработано баров на предыдущем вызове const datetime &time[], // Time const double &open[], // Open const double &high[], // High const double &low[], // Low const double &close[], // Close const long &tick_volume[], // Tick Volume const long &volume[], // Real Volume const int &spread[] // Spread ){ //--- Объявление переменных int UpT=0,DownT=0; ResetLastError();//сбрасываем сообщения об ошибках if (N1>0) { //--- Верхние ТД точки для N1 Filling_Up_TDPoints_Array(N1,TDHighPoints_N1); //--- Нижние ТД точки для N1 Filling_Low_TDpoints_Array(N1,TDLowPoints_N1); //--- Trend Lines Level 1 UpT=Filling_Up_Trends_Array(N1,TDLowPoints_N1,Lvl1UpTrend); PlotIndexSetInteger(6,PLOT_DRAW_BEGIN,UpT); DownT=Filling_Down_Trends_Array(N1,TDHighPoints_N1,Lvl1DownTrend); PlotIndexSetInteger(7,PLOT_DRAW_BEGIN,DownT); } if (N2>0) { //--- Верхние ТД точки для N2 Filling_Up_TDPoints_Array(N2,TDHighPoints_N2); //--- Нижние ТД точки для N2 Filling_Low_TDpoints_Array(N2,TDLowPoints_N2); //--- Trend Lines Level 2 UpT=Filling_Up_Trends_Array(N2,TDLowPoints_N2,Lvl2UpTrend); PlotIndexSetInteger(8,PLOT_DRAW_BEGIN,UpT); DownT=Filling_Down_Trends_Array(N2,TDHighPoints_N2,Lvl2DownTrend); PlotIndexSetInteger(9,PLOT_DRAW_BEGIN,DownT); } if (N3>0) { //--- Верхние ТД точки для N3 Filling_Up_TDPoints_Array(N3,TDHighPoints_N3); //--- Нижние ТД точки для N3 Filling_Low_TDpoints_Array(N3,TDLowPoints_N3); //--- TD Trend Lines Level 3 UpT=Filling_Up_Trends_Array(N3,TDLowPoints_N3,Lvl3UpTrend); PlotIndexSetInteger(10,PLOT_DRAW_BEGIN,UpT); DownT=Filling_Down_Trends_Array(N3,TDHighPoints_N3,Lvl3DownTrend); PlotIndexSetInteger(11,PLOT_DRAW_BEGIN,DownT); } return(rates_total); } /*+------------------------------------------------------------------+ | Custom indicator user functions | +------------------------------------------------------------------+*/ /*+------------------------------------------------------------------+ | Заполнение массива верхних ТД точек | +------------------------------------------------------------------+*/ /* Основное изменение здесь следующее: ищутся все опорные точки, как у фракталов Вильямса и все они заносятся в буфер, но если условие с углом наклона не будет выполнятся для тренда (это уже при заполнении массива линий тренда), то тренд не будет отрисован*/ void Filling_Up_TDPoints_Array(int N, double &Up_TDPoints_Array[]){ int tmpTD=0; //используется для временного хранения результата поиска ТД точек int k=0;//временный счетчик, хранит номер предпоследней ТД точки, чтобы не делать отдельной процедуры по ее поиску. for (int i=qBars-N;i>=N;i--){ tmpTD=NumberTDHighPoint(i,N); if(tmpTD!=0) Up_TDPoints_Array[i]=iHigh(Symbol(),PERIOD_CURRENT, tmpTD);//заносим в буфер значения хая!!! else Up_TDPoints_Array[i]=0; } } /*+------------------------------------------------------------------+ | Заполнение массива нижних ТД точек | +------------------------------------------------------------------+*/ void Filling_Low_TDpoints_Array(int N, double &Low_TDPoints_Array[]){ int tmpTD=0; //используется для временного хранения результата поиска ТД точек int k=0;//временный счетчик, хранит номер предпоследней ТД точки, чтобы не делать отдельной процедуры по ее поиску. for (int i=qBars-N;i>=N;i--){ tmpTD=NumberTDLowPoint(i,N); if(tmpTD!=0) Low_TDPoints_Array[i]=iLow(Symbol(),PERIOD_CURRENT,tmpTD);//заносим в буфер значение лоя else Low_TDPoints_Array[i]=0; } } /*+--------------------------------------------------------------+ | Рекурсивная проверка на условие Демарка для верхних ТД точек | +--------------------------------------------------------------+*/ int NumberTDHighPoint(int tmpI,int tmpN){ if((iHigh(Symbol(),PERIOD_CURRENT, tmpI)>iHigh(Symbol(),PERIOD_CURRENT,(tmpI-tmpN)) && (iHigh(Symbol(),PERIOD_CURRENT,tmpI)>=iHigh(Symbol(),PERIOD_CURRENT,(tmpI+tmpN))))) { if(tmpN>1) return (NumberTDHighPoint(tmpI,tmpN-1)); } else return(0); return(tmpI); } /*+-------------------------------------------------------------+ | Рекурсивная проверка на условие Демарка для нижних ТД точек | +-------------------------------------------------------------+*/ int NumberTDLowPoint(int tmpI,int tmpN){ if((iLow(Symbol(),PERIOD_CURRENT,tmpI)1) return (NumberTDLowPoint(tmpI,tmpN-1)); } else return(0); return(tmpI); } /*+-------------------------------------------------------------+ | Заполнение массива точек для Up-трендов | +-------------------------------------------------------------+*/ int Filling_Up_Trends_Array(int N,double &TDLowPointsArray[],double &UpTrend[]){ int k,n,temp_TD1, temp_TD2; double temp_TD; k=N-1;temp_TD=0;temp_TD1=0;temp_TD2=0;//обнуляем переменные для нового цикла while ((k<=(qBars-N))&&(temp_TD2==0)){ temp_TD=TDLowPointsArray[k];//эту переменную ввел для оптимизации вычислений, чтобы не проводить эти вычисления в каждом условии ниже if (temp_TD>0){ if (temp_TD1==0)temp_TD1=k;//temp_TD;//ловим индекс ТД1 точки в буфере else if ((temp_TD2==0)&&(temp_TD<=TDLowPointsArray[temp_TD1])&&additional_condition_high_points(k,temp_TD1,N)) temp_TD2=k; } k++; } if (temp_TD2!=0) {//если есть вторая точка удовлетворяющая условиям заносим в буфер обе n=LowPointDimension(temp_TD2); if (n<=N){//если размерности точек одинаковы, то заносим в буфер обе Lvl1UpTrend[temp_TD2]=TDLowPointsArray[temp_TD2]; Lvl1UpTrend[temp_TD1]=TDLowPointsArray[temp_TD1]; } else Lvl1UpTrend[temp_TD1]=TDLowPointsArray[temp_TD1];//иначе только одну } else Lvl1UpTrend[temp_TD1]=TDLowPointsArray[temp_TD1];//иначе только одну return(temp_TD2); } /*+-------------------------------------------------------------+ | Заполнение массива точек для Up-трендов | +-------------------------------------------------------------+*/ int Filling_Down_Trends_Array(int N,double &TDHighPointsArray[],double &DownTrend[]){ int k, n, temp_TD1, temp_TD2; double temp_TD; k=N-1;temp_TD=0;temp_TD1=0;temp_TD2=0;//обнуляем переменные для нового цикла while ((k<=(qBars-N))&&(temp_TD2==0)){ temp_TD=TDHighPointsArray[k];//эту переменную ввел для оптимизации вычислений, чтобы не проводить эти вычисления в каждом условии ниже if (temp_TD>0){ if (temp_TD1==0)temp_TD1=k;//ловим индекс ТД1 точки в буфере (первая назад от текущего бара) else if ((temp_TD2==0)&&(temp_TD>=TDHighPointsArray[temp_TD1])&&additional_condition_low_points(k,temp_TD1,N)) temp_TD2=k; } k++; } if (temp_TD2!=0) {//если есть вторая точка удовлетворяющая условиям Демарка заносим в буфер обе n=HighPointDimension(temp_TD2); if (n<=N){//если размерности точек одинаковы заносим в буфер обе Lvl1UpTrend[temp_TD2]=TDHighPointsArray[temp_TD2]; Lvl1UpTrend[temp_TD1]=TDHighPointsArray[temp_TD1]; } else Lvl1UpTrend[temp_TD1]=TDHighPointsArray[temp_TD1];//иначе только одну } else Lvl1UpTrend[temp_TD1]=TDHighPointsArray[temp_TD1];//иначе только одну return(temp_TD2); } /*+------ Дополнительное условие истинности верхней ТД точки: -------+ | Истинность опорного ценового максимума вызывает сомнения, | | если цена закрытия на следующий день после его регистрации | | выше расчетного значения скорости падения TD-линии для этого дня.| +------------------------------------------------------------------+ */ bool additional_condition_high_points (int tmp_k, int tmp_i, int tmp_N){//к индекс ТД2 точки, i - индекс текущей ТД1 точки bool A=true; //временная булева переменная int n=tmp_i-1; double m=0; if (tmp_k!=tmp_i) m=(iHigh(Symbol(),PERIOD_CURRENT,tmp_k)-iHigh(Symbol(),PERIOD_CURRENT,tmp_i))/(tmp_k-tmp_i);//угловой коэффициент наклона нисходящей линии тренда else m=0; while ((n>=tmp_i-tmp_N)&&A){ A=(iClose(Symbol(),PERIOD_CURRENT, n)<(m*(n-tmp_i)+iHigh(Symbol(),PERIOD_CURRENT,tmp_i))); //сравниваем значение цены закрытия и точку на прямой линии тренда, если ниже ништяки - точка определена верно. n--; } if (A) return(true); else return(false); } /*+-------------------------------------------------------------+ | Дополнительное условие истинности нижней ТД точки: | +-------------------------------------------------------------+*/ bool additional_condition_low_points (int tmp_k, int tmp_i, int tmp_N){ bool A=true; int n=tmp_i-1; double m=0; if (tmp_k!=tmp_i) m=(iLow(Symbol(),PERIOD_CURRENT,tmp_k)-iLow(Symbol(),PERIOD_CURRENT,tmp_i))/(tmp_k-tmp_i);//угловой коэффициент наклона восходящей линии тренда else m=0; while ((n>=tmp_i-tmp_N)&&A){ A=(iClose(Symbol(),PERIOD_CURRENT,n)>(m*(n-tmp_i)+iLow(Symbol(),PERIOD_CURRENT,tmp_i))); n--; } if (A) return (true); else return(false); } /*+-------------------------------------------------------------+ | Определение размерности верхней ТД точки | +-------------------------------------------------------------+*/ int HighPointDimension (int k){ int n=1; while (((k+n)<=qBars)&&(iHigh(Symbol(),PERIOD_CURRENT,k)>iHigh(Symbol(),PERIOD_CURRENT,k-n))&&(iHigh(Symbol(),PERIOD_CURRENT,k)>iHigh(Symbol(),PERIOD_CURRENT,k+n))) n++; return(n); } /*+-------------------------------------------------------------+ | Определение размерности нижней ТД точки | +-------------------------------------------------------------+*/ int LowPointDimension (int k){ int n=1; while (((k+n)<=qBars)&&(iLow(Symbol(),PERIOD_CURRENT,k)= 0; obj--){ string objname = ObjectName(0,obj,0,-1); if (StringFind(objname, Session)>=0) ObjectDelete(0,objname); } //Вторая очистка. Чистим по именам обеъктов for(int obj=obj_total-1;obj>=0;obj--){ string objname=ObjectName(0,obj,0,-1); if (StringFind(objname,"Price Projector")>=0) ObjectDelete(0,objname);//ценовые проекторы } } /*+-------------------------------------------------------------+ | Свой массив тайм-серия для лоев | +-------------------------------------------------------------+*/ double iLow(string symbol,ENUM_TIMEFRAMES timeframe,int index) { double low=0; ArraySetAsSeries(Low,true); int copied=CopyLow(symbol,timeframe,0,Bars(symbol,timeframe),Low); if(copied>0 && index0 && index0 && index