//+------------------------------------------------------------------+ //| L1VolatilitySmoothed.mq5 | //| Copyright 2000-2026, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2026, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "L1VolatilitySmoothed" #property indicator_type1 DRAW_LINE #property indicator_color1 clrMediumVioletRed #property indicator_width1 2 //--- input int BarsToShow = 1000; // Number of bars to calculate L1 input double CoefLambda = 0.015; // Lambda in lambda_max units input int SmoothPeriod = 10; // Smooth period //--- double VolSmoothed[]; //+------------------------------------------------------------------+ //| Indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, VolSmoothed, INDICATOR_DATA); ArrayInitialize(VolSmoothed, EMPTY_VALUE); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); IndicatorSetInteger(INDICATOR_DIGITS, _Digits); //--- return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| 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[]) { if(rates_total < BarsToShow) { ArrayInitialize(VolSmoothed, EMPTY_VALUE); return 0; } //--- recalc only on new bar static datetime last_bar_time = 0; if(time[0] == last_bar_time && prev_calculated > 0) return prev_calculated; last_bar_time = time[0]; //--- int start = rates_total - BarsToShow; for(int i = 0; i < start; i++) VolSmoothed[i] = EMPTY_VALUE; //--- copy close prices vector price(BarsToShow); for(int i = 0; i < BarsToShow; i++) price[i] = close[start + i]; vector l1(BarsToShow); price.L1TrendFilter(l1, CoefLambda, true); //--- calculate raw volatility vector rawVol(BarsToShow); for(int i = 0; i < BarsToShow; i++) rawVol[i] = close[start + i] - l1[i]; //--- apply simple moving average smoothing for(int i = 0; i < BarsToShow; i++) { double sum = 0; int count = 0; for(int j = MathMax(0, i - SmoothPeriod + 1); j <= i; j++) { sum += rawVol[j]; count++; } VolSmoothed[start + i] = sum / count; } //--- return rates_total; } //+------------------------------------------------------------------+