//+------------------------------------------------------------------+ //| ATR Based Zigzag w EMA.mq4 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property link "www.forex-station.com" #property copyright "www.forex-station.com" #property version "1.00" #property strict #property indicator_chart_window #property indicator_buffers 3 #property indicator_label1 "Atr based Ema" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDeepSkyBlue #property indicator_width1 3 #property indicator_label2 "Atr based Ema" #property indicator_type2 DRAW_LINE #property indicator_color2 clrCrimson #property indicator_width2 3 #property indicator_label3 "Atr based Ema" #property indicator_type3 DRAW_LINE #property indicator_color3 clrCrimson #property indicator_width3 3 // // // input double inpPeriod = 50; // Ema period input int inpAtrPeriod = 14; // Atr length input double inpAtrMulti = 5.0; // Atr multiplie input ENUM_APPLIED_PRICE inpPrice = PRICE_CLOSE; // Price double val[],vala[],valb[],trend[]; struct sGlobalStruct { double alp,prc,hi,lo; int lim; }; sGlobalStruct glo; //------------------------------------------------------------------ // Custom indicator initialization function //------------------------------------------------------------------ int OnInit() { IndicatorBuffers(4); SetIndexBuffer(0,val ,INDICATOR_DATA); SetIndexBuffer(1,vala,INDICATOR_DATA); SetIndexBuffer(2,valb,INDICATOR_DATA); SetIndexBuffer(3,trend,INDICATOR_CALCULATIONS); glo.alp = 2.0/(1.0+(fmax(inpPeriod,1))); IndicatorSetString(INDICATOR_SHORTNAME," Atr based EMA"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 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[]) { glo.lim = fmin(rates_total-prev_calculated+1,rates_total-1); // // // struct sWrkStruct { double smax,smin; }; static sWrkStruct wrk[]; static int wrkSize = -1; if (wrkSize=0; i--,r++) { glo.prc = iMA(_Symbol,_Period,1,0,MODE_SMA,inpPrice,i); val[i] = (r>0) ? val[i+1] + glo.alp*(glo.prc-val[i+1]) : glo.prc; glo.hi = (r>0) ? high[i+1] : high[i]; glo.lo = (r>0) ? low[i+1] : low[i]; wrk[r].smin = glo.lo - inpAtrMulti * iATR(_Symbol,_Period,inpAtrPeriod,i); wrk[r].smax = glo.hi + inpAtrMulti * iATR(_Symbol,_Period,inpAtrPeriod,i); trend[i] = (r>0) ? (high[i]>wrk[r-1].smax) ? 1 : (low[i]0) { if (trend[i]==-1 && wrk[r].smax>wrk[r-1].smax) wrk[r].smax = wrk[r-1].smax; if (trend[i]== 1 && wrk[r].smin=bars-3) return; if ((second[i] != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE)) second[i+1] = EMPTY_VALUE; else if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE)) first[i+1] = EMPTY_VALUE; } void iPlotPoint(int i,int bars,double& first[],double& second[],double& from[]) { if (i>=bars-2) return; if (first[i+1] == EMPTY_VALUE) if (first[i+2] == EMPTY_VALUE) { first[i] = from[i]; first[i+1] = from[i+1]; second[i] = EMPTY_VALUE; } else { second[i] = from[i]; second[i+1] = from[i+1]; first[i] = EMPTY_VALUE; } else { first[i] = from[i]; second[i] = EMPTY_VALUE; } } /*/@version=6 indicator('ATR Based Zigzag w EMA', overlay = true) // === Inputs === ATRLength = input(14, title = 'ATR Length') ATRMult = input(5.0, title = 'ATR Multiplier') lineSmoothLength = input(50, title = 'Line Smoothness (EMA Length)') upTrendColor = input(color.rgb(0, 255, 132), title = 'Uptrend Line Color') downTrendColor = input(color.rgb(255, 0, 0), title = 'Downtrend Line Color') // === ATR Calculation === atr_val = ta.atr(ATRLength) // === State Variables === var float LL = na var float HH = na var int trend = 1 // === Initialization === LL := na(LL[1]) ? low : LL[1] HH := na(HH[1]) ? high : HH[1] trend := na(trend[1]) ? 1 : trend[1] // === Core Logic === if trend > 0 // Uptrend: looking for new swing low if high >= HH HH := high HH else if low < HH - atr_val * ATRMult trend := -1 LL := low LL else // Downtrend: looking for new swing high if low <= LL LL := low LL else if high > LL + atr_val * ATRMult trend := 1 HH := high HH // === Median Price (or pick a price base you prefer) === medianPrice = (high + low) / 2 // === Smoothed Line === smoothLine = ta.ema(medianPrice, lineSmoothLength) // === Plotting the Clean Trend Line === plot(smoothLine, color = trend == 1 ? upTrendColor : downTrendColor, linewidth = 3, title = 'Trend Line') // === (Optional) Bar Coloring Too === barcolor(trend == 1 ? upTrendColor : downTrendColor) */