This tool is designed to help traders visualize the "flow of money" in a financial market. Rather than just looking at price movement, it analyzes the relationship between trading volume and price trends to determine whether buying pressure or selling pressure is currently dominant.
How the Logic Works
The script functions by calculating a specific momentum value based on several key factors:
1. Price Positioning (Typical Price) Instead of relying solely on the closing price, the tool calculates a "typical price" for every candle. This is done by averaging the highest point, the lowest point, and the closing price of each period. This provides a more balanced view of the market's reach during that timeframe.
2. Volume-Weighted Movement The core logic looks at whether this typical price is rising or falling compared to the previous period.
- If the price is moving upward, it assigns the traded volume as "positive flow."
- If the price is moving downward, it assigns that same volume as "negative flow."
By multiplying the volume by the price level, the script creates a weighted score of how much money is moving into the asset versus how much is moving out.
3. The Momentum Index (MFI) The tool then compares these two totals—the total positive flow and the total negative flow—over a user-defined period (e.g., 12 candles). This comparison produces a percentage value ranging from 0 to 100:
- A high score toward 100 suggests that buying pressure is significantly outweighing selling pressure.
- A low score toward 0 suggests that selling pressure is dominating the market.
Automated Alerts and Thresholds
To make this data actionable, the script includes built-in "Overbought" and "Oversold" boundaries. These act as safety zones to identify potential price extremes:
- Overbought Signals: When the flow of money reaches a high threshold (defaulting to 84), it indicates that the market may be overextended to the upside. If the indicator drops back below this level from above, the script can trigger a "Sell" alert.
- Oversold Signals: When the flow of money drops to a low threshold (defaulting to 16), it suggests the market may be oversaturated on the downside. If the indicator rises back above this level from below, the script can trigger a "Buy" alert.
In short, this script filters out market "noise" by focusing on the actual volume of money moving behind the price action, providing traders with a clearer picture of market sentiment and potential reversal points.
//+------------------------------------------------------------------+
//| Money Flow Index.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 3
#property indicator_color1 DodgerBlue
#property indicator_color2 LightGray
#property indicator_color3 LightGray
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_DOT
#property indicator_style3 STYLE_DOT
//---- input parameters
extern int MFIPeriod=12;
extern int ApplyTo=0;
extern bool AlertMode=true;
extern int OverBought=84;
extern int OverSold=16;
//---- buffers
double MFIBuffer[];
double MFIOBBuffer[];
double MFIOSBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string sShortName;
//---- indicator lines
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,MFIBuffer);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,MFIOBBuffer);
SetIndexStyle(2,DRAW_LINE);
SetIndexBuffer(2,MFIOSBuffer);
//---- name for DataWindow and indicator subwindow label
sShortName="MFI-Alert("+MFIPeriod+")";
IndicatorShortName(sShortName);
SetIndexLabel(0,sShortName);
SetIndexLabel(1,"OverBought");
SetIndexLabel(2,"OverSold");
//---- first values aren't drawn
SetIndexDrawBegin(0,MFIPeriod);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Money Flow Index |
//+------------------------------------------------------------------+
int start()
{
int i,j,nCountedBars;
double dPositiveMF,dNegativeMF,dCurrentTP,dPreviousTP;
//---- insufficient data
if(Bars<=MFIPeriod) return(0);
//---- bars count that does not changed after last indicator launch.
nCountedBars=IndicatorCounted();
//----
i=Bars-MFIPeriod-1;
if(nCountedBars>MFIPeriod)
i=Bars-nCountedBars-1;
while(i>=0)
{
dPositiveMF=0.0;
dNegativeMF=0.0;
dCurrentTP=(High[i]+Low[i]+Close[i])/3;
for(j=0; j<MFIPeriod; j++)
{
dPreviousTP=(High[i+j+1]+Low[i+j+1]+Close[i+j+1])/3;
if(dCurrentTP>dPreviousTP)
dPositiveMF+=Volume[i+j]*dCurrentTP;
else
{
if(dCurrentTP<dPreviousTP)
dNegativeMF+=Volume[i+j]*dCurrentTP;
}
dCurrentTP=dPreviousTP;
}
//----
if(dNegativeMF!=0.0)
MFIBuffer[i]=100-100/(1+dPositiveMF/dNegativeMF);
else
MFIBuffer[i]=100;
//----
i--;
}
if(AlertMode)
{
if(MFIBuffer[1]<OverBought && MFIBuffer[0]>=OverBought)
Alert("MFI "+MFIPeriod+ ", Sell @ Level "+OverBought+" - "+Symbol()+" M"+Period()+" @ "+DoubleToStr(Bid,Digits)+"");
else if(MFIBuffer[1]>OverSold && MFIBuffer[0]<=OverSold)
Alert("MFI "+MFIPeriod+ ", Buy @ Level "+OverSold+" - "+Symbol()+" M"+Period()+" @ "+DoubleToStr(Bid,Digits)+"");
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments