Author: Copyright � 2006, MetaQuotes Software Corp.
ParMA_BB

This technical tool is designed to provide a more advanced method of tracking price trends compared to standard moving averages. Rather than simply averaging past prices, it uses mathematical modeling to project where the price is headed based on its current trajectory.

Core Functionality

The primary purpose of this script is to calculate a Parabolic Moving Average (ParMA). While a typical moving average looks backward to tell you what has happened, this parabolic approach treats price movement as a curve. By calculating the "curvature" of recent price action, it attempts to identify the underlying momentum more smoothly.

Key Components

The logic is divided into two main layers:

1. The Parabolic Calculation (The Core) Instead of basic addition and division, the script uses a method called Parabolic Regression. It analyzes a specific window of recent price data (defined by the "Period" setting) to determine three specific coefficients. These coefficients allow the script to fit a mathematical curve to the market data.

  • The final value provided is a projection that accounts for both the current price and its acceleration/deceleration over time.

2. Bollinger Band Integration (The Optional Layer) The script includes an optional feature that adds "Bands" to the ParMA line.

  • Standard Deviation: When enabled, the script measures how much the price is fluctuating away from the average.
  • Upper and Lower Bands: It calculates a "buffer zone" based on this volatility. This helps traders visualize whether the current price is behaving normally or if it is moving into an extreme territory (potentially indicating overbought or oversold conditions).

Visual and Data Output

  • The Main Line: A smooth curve representing the Parabolic Moving Average.
  • The Bands: If enabled, two additional lines appear above and below the main curve to show the volatility boundaries.
  • On-Screen Dashboard: The script provides a real-time text display on your chart, showing the exact numerical values for the ParMA, the Upper Band, and the Lower Band simultaneously.

Summary of Behavior

In simple terms, this tool ignores "noise" by modeling the market as a curve rather than a series of jagged lines. It tells you not just where the price was, but helps define the path the price is currently carving out based on its recent momentum and volatility.

Miscellaneous
Implements a curve of type %1
7 Views
0 Downloads
0 Favorites
ParMA_BB
//+------------------------------------------------------------------+
//|                                                     ParMA_BB.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
 
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 BlueViolet // main line
#property indicator_color2 DodgerBlue // upper band
#property indicator_color3 DodgerBlue // lower band
//---- input parameters
extern int ParMA_Period  = 30;
extern bool BandsEnabled = false;
extern double BandsDev   = 1.0;
//---- buffers
double ParMABuffer[];
double UpperBandBuffer[];
double LowerBandBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
 {
  if (ParMA_Period <= 1) // fool-proof & to prevent zero divide error
   { ParMA_Period = 3; } 
 //---- indicators
  IndicatorDigits(Digits);
  //
  SetIndexStyle(0, DRAW_LINE);
  SetIndexBuffer(0, ParMABuffer);
  SetIndexLabel(0, "ParMA Line");
  SetIndexDrawBegin(0, ParMA_Period);
  //
  if (BandsEnabled == true) // initialize Bollinger Bands buffers, if allowed
  {
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, UpperBandBuffer);
   SetIndexLabel(1, "ParMA Upper Band");
   SetIndexDrawBegin(1, ParMA_Period);
   //
   SetIndexStyle(2, DRAW_LINE);
   SetIndexBuffer(2, LowerBandBuffer);
   SetIndexLabel(2, "ParMA Lower Band");
   SetIndexDrawBegin(2, ParMA_Period);
  }
 //----
  return(0);
 }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
 {
 //----
  Comment(""); // remove comment when finished; see notes below
 //----
  return(0);
 }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
 {
  int counted_bars = IndicatorCounted();
  int Limit, cnt, i, k;
  double old_val, new_val, sum, std_dev;
 //----
  if (counted_bars < 0) { return(-1); } // to prevent possible erors
  Limit = Bars - counted_bars;
  //
  if (Limit > ParMA_Period) // run once when getting started
   { cnt = Limit - ParMA_Period; }
  else                     // run elsewhere
   { cnt = Limit; }
  // calculate ParMA - one step on time-serie bars array
  for (i=cnt; i>=0; i--)
   { ParMABuffer[i] = GetParMA(i, ParMA_Period); }
    //
  if (BandsEnabled == true) // draw Bollinger Bands, if allowed
   {
    // calculate standard deviation
    i = Bars - ParMA_Period;
    if (counted_bars > (ParMA_Period - 1)) 
     { i = Bars - counted_bars - 1; }
    while (i >= 0)
     {
      sum = 0.0;
      k = i + ParMA_Period - 1;
      old_val = ParMABuffer[i];
      while (k >= i)
       {
        new_val = Close[k] - old_val;
        sum += new_val * new_val;
        k--;
       }
      std_dev = MathSqrt(sum / ParMA_Period);
      // complete BB's buffers
      UpperBandBuffer[i] = old_val + BandsDev * std_dev;
      LowerBandBuffer[i] = old_val - BandsDev * std_dev;
      i--;
     }
    // optional - may be deleted without hesitations
    // if you did it, remove 'Comment("");' from deinit() procedure too
    Comment("ParMA = ", NormalizeDouble(ParMABuffer[0], Digits), "\n",
            "UpperBand = ", NormalizeDouble(UpperBandBuffer[0], Digits), "\n",
            "LowerBand = ", NormalizeDouble(LowerBandBuffer[0], Digits));
   }
  // optional - may be deleted without hesitations
  // if you did it, remove 'Comment("");' from deinit() procedure too
  if (BandsEnabled != true)
   { Comment("ParMA = ", NormalizeDouble(ParMABuffer[0], Digits)); }
 //----
  return(0);
 }
//+------------------------------------------------------------------+
/*
 Parabolic approximation: y(x) = b0 + b1 * x + b2 * x^2;
 To obtain coefficients b0, b1, b2 we have to solve a linear system:
 b0 * N          + b1 * Sum(x,N)   + b2 * Sum(x^2,N) = Sum(y,N);
 b0 * Sum(x,N)   + b1 * Sum(x^2,N) + b2 * Sum(x^3,N) = Sum((x*y),N);
 b0 * Sum(x^2,N) + b1 * Sum(x^3,N) + b2 * Sum(x^4,N) = Sum(((x^2)*y),N);
 that can easily be done explicitly by hands.
*/
//+------------------------------------------------------------------+
double GetParMA(int shift, int ma_period)
 {
  static int ro_cnt = 1; // run-once counter
  static double sum_x = 0.0, sum_x2 = 0.0, sum_x3 = 0.0, sum_x4 = 0.0;
  int i, loop_begin; // counters
  double sum_y, sum_xy, sum_x2y, var_tmp;
  double A, B, C, D, E, F, K, L, M, P, Q, R, S; // intermediates
  double B0, B1, B2; // parabolic regression coefficients
  double ret_val;    // value to be returned - parabolic MA
 //----
  // initial accumulation - run once when getting started
  while (ro_cnt <= ma_period)
   {
    var_tmp  = ro_cnt;
    sum_x   += var_tmp; // sum(x)
    var_tmp *= ro_cnt;
    sum_x2  += var_tmp; // sum(x^2)
    var_tmp *= ro_cnt;
    sum_x3  += var_tmp; // sum(x^3)
    var_tmp *= ro_cnt;
    sum_x4  += var_tmp; // sum(x^4)
    ro_cnt++;
   }
  // main calculation loop
  loop_begin = shift + ma_period - 1;
  sum_y   = 0.0;
  sum_xy  = 0.0;
  sum_x2y = 0.0;
  for (i = 1; i<=ma_period; i++)
   {
    var_tmp  = Close[loop_begin-i+1];
    sum_y   += var_tmp;
    sum_xy  += i * var_tmp;     // sum(x*y)
    sum_x2y += i * i * var_tmp; // sum((x^2)*y)
   }
  // initialization
  A = ma_period;
  B = sum_x; C = sum_x2; F = sum_x3;
  M = sum_x4; P = sum_y; R = sum_xy; S = sum_x2y;
  // intermediates
  D = B; E = C; K = C; L = F;
  Q = D / A; E = E - Q * B; F = F - Q * C;
  R = R - Q * P; Q = K / A; L = L - Q * B;
  M = M - Q * C; S = S - Q * P; Q = L / E;
  // calculate regression coefficients
  B2 = (S - R * Q) / (M - F * Q);
  B1 = (R - F * B2) / E;
  B0 = (P - B * B1 - C * B2) / A;
  // value to be returned - parabolic MA
  ret_val = B0 + (B1 + B2 * A) * A;
 //----
  return(ret_val);
 }
//+------------------------------------------------------------------+

Comments