MFI smoothed

Author: © mladen, 2018

Okay, here's a breakdown of the script's logic, explained in a way that's easy to understand without needing any programming knowledge.

Overall Purpose

This script is designed to calculate and display a modified version of the Money Flow Index (MFI) on a trading chart. The standard MFI is a technical indicator that uses price and volume data to identify overbought or oversold conditions in a market. This script enhances the MFI by "smoothing" it, which aims to reduce noise and provide clearer signals.

Key Components and How They Work

  1. Inputs (Adjustable Settings):

    • MFI Period: This is the number of past time periods (e.g., days, hours) the script considers when calculating the MFI. A shorter period makes the indicator more sensitive to recent price changes, while a longer period makes it smoother.
    • Smoothing Period: This setting controls how much the MFI is smoothed. A higher value will create a smoother line, potentially reducing false signals but also lagging price movements more.
    • Volume Type: Determines whether the script uses tick volume (number of transactions) or real volume data.
  2. Core Calculation: Smoothed Money Flow Index

    • Calculating Typical Price: For each time period, the script calculates a "typical price" by averaging the high, low, and closing prices.
    • Determining Positive and Negative Money Flow: The script compares the current typical price to the previous one.
      • If the current typical price is higher, it's considered "positive money flow."
      • If the current typical price is lower, it's considered "negative money flow."
      • The script multiplies the typical price by volume for each period when calculating positive and negative money flow.
    • Calculating the MFI: The script uses the positive and negative money flow to calculate the raw MFI value.
    • Smoothing the MFI: Smoothing is applied to the calculated MFI to generate the final smoothed MFI value. This involves using a complex averaging technique that reduces the impact of sudden spikes. Smoothing uses volatility calculations to adapt the smoothing factor dynamically. It looks at recent changes to the price and volume, comparing current volatility with average volatility to adjust the smoothing process.
  3. Visual Display:

    • The script plots the smoothed MFI value as a line on a separate window of the chart.
    • The indicator's color changes based on whether the current smoothed MFI value is higher or lower than the previous smoothed MFI value.
    • Horizontal lines are added at the 20 and 80 levels. These lines are often used as thresholds to identify potential overbought (above 80) or oversold (below 20) conditions.

In essence, this script attempts to provide a clearer, more stable view of market momentum by calculating a Money Flow Index and then smoothing it to reduce noise and highlight potential trading opportunities.

Price Data Components
4 Views
0 Downloads
0 Favorites
MFI smoothed
ÿþ//------------------------------------------------------------------

#property copyright   "© mladen, 2018"

#property link        "mladenfx@gmail.com"

#property version     "1.00"

#property description "Smooth MFI"

//------------------------------------------------------------------

#property indicator_separate_window

#property indicator_buffers 2

#property indicator_plots   1

#property indicator_label1  "Smooth MFI"

#property indicator_type1   DRAW_COLOR_LINE

#property indicator_color1  clrDodgerBlue,clrSandyBrown

#property indicator_width1  2

#property indicator_maximum 100.0

#property indicator_minimum 0.0

#property indicator_level1  20.0

#property indicator_level2  80.0

//

//--- input parameters

//

input int                 inpMfiPeriod  = 14;          // MFI period

input int                 inpSmoPeriod  = 14;          // Smoothing period

input ENUM_APPLIED_VOLUME inpVolumeType = VOLUME_TICK; // Volumes

//

//--- indicator buffers

//

double val[],valc[];

//------------------------------------------------------------------

// Custom indicator initialization function

//------------------------------------------------------------------

int OnInit()

{

   SetIndexBuffer(0,val,INDICATOR_DATA);

   SetIndexBuffer(1,valc,INDICATOR_COLOR_INDEX);

//---

   IndicatorSetString(INDICATOR_SHORTNAME,"Smoothed MFI ("+(string)inpMfiPeriod+","+(string)inpSmoPeriod+")");

   return(INIT_SUCCEEDED);

}

//------------------------------------------------------------------

// Custom indicator de-initialization function

//------------------------------------------------------------------

void OnDeinit(const int reason) { return; }

//------------------------------------------------------------------

// Custom 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 (Bars(_Symbol,_Period)<rates_total) return(-1);

   

   //

   //---

   //



   for (int i=(int)MathMax(prev_calculated-1,0); i<rates_total && !_StopFlag; i++)

   {

      double dPositiveMF=0.0;

      double dNegativeMF=0.0;

      double dCurrentTP=(high[i]+low[i]+close[i])/3;

      for(int j=0; j<inpMfiPeriod && (i-j-1)>=0; j++)

        {

         double dPreviousTP=(high[i-j-1]+low[i-j-1]+close[i-j-1])/3.0;

            if(dCurrentTP>dPreviousTP) dPositiveMF+=(inpVolumeType==VOLUME_TICK?tick_volume[i-j]:volume[i-j])*dCurrentTP;

            if(dCurrentTP<dPreviousTP) dNegativeMF+=(inpVolumeType==VOLUME_TICK?tick_volume[i-j]:volume[i-j])*dCurrentTP;

               dCurrentTP=dPreviousTP;

        }

      val[i]  = iSmooth((dNegativeMF!=0.0) ? 100.0-100.0/(1.0+dPositiveMF/dNegativeMF) : 100.0,inpSmoPeriod,0,i,rates_total);

      valc[i] = (i>0) ? (val[i]<val[i-1]) : 0 ;

   }          

   return(rates_total);

}



//+------------------------------------------------------------------

//| Custom functions

//+------------------------------------------------------------------

#define _smoothInstances     1

#define _smoothInstancesSize 10

double m_wrk[][_smoothInstances*_smoothInstancesSize];

int    m_size=0;

//

//---

//

double iSmooth(double price,double length,double phase,int r,int bars,int instanceNo=0)

  {

   #define bsmax  5

   #define bsmin  6

   #define volty  7

   #define vsum   8

   #define avolty 9



   if(ArrayRange(m_wrk,0)!=bars) ArrayResize(m_wrk,bars); if(ArrayRange(m_wrk,0)!=bars) return(price); instanceNo*=_smoothInstancesSize;

   if(r==0 || length<=1) { int k=0; for(; k<7; k++) m_wrk[r][instanceNo+k]=price; for(; k<10; k++) m_wrk[r][instanceNo+k]=0; return(price); }



//

//---

//



   double len1   = MathMax(MathLog(MathSqrt(0.5*(length-1)))/MathLog(2.0)+2.0,0);

   double pow1   = MathMax(len1-2.0,0.5);

   double del1   = price - m_wrk[r-1][instanceNo+bsmax];

   double del2   = price - m_wrk[r-1][instanceNo+bsmin];

   int    forBar = MathMin(r,10);



   m_wrk[r][instanceNo+volty]=0;

   if(MathAbs(del1) > MathAbs(del2)) m_wrk[r][instanceNo+volty] = MathAbs(del1);

   if(MathAbs(del1) < MathAbs(del2)) m_wrk[r][instanceNo+volty] = MathAbs(del2);

   m_wrk[r][instanceNo+vsum]=m_wrk[r-1][instanceNo+vsum]+(m_wrk[r][instanceNo+volty]-m_wrk[r-forBar][instanceNo+volty])*0.1;



//

//---

//



   m_wrk[r][instanceNo+avolty]=m_wrk[r-1][instanceNo+avolty]+(2.0/(MathMax(4.0*length,30)+1.0))*(m_wrk[r][instanceNo+vsum]-m_wrk[r-1][instanceNo+avolty]);

   double dVolty=(m_wrk[r][instanceNo+avolty]>0) ? m_wrk[r][instanceNo+volty]/m_wrk[r][instanceNo+avolty]: 0;

   if(dVolty > MathPow(len1,1.0/pow1)) dVolty = MathPow(len1,1.0/pow1);

   if(dVolty < 1)                      dVolty = 1.0;



//

//---

//



   double pow2 = MathPow(dVolty, pow1);

   double len2 = MathSqrt(0.5*(length-1))*len1;

   double Kv   = MathPow(len2/(len2+1), MathSqrt(pow2));



   if(del1 > 0) m_wrk[r][instanceNo+bsmax] = price; else m_wrk[r][instanceNo+bsmax] = price - Kv*del1;

   if(del2 < 0) m_wrk[r][instanceNo+bsmin] = price; else m_wrk[r][instanceNo+bsmin] = price - Kv*del2;



//

//---

//



   double corr  = MathMax(MathMin(phase,100),-100)/100.0 + 1.5;

   double beta  = 0.45*(length-1)/(0.45*(length-1)+2);

   double alpha = MathPow(beta,pow2);



   m_wrk[r][instanceNo+0] = price + alpha*(m_wrk[r-1][instanceNo+0]-price);

   m_wrk[r][instanceNo+1] = (price - m_wrk[r][instanceNo+0])*(1-beta) + beta*m_wrk[r-1][instanceNo+1];

   m_wrk[r][instanceNo+2] = (m_wrk[r][instanceNo+0] + corr*m_wrk[r][instanceNo+1]);

   m_wrk[r][instanceNo+3] = (m_wrk[r][instanceNo+2] - m_wrk[r-1][instanceNo+4])*MathPow((1-alpha),2) + MathPow(alpha,2)*m_wrk[r-1][instanceNo+3];

   m_wrk[r][instanceNo+4] = (m_wrk[r-1][instanceNo+4] + m_wrk[r][instanceNo+3]);



//

//---

//



   return(m_wrk[r][instanceNo+4]);



   #undef bsmax

   #undef bsmin

   #undef volty

   #undef vsum

   #undef avolty

  }    

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---