Inverse Fisher
Download scriptThis tool is designed to help traders identify market momentum by analyzing price movements through a multi-layered mathematical filter. Instead of looking at raw price alone, the script processes the data in stages to smooth out "noise" and highlight significant trends.
How the Logic Works
1. Data Normalization (The Foundation) The process begins by taking the Relative Strength Index (RSI)—a common tool used to measure the speed and change of price movements—and adjusting it into a specific numerical range. By shifting the standard RSI values, the script creates a centered data set that makes it easier to identify whether the market is leaning towards overbought or oversold conditions relative to a neutral midpoint.
2. Trend Smoothing (The Filter) Once the initial data is normalized, the script applies a Weighted Moving Average (WMA). This acts as a smoothing agent; it looks at the recent history of the normalized data and calculates an average that gives more importance to the most recent price actions. This prevents the indicator from reacting too wildly to small, insignificant price flickers, ensuring that only sustained movements are captured.
3. The Inverse Fisher Transformation (The Final Result) The final step involves a complex mathematical calculation known as the "Inverse Fisher" transformation. This takes the smoothed average and converts it into a specific curve. The goal of this conversion is to linearize the data—essentially taking price movements that might be curving or oscillating and stretching them out so they are easier to read visually.
Visual Interpretation
The resulting output is displayed on a separate window with two primary horizontal reference lines:
- Upper Boundary (0.5): When the indicator moves toward this level, it suggests strong upward momentum.
- Lower Boundary (-0.5): When the indicator moves toward this level, it suggests strong downward momentum.
By observing where the main line sits in relation to these boundaries and how it curves over time, traders can get a clearer picture of the market's underlying direction without being distracted by daily price volatility.
//+------------------------------------------------------------------+
//| Inverse Fisher.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Maroon
#property indicator_color2 CornflowerBlue
#property indicator_level1 0.5
#property indicator_level2 -0.5
#property indicator_levelstyle STYLE_DASH
#property indicator_levelcolor Gold
#property indicator_maximum 1
#property indicator_minimum -1
//---- input parameters
extern int RSI_Period=5;
extern int RSI_MA=9;
extern bool SHOW_RSI=false;
//---- buffers
double RSIval[];
double IF[];
double RSI[];
double WMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorBuffers(4);
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,RSIval);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,IF);
SetIndexBuffer(2,RSI);
SetIndexBuffer(3,WMA);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
ObjectDelete("toplevel");
ObjectDelete("botlevel");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//----
int limit,i;
limit = Bars - counted_bars + 1;
for (i = limit; i>=0; i--)
{
RSI[i] = (iRSI(0,0,RSI_Period,PRICE_CLOSE,i)-50.0)/10.0;
if (SHOW_RSI) RSIval[i] = RSI[i]/5.0;
else RSIval[i]=EMPTY_VALUE;
}
for (i = limit; i>=0; i--)
{
WMA[i] = iMAOnArray(RSI,0,RSI_MA,0,MODE_LWMA,i);
IF[i] = (MathExp(2.0*WMA[i])-1.0) / (MathExp(2.0*WMA[i])+1.0);
}
if (ObjectFind("toplevel")==-1)
{
ObjectCreate("toplevel",OBJ_HLINE,1,1,0.5);
ObjectCreate("botlevel",OBJ_HLINE,1,1,-0.5);
ObjectSet("toplevel",OBJPROP_COLOR,Lime);
ObjectSet("botlevel",OBJPROP_COLOR,Red);
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments