Meta Cluster Filter Price v1.0 (Non-Repaint) MT 4 Indicator

The Meta Cluster Filter Price (Non-Repaint) indicator is designed to visualize price trends using a combination of moving averages and a custom filter. It calculates and displays three distinct lines: a Simple Moving Average (SMA), an Exponential Moving Average (EMA), and a Custom Filter (CF) that refines the price movement. This non-repainting indicator provides a stable historical view of price data without altering past values. With customizable parameters, including the choice of price type and calculation period, the Meta Cluster Filter Price indicator helps track market trends by smoothing out price fluctuations.

#property indicator_chart_window 
#property indicator_buffers 3        // Number of indicator buffers
#property indicator_plots   3        // Number of plots (lines) drawn

//--- Enum to select price type for calculations
enum enum_price
   {
      O = 1, // PRICE_OPEN
      H = 2, // PRICE_HIGH
      L = 3, // PRICE_LOW
      C = 4  // PRICE_CLOSE
   };

//--- Indicator buffers to store MA, EMA, and CF values
double   ExtBuffer_MA[];   // Buffer for Simple Moving Average (MA)
double   ExtBuffer_EMA[];  // Buffer for Exponential Moving Average (EMA)
double   ExtBuffer_CF[];   // Buffer for Custom Filter (CF)

//--- Input parameters
input int ext_period_MA = 2;               // Period for MA calculation
input enum_price price_type = C;           // Price type (O, H, L, C)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Map buffers to indicator for display
   SetIndexBuffer(0, ExtBuffer_MA);
   SetIndexBuffer(1, ExtBuffer_EMA);
   SetIndexBuffer(2, ExtBuffer_CF);

   //--- Set styles for indicator lines
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 1, clrBlue);   // MA line in Blue
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 1, clrGreen);  // EMA line in Green
   SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 1, clrRed);    // CF line in Red

   //--- Set the number of digits for indicator precision
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits + 1);

   //--- Initialize arrays to be series (not reversed)
   ArraySetAsSeries(ExtBuffer_MA, false);
   ArraySetAsSeries(ExtBuffer_EMA, false);
   ArraySetAsSeries(ExtBuffer_CF, false);

   //--- Initialization succeeded
   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[])
  {
   //--- Define beginning index
   int begin = 0;

   //--- Switch for price type selection
   if(price_type == O) // Open price selected
      {
         ArraySetAsSeries(open, false);  // Set Open array as series
         CalculateSimpleMA(rates_total, prev_calculated, begin, open);
         CalculateEMA(rates_total, prev_calculated, begin, open);
         CalculateCF(rates_total, prev_calculated, begin, open);
      } 
   else if(price_type == H) // High price selected
      {
         ArraySetAsSeries(high, false);  // Set High array as series
         CalculateSimpleMA(rates_total, prev_calculated, begin, high);
         CalculateEMA(rates_total, prev_calculated, begin, high);
         CalculateCF(rates_total, prev_calculated, begin, high);
      } 
   else if(price_type == L) // Low price selected
      {
         ArraySetAsSeries(low, false);  // Set Low array as series
         CalculateSimpleMA(rates_total, prev_calculated, begin, low);
         CalculateEMA(rates_total, prev_calculated, begin, low);
         CalculateCF(rates_total, prev_calculated, begin, low);
      } 
   else // Close price selected (default)
      {
         ArraySetAsSeries(close, false);  // Set Close array as series
         CalculateSimpleMA(rates_total, prev_calculated, begin, close);
         CalculateEMA(rates_total, prev_calculated, begin, close);
         CalculateCF(rates_total, prev_calculated, begin, close);
      }

   //--- Return calculated bars for next iteration
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Simple Moving Average (SMA) Calculation                          |
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total, int prev_calculated, int begin, const double &price[])
  {
   int i, limit;

   //--- First calculation or number of bars changed
   if(prev_calculated == 0) // If it's the first calculation
     {
      limit = ext_period_MA + begin;
      //--- Set zero value for first 'limit' bars
      for(i = 0; i < limit - 1; i++) { ExtBuffer_MA[i] = 0.0; }

      //--- Calculate first visible value
      double firstValue = 0;
      for(i = begin; i < limit; i++) { firstValue += price[i]; }
      firstValue /= ext_period_MA;
      ExtBuffer_MA[limit - 1] = firstValue;
     }
   else { limit = prev_calculated - 1; }

   //--- Main loop for calculation
   for(i = limit; i < rates_total && !IsStopped(); i++)
      ExtBuffer_MA[i] = ExtBuffer_MA[i - 1] + (price[i] - price[i - ext_period_MA]) / ext_period_MA;
  }

//+------------------------------------------------------------------+
//| Exponential Moving Average (EMA) Calculation                     |
//+------------------------------------------------------------------+
void CalculateEMA(int rates_total, int prev_calculated, int begin, const double &price[])
  {
   int i, limit;
   double SmoothFactor = 2.0 / (1.0 + ext_period_MA); // Smoothing factor for EMA

   //--- First calculation or number of bars changed
   if(prev_calculated == 0) // If it's the first calculation
     {
      limit = ext_period_MA + begin;
      ExtBuffer_EMA[begin] = price[begin]; // Initialize EMA with first price value

      //--- Loop to calculate initial EMA
      for(i = begin + 1; i < limit; i++)
         ExtBuffer_EMA[i] = price[i] * SmoothFactor + ExtBuffer_EMA[i - 1] * (1.0 - SmoothFactor);
     }
   else { limit = prev_calculated - 1; }

   //--- Main loop for calculation
   for(i = limit; i < rates_total && !IsStopped(); i++)
      ExtBuffer_EMA[i] = price[i] * SmoothFactor + ExtBuffer_EMA[i - 1] * (1.0 - SmoothFactor);
  }

//+------------------------------------------------------------------+
//| Custom Filter (CF) Calculation                                   |
//+------------------------------------------------------------------+
void CalculateCF(int rates_total, int prev_calculated, int begin, const double &price[])
  {
   int i, limit;

   //--- First calculation or number of bars changed
   if(prev_calculated == 0) // If it's the first calculation
     {
      limit = ext_period_MA + begin;
      for(i = begin; i < limit; i++)
         ExtBuffer_CF[i] = ExtBuffer_EMA[i]; // Initialize CF with EMA values
     }
   else { limit = prev_calculated - 1; }

   //--- Main loop for CF calculation
   for(i = limit; i < rates_total && !IsStopped(); i++)
     {
      //--- If CF trend is upward
      if(ExtBuffer_CF[i - 1] > ExtBuffer_CF[i - 2])
        {
         if(ExtBuffer_CF[i - 1] < ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] < ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = fmin(ExtBuffer_MA[i], ExtBuffer_EMA[i]);
            continue;
           }
         if(ExtBuffer_CF[i - 1] < ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] > ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = ExtBuffer_MA[i];
            continue;
           }
         if(ExtBuffer_CF[i - 1] > ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] < ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = ExtBuffer_EMA[i];
            continue;
           }
         ExtBuffer_CF[i] = fmax(ExtBuffer_MA[i], ExtBuffer_EMA[i]);
        }
      //--- If CF trend is downward
      else
        {
         if(ExtBuffer_CF[i - 1] > ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] > ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = fmax(ExtBuffer_MA[i], ExtBuffer_EMA[i]);
            continue;
           }
         if(ExtBuffer_CF[i - 1] > ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] < ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = ExtBuffer_MA[i];
            continue;
           }
         if(ExtBuffer_CF[i - 1] < ExtBuffer_MA[i] && ExtBuffer_CF[i - 1] > ExtBuffer_EMA[i])
           {
            ExtBuffer_CF[i] = ExtBuffer_EMA[i];
            continue;
           }
         ExtBuffer_CF[i] = fmin(ExtBuffer_MA[i], ExtBuffer_EMA[i]);
        }
     }
  }
//+------------------------------------------------------------------+

What Does This Indicator Do?

At its core, this indicator calculates and plots three lines on your chart:

  1. Simple Moving Average (SMA) – A basic average of prices over a specific period.
  2. Exponential Moving Average (EMA) – A weighted average that gives more importance to recent price data.
  3. Custom Filter (CF) – A filter that uses both the SMA and EMA to adjust and smooth out price movements.
See also  Rise and Down Trend v1.2 (Non-Repaint) MetaTrader 4 Indicator

These three lines help visualize how price data is trending over time and offer a way to track shifts in market momentum.

How Does the Indicator Work?

This indicator calculates values for each of its three lines based on price data from a selected timeframe. Here’s how each part functions:

1. Simple Moving Average (SMA)

The Simple Moving Average is one of the most straightforward ways to track price trends. It takes the average of a set number of prices over a given period. In this indicator, you can select from open, high, low, or close prices to feed into the calculation.

For each new bar on the chart, the SMA updates, showing you how the average price changes over time. While it’s easy to compute, the SMA can sometimes react slowly to sudden price changes because it gives equal weight to all prices in its calculation.

2. Exponential Moving Average (EMA)

The Exponential Moving Average works similarly to the SMA but with a twist. It gives more weight to recent price data, making it more responsive to current market movements. This can make the EMA more dynamic in reacting to quick price shifts compared to the slower-moving SMA.

The indicator calculates the EMA using a “smoothing factor,” which determines how much recent prices influence the result. This is helpful when you want an average that reflects the latest trends without completely ignoring older price information.

3. Custom Filter (CF)

The Custom Filter is the most unique part of this indicator. It takes the data from both the SMA and EMA and applies a series of conditions to refine the result. Essentially, the filter smooths out the price movements by checking how the SMA and EMA lines compare to each other and adjusting the values accordingly.

See also  Alixa SSL + ATR Band (Non-Repaint) MetaTrader 4 Indicator

This Custom Filter helps reduce noise from random price movements that might not indicate a true trend. The filter checks whether price values are rising or falling and adjusts the final output to either the minimum or maximum of the two moving averages, depending on the conditions met.

Price Selection

This indicator gives you control over which type of price data to use for the calculations. You can choose from open, high, low, or close prices, which are common options for most moving averages.

  • Open Price: The first price of the trading period.
  • High Price: The highest price during the trading period.
  • Low Price: The lowest price during the trading period.
  • Close Price: The final price of the trading period.

Your choice of price type will affect the final outcome of the indicator, as different prices can provide different perspectives on market behavior.

Important Details

There are a few essential things to note when using this type of indicator:

Non-Repaint

A non-repainting indicator means that once a value is plotted on the chart, it won’t change as new data comes in. This is important for historical analysis because you want to be confident that the values you see from previous periods remain consistent.

Lagging

Moving averages, by their nature, are lagging indicators. This means they reflect past price action rather than predicting future price movements. The Simple Moving Average (SMA) lags more because it weighs all prices equally, while the Exponential Moving Average (EMA) reacts faster to recent changes but still lags behind price action.

See also  Alice Pro CCI MTF v1.2 (Non-Repaint) MetaTrader 4 Indicator

Recalculation

This indicator recalculates on every new tick or bar. While it doesn’t repaint old values, it continuously updates as new price data comes in, ensuring that the moving averages and filters adjust in real-time.

Customization and Parameters

The indicator allows for some degree of customization, which is controlled through its input parameters. One of the main customizable features is the period used in calculating the moving averages. This period represents the number of bars or candlesticks over which the average is calculated. A longer period will smooth the lines, while a shorter period makes the indicator more sensitive to price changes.

Another key parameter is the price type. As mentioned earlier, you can select whether the indicator should base its calculations on the opening, closing, high, or low prices of each bar. Depending on your trading strategy, this flexibility can be crucial in tailoring the indicator to your needs.

When Might This Indicator Be Useful?

It can be useful for traders who want to see price trends and identify potential areas of price convergence or divergence. The combination of the SMA, EMA, and Custom Filter offers a smoother and potentially more informative representation of market movements.

Key Takeaways

  • Simple Moving Average (SMA) gives a straightforward trend view but lags due to equal weighting of prices.
  • Exponential Moving Average (EMA) reacts more quickly by emphasizing recent price changes.
  • Custom Filter (CF) adjusts based on both the SMA and EMA to reduce noise and refine the trend signal.
  • Non-repaint ensures historical data remains unchanged, but the indicator will recalculate with new data.
  • Price type and period parameters offer flexibility to adapt to different strategies.

Conclusion

This Meta Cluster Filter Price Indicator is designed to provide a clear visual representation of price trends by using a combination of standard moving averages and a custom filter. While it doesn’t predict future price movements, its value lies in offering a refined view of price behavior over time, helping traders understand where trends might be forming.

Leave a Comment