#property copyright "EMA Step Non-Repaint Indicator" #property link "https://x.ai" #property version "1.00" #property strict #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_label1 "Upper Step Line" #property indicator_label2 "Lower Step Line" #property indicator_type1 DRAW_LINE #property indicator_type2 DRAW_LINE #property indicator_color1 clrRed #property indicator_color2 clrBlue #property indicator_style1 STYLE_SOLID #property indicator_style2 STYLE_SOLID #property indicator_width1 2 #property indicator_width2 2 // Bemeneti paraméterek input int EMA_Period = 50; // EMA Period input double Offset_Pips = 10; // Distance from Candles (Pips) input int Step_Period = 10; // Step Period (Candles) input double Trend_Threshold = 0.5; // Trend Change Threshold (Pips) // Indikátor bufferek double UpperBuffer[]; double LowerBuffer[]; // Globális változók double pip; datetime lastBarTime; // Inicializáció int OnInit() { SetIndexBuffer(0, UpperBuffer); SetIndexBuffer(1, LowerBuffer); // Pip érték kiszámítása pip = Point; if(Digits == 3 || Digits == 5) pip *= 10; IndicatorShortName("EMA Step Non-Repaint (" + IntegerToString(EMA_Period) + ")"); lastBarTime = 0; return(INIT_SUCCEEDED); } // Számítás 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[]) { // Csak új gyertyánál számolunk if(time[0] == lastBarTime && prev_calculated > 0) return(rates_total); lastBarTime = time[0]; // EMA számítása double ema[]; ArrayResize(ema, rates_total); for(int i = 0; i < rates_total; i++) { ema[i] = iMA(NULL, 0, EMA_Period, 0, MODE_EMA, PRICE_CLOSE, i); } // Non-repainting lépcsős vonalak számítása static double lastUpperLevel = 0; static double lastLowerLevel = 0; static bool lastTrendUp = true; for(int i = rates_total - 1 - prev_calculated; i >= 0; i--) { // Trend meghatározása az EMA alapján bool isUptrend = (i < rates_total - 1 && ema[i] > ema[i + 1] + Trend_Threshold * pip); bool isDowntrend = (i < rates_total - 1 && ema[i] < ema[i + 1] - Trend_Threshold * pip); // Csak akkor számolunk új szintet, ha új lépcső periódus kezdődik if(i % Step_Period == 0 || i == rates_total - 1) { if(isUptrend && !isDowntrend) { // Felfelé trend: vonal a gyertyák minimuma alatt double minLow = low[i]; for(int j = 1; j < Step_Period && i + j < rates_total; j++) { minLow = MathMin(minLow, low[i + j]); } lastLowerLevel = minLow - Offset_Pips * pip; lastUpperLevel = 0; lastTrendUp = true; } else if(isDowntrend && !isUptrend) { // Lefelé trend: vonal a gyertyák maximuma felett double maxHigh = high[i]; for(int j = 1; j < Step_Period && i + j < rates_total; j++) { maxHigh = MathMax(maxHigh, high[i + j]); } lastUpperLevel = maxHigh + Offset_Pips * pip; lastLowerLevel = 0; lastTrendUp = false; } else { // Semleges trend: a legutóbbi szintet tartjuk lastUpperLevel = lastTrendUp ? 0 : lastUpperLevel; lastLowerLevel = lastTrendUp ? lastLowerLevel : 0; } } // Buffer értékek beállítása UpperBuffer[i] = lastUpperLevel > 0 ? lastUpperLevel : EMPTY_VALUE; LowerBuffer[i] = lastLowerLevel > 0 ? lastLowerLevel : EMPTY_VALUE; // Következő gyertyákhoz másolás, ha nem új lépcső if(i < rates_total - 1 && i % Step_Period != 0) { UpperBuffer[i] = UpperBuffer[i + 1]; LowerBuffer[i] = LowerBuffer[i + 1]; } } return(rates_total); }