//+-----------------------------------------------------------------+ //| UtterFractals.mq5 | //| Copyright © 2011, RMM | //| rmm@nm.ru | //+------------------------------------------------------------------+ #property description "Utter Fractals" //---- author of the indicator #property copyright "Copyright © 2011, RMM" //---- link to the website of the author #property link "rmm@nm.ru" //---- indicator version #property version "1.00" //---- drawing the indicator in the main window #property indicator_chart_window //---- two buffers are used for calculation and drawing the indicator #property indicator_buffers 2 //---- two plots are used #property indicator_plots 2 //+----------------------------------------------+ //| Upper indicator drawing parameters | //+----------------------------------------------+ //---- drawing the indicator 1 as a symbol #property indicator_type1 DRAW_ARROW //---- green color is used for the indicator #property indicator_color1 Green //---- indicator 1 line width is equal to 1 #property indicator_width1 1 //---- displaying the indicator label #property indicator_label1 "Up Fractal" //+----------------------------------------------+ //| Lower indicator drawing parameters | //+----------------------------------------------+ //---- drawing the indicator 2 as a line #property indicator_type2 DRAW_ARROW //---- magenta color is used for the indicator #property indicator_color2 Magenta //---- indicator 2 line width is equal to 1 #property indicator_width2 1 //---- displaying the indicator label #property indicator_label2 "Down Fractal" //+----------------------------------------------+ //| Indicator input parameters | //+----------------------------------------------+ input uint QuantityOfBars_=1000; // History observation depth in bars input int UpLable=217; // Upper fractal symbol code input int DnLable=218; // Lower fractal symbol code //+----------------------------------------------+ //---- declaration of dynamic arrays that //---- will be used as indicator buffers double Up[]; double Dn[]; //---- declaration of global variables double Up_tmp; double Dn_tmp; int review=20; int StartBars; uint QuantityOfBars; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //---- initialization of global variables StartBars=6; QuantityOfBars=QuantityOfBars_; //---- set Up[] dynamic array as an indicator buffer SetIndexBuffer(0,Up,INDICATOR_DATA); //---- shifting the start of drawing the indicator 1 PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,StartBars); //---- indicator symbol PlotIndexSetInteger(0,PLOT_ARROW,UpLable); //---- indexing the elements in the buffer as timeseries ArraySetAsSeries(Up,true); //---- restriction to draw empty values for the indicator PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); //---- set Dn[] dynamic array as an indicator buffer SetIndexBuffer(1,Dn,INDICATOR_DATA); //---- shifting the start of drawing the indicator 2 PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,StartBars); //---- indicator symbol PlotIndexSetInteger(1,PLOT_ARROW,DnLable); //---- indexing the elements in the buffer as timeseries ArraySetAsSeries(Dn,true); //---- restriction to draw empty values for the indicator PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); //---- setting the format of accuracy of displaying the indicator IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //---- name for the data window and the label for sub-windows string short_name="UtterFractals"; IndicatorSetString(INDICATOR_SHORTNAME,short_name); //---- } //+------------------------------------------------------------------+ //| Check for the upper extremum presence | //+------------------------------------------------------------------+ bool ExistUp(uint index,const double &High[]) { //---- if(High[index+1]=High[index-1]) return(true); //---- return(false); } //+------------------------------------------------------------------+ //| Check for the lower extremum presence | //+------------------------------------------------------------------+ bool ExistDn(uint index,const double &Low[]) { //---- if(Low[index+1]>=Low[index] && Low[index]<=Low[index-1]) return(true); //---- return(false); } //+------------------------------------------------------------------+ //| Determining the pattern type in case of the extremum presence | //+------------------------------------------------------------------+ int IdentDualExtr(int index,const double &Open[],const double &Low[],const double &High[],const double &Close[]) { //---- int j,type=0; bool up_back=false,dn_back=false,up_forward=false,dn_forward=false,upres,dnres; string direction; //--- storing the bar, at which the lower extremum is found j=index; if(Open[index]Close[index]) direction="dn"; upres=ExistUp(j,High); dnres=ExistDn(j,Low); //--- preparing to move back to the past in history along the bars according to the review value while(jLow[index]) { if(High[j]>High[index]&&Open[index]>Close[index]){up_back=true; dn_back=false; direction="dn"; break;} if(High[j]Close[index]){up_back=false; dn_back=false; direction="dn"; break;} if(High[j]>High[index]&&Open[index]High[index]&&Open[index]==Close[index]){up_back=true; dn_back=false; direction="up"; break;} if(High[j]Close[index]){up_back=false; dn_back=true; direction="dn"; break;} if(Low[j]>Low[index]&&Low[j]Close[index]){up_back=false; dn_back=true; direction="dn"; break;} if(Low[j]Low[index]&&Low[j]Low[index]&&Open[index]==Close[index]){up_back=false; dn_back=true; direction="up"; break;} } } //--- storing the bar, at which the lower extremum is found j=index; //--- preparing to move forward in history along the bars according to the review value while(j>index-review) { //--- enlarging the move counter forward in history j--; if(upres && !dnres && High[j]>Low[index]) { if(High[j]>High[index]&&Open[index]>Close[index]){up_forward=true; dn_forward=false; direction="dn"; break;} if(High[j]Close[index]){up_forward=true; dn_forward=false; direction="dn"; break;} if(High[j]>High[index]&&Open[index]High[index]&&Open[index]==Close[index]){up_forward=true; dn_forward=false; direction="up"; break;} if(High[j]Close[index]){up_forward=false; dn_forward=true; direction="dn"; break;} if(Low[j]>Low [index]&&Open[index]>Close[index]){up_forward=false; dn_forward=false; direction="dn"; break;} if(Low[j]Low [index]&&Open[index]Low [index]&&Open[index]==Close[index]){up_forward=false; dn_forward=true; direction="up"; break;} } } if( up_back&& up_forward&&direction=="dn") type=1; if(!up_back&& up_forward&&direction=="dn") type=2; if(!up_back&& up_forward&&direction=="dn") type=3; if( up_back&& up_forward&&direction=="dn") type=4; if( up_back&& up_forward&&direction=="up") type=5; if( up_back&& up_forward&&direction=="up") type=6; if( up_back&& up_forward&&direction=="up") type=7; if( up_back&& up_forward&&direction=="up") type=8; if( dn_back&& dn_forward&&direction=="dn") type=9; if( dn_back&& dn_forward&&direction=="dn") type=10; if( dn_back&& dn_forward&&direction=="dn") type=11; if( dn_back&& dn_forward&&direction=="dn") type=12; if( dn_back&& dn_forward&&direction=="up") type=13; if(!dn_back&& dn_forward&&direction=="up") type=14; if( dn_back&& dn_forward&&direction=="up") type=15; if(!dn_back&& dn_forward&&direction=="up") type=16; if( dn_back&& up_forward&&direction=="dn") type=17; if( dn_back&& up_forward&&direction=="dn") type=18; if( dn_back&& up_forward&&direction=="dn") type=19; if( dn_back&& up_forward&&direction=="dn") type=20; if( dn_back&& up_forward&&direction=="up") type=21; if(!dn_back&& up_forward&&direction=="up") type=22; if( dn_back&&!up_forward&&direction=="up") type=23; if(!dn_back&&!up_forward&&direction=="up") type=24; if( up_back&& dn_forward&&direction=="dn") type=25; if( up_back&&!dn_forward&&direction=="dn") type=26; if(!up_back&& dn_forward&&direction=="dn") type=27; if(!up_back&&!dn_forward&&direction=="dn") type=28; if( up_back&& dn_forward&&direction=="up") type=29; if( up_back&& dn_forward&&direction=="up") type=30; if( up_back&& dn_forward&&direction=="up") type=31; if( up_back&& dn_forward&&direction=="up") type=32; //---- return(type); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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[]) { //---- checking the number of bars to be enough for the calculation if(rates_totalrates_total-21) QuantityOfBars=rates_total-21; for(i=int(QuantityOfBars); i>1; i--) // basic iteration { Up[i]=0; Dn[i]=0; //--- the upper extremum is found, the lower one is absent //--- in case the upper extremum is found if(ExistUp(i,high) && !ExistDn(i,high)) { //--- zeroing out the relevance flag when viewed back in history actual_back=false; //--- storing the bar, at which the upper extremum is found j=i; //--- preparing to move back to the past in history along the bars according to the review value while(j=high[i]) {actual_back=false; break;} //--- if there is a lower extremum and it is below the current one, then our upper one is relevant if(ExistDn(j,high) && !ExistUp(j,high) && low[j]i-review) { if(j<2) break; //--- enlarging the move counter forward in history j--; //--- if there is an upper extremum and it is above the current one, then our upper one is irrelevant if(ExistUp(j,high) && !ExistDn(j,high) && high[j]>high[i]) {actual_forward=false; break;} //--- if there is a lower extremum and it is below the current one, then our upper one is relevant if(ExistDn(j,high) && !ExistUp(j,high) && low[j]low[i]) {actual_back=true; break;} //--- if both lower and upper extremums are found if(ExistDn(j,high) && ExistUp(j,high)) { TypeDuo=IdentDualExtr(j,open,low,high,close); switch(TypeDuo) { case 1: actual_back=true; break; case 2: actual_back=true; break; case 3: actual_back=true; break; case 4: actual_back=true; break; case 5: actual_back=true; break; case 6: actual_back=true; break; case 7: actual_back=true; break; case 8: actual_back=true; break; case 9: actual_back=true; break; case 10: actual_back=true; break; case 11: actual_back=true; break; case 12: actual_back=true; break; case 13: actual_back=true; break; case 14: actual_back=true; break; case 15: actual_back=true; break; case 16: actual_back=true; break; case 17: actual_back=true; break; case 18: actual_back=true; break; case 19: actual_back=true; break; case 20: actual_back=true; break; case 21: actual_back=true; break; case 22: actual_back=true; break; case 23: actual_back=true; break; case 24: actual_back=true; break; case 25: actual_back=true; break; case 26: actual_back=false; break; case 27: actual_back=true; break; case 28: actual_back=false; break; case 29: actual_back=true; break; case 30: actual_back=true; break; case 31: actual_back=true; break; case 32: actual_back=true; } break; } } //--- zeroing out the relevance flag when viewed forward in history actual_forward=false; //--- storing the bar, at which the lower extremum is found j=i; //--- preparing to move forward in history along the bars according to the review value while(j>i-review) { if(j<2) break; //--- enlarging the move counter forward in history j--; //--- if there is a lower extremum and it is below the current one, then our lower one is irrelevant if(ExistDn(j,high) && !ExistUp(j,high) && low[j]low[i]) {actual_forward=true; break;} //--- if both lower and upper extremums are found if(ExistDn(j,high) && ExistUp(j,high)) { TypeDuo=IdentDualExtr(j,open,low,high,close); switch(TypeDuo) { case 1: actual_forward=true; break; case 2: actual_forward=true; break; case 3: actual_forward=true; break; case 4: actual_forward=true; break; case 5: actual_forward=true; break; case 6: actual_forward=true; break; case 7: actual_forward=true; break; case 8: actual_forward=true; break; case 9: actual_forward=true; break; case 10: actual_forward=true; break; case 11: actual_forward=true; break; case 12: actual_forward=true; break; case 13: actual_forward=true; break; case 14: actual_forward=false; break; case 15: actual_forward=true; break; case 16: actual_forward=false; break; case 17: actual_forward=true; break; case 18: actual_forward=true; break; case 19: actual_forward=true; break; case 20: actual_forward=true; break; case 21: actual_forward=true; break; case 22: actual_forward=false; break; case 23: actual_forward=true; break; case 24: actual_forward=false; break; case 25: actual_forward=true; break; case 26: actual_forward=true; break; case 27: actual_forward=true; break; case 28: actual_forward=true; break; case 29: actual_forward=true; break; case 30: actual_forward=true; break; case 31: actual_forward=true; break; case 32: actual_forward=true; } break; } } //--- in case everything is OK behind and ahead if(actual_back && actual_forward) { //--- filling Dn array using Dn_tmp variable Dn_tmp=low[i]; } //--- in case the extremum is irrelevant, the array must be zeroed out using Dn_tmp variable else Dn_tmp=0; } //--- everything is executed, in case the lower extremum is found //--- in case the lower extremum is absent, the array must be zeroed out using Dn_tmp variable else Dn_tmp=0; //--- both extremums are found //--- if both lower and upper extremums are found if(ExistDn(i,high) && ExistUp(i,high)) { TypeDuo=IdentDualExtr(i,open,low,high,close); switch(TypeDuo) { case 1: Up_tmp=0; Dn_tmp=low[i]; break; case 2: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 3: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 4: Up_tmp=0; Dn_tmp=low[i]; break; case 5: Up_tmp=0; Dn_tmp=low[i]; break; case 6: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 7: Up_tmp=0; Dn_tmp=low[i]; break; case 8: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 9: Up_tmp=high[i]; Dn_tmp=0; break; case 10: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 11: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 12: Up_tmp=low[i]; Dn_tmp=0; break; case 13: Up_tmp=high[i]; Dn_tmp=0; break; case 14: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 15: Up_tmp=high[i]; Dn_tmp=0; break; case 16: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 17: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 18: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 19: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 20: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 21: Up_tmp=0; Dn_tmp=0; break; case 22: Up_tmp=0; Dn_tmp=low[i]; break; case 23: Up_tmp=high[i]; Dn_tmp=0; break; case 24: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 25: Up_tmp=0; Dn_tmp=0; break; case 26: Up_tmp=0; Dn_tmp=low[i]; break; case 27: Up_tmp=high[i]; Dn_tmp=0; break; case 28: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 29: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 30: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 31: Up_tmp=high[i]; Dn_tmp=low[i]; break; case 32: Up_tmp=high[i]; Dn_tmp=low[i]; break; } } //--- if both extremums are not found if(!ExistDn(i,high) && !ExistUp(i,high)) { Up_tmp=0; Dn_tmp=0; } //--- Up array is filled directly Up[i]=Up_tmp+2*_Point; //--- Dn array is filled directly Dn[i]=Dn_tmp-2*_Point; } //---- return(rates_total); } //+------------------------------------------------------------------+