//------------------------------------------------------------------ #property copyright "© mladen, 2016, MetaQuotes Software Corp." #property link "www.forex-tsd.com, www.mql5.com" //------------------------------------------------------------------ #property indicator_separate_window #property indicator_buffers 9 #property indicator_plots 5 #property indicator_label1 "CCI Ob/Os zone" #property indicator_type1 DRAW_FILLING #property indicator_color1 clrLimeGreen,clrDeepPink #property indicator_label2 "CCI level up" #property indicator_type2 DRAW_LINE #property indicator_color2 clrYellowGreen #property indicator_style2 STYLE_DOT #property indicator_label3 "CCI middle level" #property indicator_type3 DRAW_LINE #property indicator_color3 clrSilver #property indicator_style3 STYLE_DOT #property indicator_label4 "CCI level down" #property indicator_type4 DRAW_LINE #property indicator_color4 clrHotPink #property indicator_style4 STYLE_DOT #property indicator_label5 "CCI" #property indicator_type5 DRAW_COLOR_LINE #property indicator_color5 clrSilver,clrLimeGreen,clrHotPink #property indicator_style5 STYLE_SOLID #property indicator_width5 2 // // // // // enum enPrices { pr_close, // Close pr_open, // Open pr_high, // High pr_low, // Low pr_median, // Median pr_typical, // Typical pr_weighted, // Weighted pr_average, // Average (high+low+open+close)/4 pr_medianb, // Average median body (open+close)/2 pr_tbiased, // Trend biased price pr_tbiased2, // Trend biased (extreme) price pr_haclose, // Heiken ashi close pr_haopen , // Heiken ashi open pr_hahigh, // Heiken ashi high pr_halow, // Heiken ashi low pr_hamedian, // Heiken ashi median pr_hatypical, // Heiken ashi typical pr_haweighted, // Heiken ashi weighted pr_haaverage, // Heiken ashi average pr_hamedianb, // Heiken ashi median body pr_hatbiased, // Heiken ashi trend biased price pr_hatbiased2 // Heiken ashi trend biased (extreme) price }; enum enMaTypes { ma_sma, // Simple moving average ma_ema, // Exponential moving average ma_smma, // Smoothed MA ma_lwma // Linear weighted MA }; enum chgColor { chg_onSlope, // change color on slope change chg_onLevel, // Change color on outer levels cross chg_onMiddle // Change color on middle level cross }; enum enLevelType { lvl_floa, // Floating levels lvl_quan // Quantile levels }; enum enAdapting { ada_vhf, // VHF adaptive ada_noa // Regular (no adapting) }; input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame input int CciPeriod = 50; // CCI calculating period input enPrices CciPrice = pr_close; // Price input enAdapting CciAdapting = ada_vhf; // Adapting type input int PriceSmooth = 32; // Price smoothing input enMaTypes PriceSmoothMethod = ma_ema; // Price smoothing method input int LevelsPeriod = 25; // Levels period (<0 no levels, 0 same as CCI period) input double LevelsUp = 90; // Levels up level % input double LevelsDown = 10; // Levels down level % input enLevelType LevelType = lvl_floa; // Levels type input chgColor ColorOn = chg_onLevel; // Color change on : input bool AlertsOn = false; // Turn alerts on? input bool AlertsOnCurrent = true; // Alert on current bar? input bool AlertsMessage = true; // Display messageas on alerts? input bool AlertsSound = false; // Play sound on alerts? input bool AlertsEmail = false; // Send email on alerts? input bool AlertsNotify = false; // Send push notification on alerts? input bool Interpolate = true; // Interpolate in multi time frame mode? double val[],fillup[],filldn[],levelup[],levelmi[],leveldn[],colorBuffer[],count[],prices[]; int _mtfHandle = INVALID_HANDLE; ENUM_TIMEFRAMES timeFrame; #define _mtfCall iCustom(_Symbol,timeFrame,getIndicatorName(),PERIOD_CURRENT,CciPeriod,CciPrice,CciAdapting,PriceSmooth,PriceSmoothMethod,LevelsPeriod,LevelsUp,LevelsDown,LevelType,ColorOn,AlertsOn,AlertsOnCurrent,AlertsMessage,AlertsSound,AlertsEmail,AlertsNotify) //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // int OnInit() { SetIndexBuffer(0,fillup ,INDICATOR_DATA); SetIndexBuffer(1,filldn ,INDICATOR_DATA); SetIndexBuffer(2,levelup ,INDICATOR_DATA); SetIndexBuffer(3,levelmi ,INDICATOR_DATA); SetIndexBuffer(4,leveldn ,INDICATOR_DATA); SetIndexBuffer(5,val ,INDICATOR_DATA); SetIndexBuffer(6,colorBuffer,INDICATOR_COLOR_INDEX); SetIndexBuffer(7,count ,INDICATOR_CALCULATIONS); SetIndexBuffer(8,prices ,INDICATOR_CALCULATIONS); for (int i=0; i<4; i++) PlotIndexSetInteger(i,PLOT_SHOW_DATA,false); timeFrame = MathMax(_Period,TimeFrame); if (timeFrame != _Period) _mtfHandle = _mtfCall; IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(timeFrame)+" CCI ("+string(CciPeriod)+","+string(PriceSmooth)+")"); 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[]) { if (Bars(_Symbol,_Period) 0 && time[i-n] >= currTime[0]; n++) continue; for(k=1; (i-k)>=0 && k1) ? ColorOn : chg_onSlope; int i; for (i=(int)MathMax(prev_calculated-1,0); i=0; k++) avg += prices[i-k]; avg /= (int)period; double dev = 0; for(int k=0; k<(int)period && (i-k)>=0; k++) dev += MathAbs(prices[i-k]-avg); dev /= (int)period; if (dev!=0) val[i] = (prices[i]-avg)/(0.015*dev); else val[i] = 0; // // // // // if (LevelType==lvl_floa) { int start = MathMax(i-levelsPeriod+1,0); double min = val[ArrayMinimum(val,start,levelsPeriod)]; double max = val[ArrayMaximum(val,start,levelsPeriod)]; double range = max-min; levelup[i] = min+LevelsUp *range/100.0; leveldn[i] = min+LevelsDown*range/100.0; levelmi[i] = min+0.5*range; } else { levelup[i] = iQuantile(val[i],levelsPeriod, LevelsUp ,i,rates_total); leveldn[i] = iQuantile(val[i],levelsPeriod, LevelsDown ,i,rates_total); levelmi[i] = iQuantile(val[i],levelsPeriod,(LevelsUp+LevelsDown)/2.0,i,rates_total); } switch (colorOn) { case chg_onLevel : colorBuffer[i] = (val[i]>levelup[i]) ? 1 : (val[i]leveldn[i]) ? 0 : (i>0) ? colorBuffer[i-1]: 0; break; case chg_onMiddle : colorBuffer[i] = (val[i]>levelmi[i]) ? 1 : (val[i]0) ? colorBuffer[i-1] : 0; break; default : colorBuffer[i] = (i>0) ? (val[i]>val[i-1]) ? 1 : (val[i]=0; k++) { noise += MathAbs(_workVhf[i-k][instanceNo]-_workVhf[i-k-1][instanceNo]); max = MathMax(_workVhf[i-k][instanceNo],max); min = MathMin(_workVhf[i-k][instanceNo],min); } if (noise>0) vhf = (max-min)/noise; return(vhf); } //------------------------------------------------------------------- // //------------------------------------------------------------------- // // // // // #define _quantileInstances 1 double _sortQuant[]; double _workQuant[][_quantileInstances]; double iQuantile(double value, int period, double qp, int i, int bars, int instanceNo=0) { if (ArrayRange(_workQuant,0)!=bars) ArrayResize(_workQuant,bars); _workQuant[i][instanceNo]=value; if (period<1) return(value); if (ArraySize(_sortQuant)!=period) ArrayResize(_sortQuant,period); int k=0; for (; k=0; k++) _sortQuant[k] = _workQuant[i-k][instanceNo]; for (; k=0; k++) avg += workSma[r-k][instanceNo+0]; avg /= (double)k; return(avg); } // // // // // double workEma[][_maWorkBufferx1]; double iEma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars); workEma[r][instanceNo] = price; if (r>0 && period>1) workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]); return(workEma[r][instanceNo]); } // // // // // double workSmma[][_maWorkBufferx1]; double iSmma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars); workSmma[r][instanceNo] = price; if (r>1 && period>1) workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period; return(workSmma[r][instanceNo]); } // // // // // double workLwma[][_maWorkBufferx1]; double iLwma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars); workLwma[r][instanceNo] = price; if (period<1) return(price); double sumw = period; double sum = period*price; for(int k=1; k=0; k++) { double weight = period-k; sumw += weight; sum += weight*workLwma[r-k][instanceNo]; } return(sum/sumw); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // void manageAlerts(const datetime& time[], double& trend[], int bars) { if (!AlertsOn) return; int whichBar = bars-1; if (!AlertsOnCurrent) whichBar = bars-2; datetime time1 = time[whichBar]; if (trend[whichBar] != trend[whichBar-1]) { if (trend[whichBar] == 1) doAlert(time1,"up"); if (trend[whichBar] == 2) doAlert(time1,"down"); } } // // // // // void doAlert(datetime forTime, string doWhat) { static string previousAlert="nothing"; static datetime previousTime; string message; if (previousAlert != doWhat || previousTime != forTime) { previousAlert = doWhat; previousTime = forTime; // // // // // message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToString(TimeLocal(),TIME_SECONDS)+" CCI state changed to "+doWhat; if (AlertsMessage) Alert(message); if (AlertsEmail) SendMail(_Symbol+" CCI",message); if (AlertsNotify) SendNotification(message); if (AlertsSound) PlaySound("alert2.wav"); } } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // // #define _pricesInstances 3 #define _pricesSize 4 double workHa[][_pricesInstances*_pricesSize]; double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i,int _bars, int instanceNo=0) { if (tprice>=pr_haclose) { if (ArrayRange(workHa,0)!= _bars) ArrayResize(workHa,_bars); instanceNo*=_pricesSize; // // // // // double haOpen; if (i>0) haOpen = (workHa[i-1][instanceNo+2] + workHa[i-1][instanceNo+3])/2.0; else haOpen = (open[i]+close[i])/2; double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0; double haHigh = MathMax(high[i], MathMax(haOpen,haClose)); double haLow = MathMin(low[i] , MathMin(haOpen,haClose)); if(haOpen haOpen) return((haHigh+haClose)/2.0); else return((haLow+haClose)/2.0); case pr_hatbiased2: if (haClose>haOpen) return(haHigh); if (haCloseopen[i]) return((high[i]+close[i])/2.0); else return((low[i]+close[i])/2.0); case pr_tbiased2: if (close[i]>open[i]) return(high[i]); if (close[i]