Fisher_m11
Download scriptThis script is a specialized technical analysis tool designed to help traders visualize market momentum and trend direction. It processes historical price data to create a visual "Fisher" indicator, which highlights whether the current market sentiment is leaning toward an upward or downward move.
Core Logic and Workflow
The indicator operates by analyzing specific price movements over a defined timeframe (the "Range") and then applying a multi-layered smoothing process to filter out market noise. Here is the step-by-step logic:
1. Identifying Market Boundaries The script first looks back at a specific number of bars to identify the highest high and the lowest low within that period. By establishing these boundaries, it determines the "Greatest Range" of the current price action.
2. Calculating Relative Price Position Once the boundaries are known, the script finds the midpoint of the current price bar. It then calculates where this midpoint sits relative to the high and low of the range. This is converted into a numerical value:
- A position near the top of the range results in a higher positive number.
- A position near the bottom of the range results in a lower negative number.
- This allows the script to see not just if the price is moving, but how "strongly" it is positioned within its recent history.
3. Dual-Layer Smoothing To prevent the indicator from reacting too wildly to minor, insignificant price flickers (market noise), the script applies two distinct layers of smoothing:
- Price Smoothing: The initial relative position is blended with previous data points based on a user-defined factor. This ensures that a single erratic candle doesn't cause a massive jump in the indicator.
- Index Smoothing: After the first calculation, the resulting "Fisher Index" undergoes a second round of smoothing. This creates a fluid, continuous line that clearly reveals the underlying trend.
4. Trend Identification and Visual Output The final step is the translation of these numbers into a visual histogram:
- Upward Trend: If the final calculated value is positive (above zero), the script identifies an upward trend and displays a Lime-colored histogram.
- Downward Trend: If the final value is negative (below zero), the script identifies a downward trend and displays a Red-colored histogram.
Summary for the User
In simple terms, this tool acts as a "momentum filter." It takes the raw movement of price, calculates where the price is sitting relative to its recent highs and lows, and smooths out the "jitter" of the market. The result is a clean visual cue: when the histogram is Lime, the momentum is technically bullish; when it is Red, the momentum is technically bearish.
//+------------------------------------------------------------------+
//| Fisher_m11.mq4 |
//| Copyright © 23.07.2006 MartinG |
//| http://home.arcor.de/cam06/fisher |
//+------------------------------------------------------------------+
#property copyright "Copyright © 23.07.2006 MartinG"
#property link "http://home.arcor.de/cam06/fisher"
#property indicator_separate_window
//#property indicator_minimum -1
//#property indicator_maximum 1
#property indicator_buffers 3
#property indicator_color2 Lime
#property indicator_color3 Red
#property indicator_width2 4
#property indicator_width3 4
int LeftNum1=56;
int LeftNum2=56;
extern int RangePeriods=10;
extern double PriceSmoothing=0.3; // =0.67 bei Fisher_m10
extern double IndexSmoothing=0.3; // =0.50 bei Fisher_m10
string ThisName="Fisher_m11";
int DrawStart;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorBuffers(4);
SetIndexLabel(0,"Fish");
SetIndexStyle(0,DRAW_NONE);
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexStyle(2,DRAW_HISTOGRAM);
SetIndexBuffer(2,ExtMapBuffer3);
SetIndexStyle(3,DRAW_NONE);
SetIndexBuffer(3,ExtMapBuffer4);
string Text=ThisName;
Text=Text+" (rPeriods "+RangePeriods;
Text=Text+", pSmooth "+DoubleToStr(PriceSmoothing,2);
Text=Text+", iSmooth "+DoubleToStr(IndexSmoothing,2);
Text=Text+") ";
IndicatorShortName(Text);
SetIndexLabel(1,NULL);
SetIndexLabel(2,NULL);
DrawStart=2*RangePeriods+4; // DrawStart= BarNumber calculated from left to right
SetIndexDrawBegin(1,DrawStart);
SetIndexDrawBegin(2,DrawStart);
if (PriceSmoothing>=1.0)
{
PriceSmoothing=0.9999;
Alert("Fish61: PriceSmothing factor has to be smaller 1!");
}
if (PriceSmoothing<0)
{
PriceSmoothing=0;
Alert("Fish61: PriceSmothing factor mustn''t be negative!");
}
if (IndexSmoothing>=1.0)
{
IndexSmoothing=0.9999;
Alert("Fish61: PriceSmothing factor has to be smaller 1!");
}
if (IndexSmoothing<0)
{
IndexSmoothing=0;
Alert("Fish61: PriceSmothing factor mustn''t be negative!");
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
if (Bars<DrawStart)
{
Alert("Fish84: Not enough Bars loaded to calculate FisherIndicator with RangePeriods=",RangePeriods);
return(-1);
}
//----
int counted_bars=IndicatorCounted();
if (counted_bars<0) return(-1);
if (counted_bars>0) counted_bars--;
//----
int Position=Bars-counted_bars; // Position = BarPosition calculated from right to left
int LeftNum1=Bars-Position; // when more bars are loaded the Position of a bar changes but not its LeftNum
if (LeftNum1<RangePeriods+1)Position=Bars-RangePeriods-1;
while(Position>=0)
{
CalculateCurrentBar(Position);
Position--;
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| Single Bar Calculation function |
//+------------------------------------------------------------------+
int CalculateCurrentBar(int pos)
{
double LowestLow, HighestHigh, GreatestRange, MidPrice;
double PriceLocation, SmoothedLocation, FishIndex, SmoothedFish;
//----
LowestLow = Low[Lowest(NULL,0,MODE_LOW,RangePeriods,pos)];
HighestHigh = High[Highest(NULL,0,MODE_HIGH,RangePeriods,pos)];
if (HighestHigh-LowestLow<0.1*Point)HighestHigh=LowestLow+0.1*Point;
GreatestRange=HighestHigh-LowestLow;
MidPrice = (High[pos]+Low[pos])/2;
// PriceLocation in current Range
if (GreatestRange!=0)
{
PriceLocation=(MidPrice-LowestLow)/GreatestRange;
PriceLocation= 2.0*PriceLocation - 1.0; // -> -1 < PriceLocation < +1
}
// Smoothing of PriceLocation
ExtMapBuffer4[pos]=PriceSmoothing*ExtMapBuffer4[pos+1]+(1.0-PriceSmoothing)*PriceLocation;
SmoothedLocation=ExtMapBuffer4[pos];
if (SmoothedLocation> 0.99) SmoothedLocation= 0.99; // verhindert, dass MathLog unendlich wird
if (SmoothedLocation<-0.99) SmoothedLocation=-0.99; // verhindert, dass MathLog minuns unendlich wird
// FisherIndex
if(1-SmoothedLocation!=0) FishIndex=MathLog((1+SmoothedLocation)/(1-SmoothedLocation));
else Alert("Fisher129: Unerlaubter Zustand bei Bar Nummer ",Bars-pos);
// Smoothing of FisherIndex
ExtMapBuffer1[pos]=IndexSmoothing*ExtMapBuffer1[pos+1]+(1.0-IndexSmoothing)*FishIndex;
if (Bars-pos<DrawStart)ExtMapBuffer1[pos]=0;
SmoothedFish=ExtMapBuffer1[pos];
if (SmoothedFish>0) // up trend
{
ExtMapBuffer2[pos]=SmoothedFish;
ExtMapBuffer3[pos]=0;
}
else // else down trend
{
ExtMapBuffer2[pos]=0;
ExtMapBuffer3[pos]=SmoothedFish;
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments