//+------------------------------------------------------------------+ //| Flat_Ind_v01.mq4 | //| нач. 11/04/2016 | //+------------------------------------------------------------------+ #property copyright "Inkov Evgeni" #property link "ew123@mail.ru" //+------------------------------------------------------------------+ #property version "1.00" #property strict #property indicator_chart_window //+------------------------------------------------------------------+ #property indicator_buffers 3 //+------------------------------------------------------------------+ input ENUM_TIMEFRAMES TF = PERIOD_CURRENT; input int proc_deviation = 30; input color clr = clrPaleTurquoise; //+------------------------------------------------------------------+ double buf [1000]; double buf1[1000]; double buf2[1000]; //+------------------------------------------------------------------+ bool Bar_2 =true; int n=1; string pref="PL_"; int bar_pereschet=-1; int put_buf1=true; //+------------------------------------------------------------------+ int OnInit() { pref=pref+str_TF(TF)+"_"; IndicatorShortName("Flat_Ind (P="+IntegerToString(proc_deviation)+"% TF="+str_TF(TF)+")"); IndicatorBuffers(3); SetIndexBuffer(0, buf1); SetIndexStyle(0, DRAW_NONE); ArrayInitialize(buf1,0); SetIndexBuffer(1, buf2); SetIndexStyle(1, DRAW_NONE); ArrayInitialize(buf2,0); SetIndexBuffer(2, buf); SetIndexStyle(2, DRAW_NONE); ArrayInitialize(buf,0); bar_pereschet=-1; return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { remove_objects(pref); } //+------------------------------------------------------------------+ 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 k=0; // переключатель буферов if (rates_total!=prev_calculated || bar_pereschet==-1) { n=MathMin(Bars,1000)-2; ArrayInitialize(buf ,0); ArrayInitialize(buf1,0); ArrayInitialize(buf2,0); remove_objects(pref); } else { n=bar_pereschet; if (put_buf1)k++; for(int i=n;i>=0;i--) { buf [i]=0; if (put_buf1) buf1[i]=0; else buf2[i]=0; } if (put_buf1) opred_begin_Flat_Rect(buf1); else opred_begin_Flat_Rect(buf2); } //.................................. bar_pereschet=-1; double t=0; // результат измерения девиации int beg=0; // бар начала Flat_Rect // определить девиацию баров в Flat_Rect (t>0 - бар принадлежит Flat_Rect) for(int i=n-1;i>=0;i--) { if (beg==0) { t=Check_2_Bar(i+1,i); if (t>0) { beg=i+1; bar_pereschet=beg; k++; } } else { t=Check_2_Bar(beg,i); if (t==0)beg=0; } //..................... // распределить инф. между буферами if (MathMod(k,2)==0) { put_buf1=true; buf1[i]=t; buf2[i]=0; } else { put_buf1=false; buf1[i]=0; buf2[i]=t; } buf[i]=t; } //............................. if (!Bar_2) for(int i=n-2;i>=2;i--) //убрать одиночные if (buf[i-1]==0 && buf[i]>0 && buf[i+1]==0) { buf [i]=0.0; buf1[i]=0.0; buf2[i]=0.0; } //............................. // сформировать прямоугольники For_Rect(buf1); For_Rect(buf2); //............................. return(rates_total); } //+------------------------------------------------------------------+ void opred_begin_Flat_Rect(double& BUF[]) { if (BUF[2]==0 && BUF[1]>0 && BUF[1]==0) { string name=pref+TimeToStr(iTime(NULL,TF,1),TIME_DATE)+"_"+TimeToStr(iTime(NULL,TF,1),TIME_MINUTES); if (ObjectFind(name)>=0)ObjectDelete(name); } } //--------------------------- void For_Rect(double& BUF[]) { for(int i=n-1;i>=0;i--) // добавить левый бар в каждой Flat_Rect if (BUF[i+1]==0 && BUF[i]>0) { BUF[i+1]=BUF[i]; buf[i+1]=buf[i]; } //............................. int b=0; for(int i=n;i>=0;i--) { // найти начало и конец Flat_Rect if (BUF[i+1]==0 && BUF[i]==0)b=0; if (BUF[i+1]==0 && BUF[i]>0)b=i; if (b>0 && BUF[i+1]>0) // вывести прямоугольник if (i>0) { if (BUF[i]==0) { Out_rect(b,i+1); b=0; } } else if (BUF[0]>0) Out_rect(b,0); else Out_rect(b,1); } } //--------------------------------- double Check_2_Bar(int l,int r) { // - по всем барам между левым(l) и правым (r) опред. параметры среднего бара // - проверить, что все бары Flat_Rect по разбросу соответствуют среднему бару // если нет, то новый бар не входит в Flat_Rect //................................. // найти параметры среднего бара double Sum_H=0.0,Sum_L=0.0; for(int i=l;i>=r;i--) { Sum_H+=iHigh(NULL,TF,i); Sum_L+=iLow(NULL,TF,i); } double H_s =Sum_H/(l-r+1); double L_s =Sum_L/(l-r+1); double HL_s=(H_s-L_s)/Point; if (HL_s<1.0)return(0.0); // т.к. нулевой средний бар //............................. // определить разброс по High double Max_H=iHigh(NULL,TF,iHighest(NULL,TF,MODE_HIGH,l-r+1,r)); double Min_H=iHigh(NULL,TF,iLowest (NULL,TF,MODE_HIGH,l-r+1,r)); double d_Hr=MathAbs(Max_H-H_s)/Point; double d_Hl=MathAbs(Min_H-H_s)/Point; double Hr=d_Hr/HL_s; double Hl=d_Hl/HL_s; double maxH=MathMax(Hr,Hl)*100.0; if (maxH>proc_deviation)return(0); //.......................... // определить разброс по Low double Max_L=iLow (NULL,TF,iHighest(NULL,TF,MODE_LOW, l-r+1,r)); double Min_L=iLow (NULL,TF,iLowest (NULL,TF,MODE_LOW, l-r+1,r)); double d_Lr=MathAbs(Max_L-L_s)/Point; double d_Ll=MathAbs(Min_L-L_s)/Point; double Lr=d_Lr/HL_s; double Ll=d_Ll/HL_s; double maxL=MathMax(Lr,Ll)*100.0; if (maxL>proc_deviation)return(0); //............................... double max=NormalizeDouble(MathMax(maxH,maxL),1); return(max); } //--------------------------------- void Out_rect(int B,int E) { if (TF>0 && Period()>TF)return; //........................... string name=pref+TimeToStr(iTime(NULL,TF,B),TIME_DATE)+"_"+TimeToStr(iTime(NULL,TF,B),TIME_MINUTES); double H=iHigh(NULL,TF,iHighest(NULL,TF,MODE_HIGH,B-E+1,E)); double L=iLow (NULL,TF,iLowest (NULL,TF,MODE_LOW, B-E+1,E)); datetime t_E=Time[0]; if (E>0)t_E=Time[iBarShift(NULL,0,iTime(NULL,TF,E-1))+1]; if (ObjectFind(name)<0)ObjectCreate(name,OBJ_RECTANGLE,0,iTime(NULL,TF,B),H,t_E,L); ObjectSet(name,OBJPROP_TIME1,iTime(NULL,TF,B)); ObjectSet(name,OBJPROP_PRICE1,H); ObjectSet(name,OBJPROP_TIME2,t_E); ObjectSet(name,OBJPROP_PRICE2,L); ObjectSet(name,OBJPROP_COLOR,clr); } //------------------------------------ void remove_objects(string PreName) { string Obj_Name,Head; for(int k=ObjectsTotal()-1; k>=0; k--) { Obj_Name=ObjectName(k); Head=StringSubstr(Obj_Name,0,StringLen(PreName)); if (Head==PreName)ObjectDelete(Obj_Name); } } //---------------------------------------------- string str_TF(int n1) { if (n1==0)n1=Period(); switch(n1) { case PERIOD_M1: return ("M1 "); case PERIOD_M5: return ("M5"); case PERIOD_M15: return ("M15"); case PERIOD_M30: return ("M30"); case PERIOD_H1: return ("H1"); case PERIOD_H4: return ("H4"); case PERIOD_D1: return ("D1"); case PERIOD_W1: return ("W1"); case PERIOD_MN1: return ("MN1"); } return("TF?"); } //----------------------------