afl_winner
Download scriptOverview of the "Winner" Indicator Logic
The Winner indicator is designed to help traders visualize market momentum and trend direction by analyzing the relationship between price action and trading volume. Instead of looking at simple price movements, it calculates a weighted perspective of the market to distinguish between bullish (upward) and bearish (downward) pressure.
The logic follows a structured multi-step process:
1. Price and Volume Integration
The script begins by calculating a specialized price point for every bar on the chart. Rather than using just the closing price, it creates a custom average that combines the High, Low, and Closing prices. It then takes this value and weights it against the actual trading volume. By doing this, the indicator ensures that periods of high activity carry more weight in the calculation than periods of low activity.
2. Momentum Range Calculation
Once the volume-weighted price is established, the script identifies the highest and lowest values over a specific lookback period (defined by the user settings). It then calculates where the current price sits within that range as a percentage. This essentially creates a "momentum scale," showing whether the market is currently leaning toward the top or bottom of its recent range.
3. Smoothing and Trend Analysis
To remove "noise" and prevent the indicator from jumping erratically, the script applies two consecutive layers of linear weighting (Moving Averages). This smoothing process helps to clarify the underlying trend by filtering out minor, insignificant price fluctuations.
4. Visual Representation (The Histogram)
The final output is displayed as a three-part histogram that provides a clear visual cue:
- Bullish Signal: When the primary momentum line rises above its secondary smoothed line, the indicator displays a positive signal (Lime). This suggests that upward pressure is strengthening.
- Bearish Signal: When the primary momentum line falls below the secondary smoothed line, the indicator displays a negative signal (Red), suggesting that downward pressure is taking over.
- Zero Line/Baseline: The script uses a central reference point to help traders instantly identify the "breakout" moment where the trend shifts from one direction to the other.
Summary for the User: This indicator acts as a momentum tracker. It tells you not just what the price is doing, but how much "effort" (volume) is behind the move. When the histogram changes color or crosses the baseline, it signals a shift in market sentiment between buyers and sellers.
//+------------------------------------------------------------------+
//| AFL_Winner.mq4 |
//| avoitenko |
//| https://login.mql5.com/en/users/avoitenko |
//+------------------------------------------------------------------+
#property copyright ""
#property link "https://login.mql5.com/en/users/avoitenko"
#property indicator_separate_window
#property indicator_buffers 3
//---
#property indicator_color1 Lime
#property indicator_width1 3
#property indicator_style1 STYLE_SOLID
//---
#property indicator_color2 Red
#property indicator_width2 3
#property indicator_style2 STYLE_SOLID
//---
#property indicator_color3 Black
#property indicator_width3 3
#property indicator_style3 STYLE_SOLID
//--- extern
extern int PERIOD = 10;
extern int AVERAGE = 5;
//--- buffers
double BullHBuffer[];
double BearHBuffer[];
double ZeroBuffer[];
double pa[];
double pa5[];
double rsv[];
double pak[];
double pad[];
//--- global vars
int i, k;
int offset;
double scost5;
double svolume5;
double max,min;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//--- check input parameters
if(PERIOD < 2) PERIOD = 2;
if(AVERAGE < 2) AVERAGE = 2;
offset = PERIOD + AVERAGE*AVERAGE;
IndicatorBuffers(8);
//--- buffers
SetIndexBuffer(0, BullHBuffer);
SetIndexBuffer(1, BearHBuffer);
SetIndexBuffer(2, ZeroBuffer);
SetIndexBuffer(3, pa);
SetIndexBuffer(4, pa5);
SetIndexBuffer(5, rsv);
SetIndexBuffer(6, pak);
SetIndexBuffer(7, pad);
//---
SetIndexStyle(0,DRAW_HISTOGRAM);
SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexStyle(2,DRAW_HISTOGRAM);
//---
SetIndexLabel(0,"Bull High");
SetIndexLabel(1,"Bear High");
SetIndexLabel(2,"Low");
//---
SetIndexEmptyValue(0,0);
SetIndexEmptyValue(1,0);
SetIndexEmptyValue(2,0);
//---
IndicatorDigits(2);
IndicatorShortName("Winner (" + PERIOD + ", " + AVERAGE + ") ");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars = IndicatorCounted();
int limit;
if(counted_bars<0)return(0);
if(counted_bars==0)
{
limit= Bars-offset;
ArrayInitialize(BullHBuffer,0);
ArrayInitialize(BearHBuffer,0);
ArrayInitialize(ZeroBuffer,0);
}
else limit = Bars-counted_bars-1;
//--- main cycle
for(i=limit; i>=0; i--)
{
pa[i] = (2*Close[i]+High[i]+Low[i])/4;
scost5=0;
for(k=0; k < AVERAGE; k++)
scost5 += Volume[i+k]*pa[i+k];
svolume5=0;
for(k=0; k < AVERAGE; k++)
svolume5 += Volume[i+k];
if(svolume5==0)continue;
pa5[i] = scost5/svolume5;
min = LLV(pa5,i,PERIOD);
max = HHV(pa5,i,PERIOD);
rsv[i] = ((pa5[i] - min)/MathMax(max-min,Point))*100;
}
//--- wma
for(i=limit; i>=0; i--)
pak[i] = iMAOnArray(rsv,0,AVERAGE,0,MODE_LWMA,i);
for(i=limit; i>=0; i--)
pad[i] = iMAOnArray(pak,0,AVERAGE,0,MODE_LWMA,i);
//--- histo
for(i=limit; i>=0; i--)
{
if(pak[i]>pad[i])
{
BullHBuffer[i]=pak[i];
ZeroBuffer[i]=pad[i];
BearHBuffer[i]=0;
}
else
{
BearHBuffer[i]=pad[i];
ZeroBuffer[i]=pak[i];
BullHBuffer[i]=0;
}
}
//---
return(0);
}
//+------------------------------------------------------------------+
//| LLV |
//+------------------------------------------------------------------+
double LLV(double &buffer[],int index, int period)
{
int total = ArraySize(buffer);
double min = buffer[index];
for(int i = index+1; i<MathMin(index+period,total); i++)
if(buffer[i] < min) min = buffer[i];
return(min);
}
//+------------------------------------------------------------------+
//| HHV |
//+------------------------------------------------------------------+
double HHV(double &buffer[],int index, int period)
{
int total = ArraySize(buffer);
double max = buffer[index];
for(int i=index+1; i<MathMin(index+period,total); i++)
if(buffer[i] > max) max = buffer[i];
return(max);
}
//+------------------------------------------------------------------+
Comments