The Vortex Oscillator is a technical analysis tool designed to help traders identify the strength and direction of market momentum. Unlike standard indicators that might simply show where a price is going, this specific version acts as an "oscillator," meaning it focuses on the relative difference between upward and downward price movements to create a clearer picture of market sentiment.
How the Logic Works
The tool operates by breaking down price action into two distinct components: positive momentum (upward movement) and negative momentum (downward movement). Here is the step-by-step process it uses to generate its readings:
1. Identifying Movement Extremes The script looks at the relationship between a candle's high and low points relative to the previous day's price.
- To measure positive potential, it calculates the distance between today's high and yesterday's low.
- To measure negative potential, it calculates the distance between today's low and yesterday's high.
2. Smoothing the Data Because individual price fluctuations can be "noisy" or erratic, the script doesn't just look at a single moment in time. It takes the user-defined length (defaulting to 14 periods) and adds up all those positive and negative movements over that timeframe. This creates a much smoother, more reliable trend line by filtering out minor price spikes.
3. Normalizing against Market Volatility To ensure the indicator remains accurate regardless of whether the market is highly volatile or very calm, the script incorporates a "True Range" calculation. By dividing both the positive and negative momentum sums by this True Range, the tool "normalizes" the data. This ensures that the resulting values are comparable across different market conditions.
4. The Final Output (The Oscillator) Finally, the script subtracts the normalized negative momentum from the normalized positive momentum.
- When the result is positive, it suggests that upward momentum is stronger than downward pressure.
- When the result is negative, it indicates that downward pressure is dominating the market.
By visualizing this difference as a histogram, traders can more easily see when the momentum is shifting, helping them identify whether a trend is gaining strength or losing steam.
//+------------------------------------------------------------------+
//|Vortex Oscillator.mq4 |
//|An adaptation of the Vortex Indicator described in the |
//|January 2010 issue of Technical Analysis of Stocks & Commodities |
//|This version plots the difference of VI+ - VI- to create an |
//|oscillator indicator, as suggested by Michael Moses. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2009 under Creative Commons BY-SA License by Neil D. Rosenthal & Michael Moses"
#property link "http://creativecommons.org/licenses/by-sa/3.0/"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Blue
#property indicator_level1 0
#property indicator_levelcolor Black
#property indicator_levelstyle STYLE_DOT
//---- Input parameters
extern int VI_Length=14;
//---- Buffers
double VortexOsc[]; //The Vortex Oscialltor - the difference betweeen VI+ and VI-
double PlusVI[]; //VI+ : + Vortex Indicator buffer
double MinusVI[]; //VI- : - Vortex Indicator buffer
double PlusVM[]; //VM+ : + Vortex Movement buffer
double MinusVM[]; //VM- : - Vorext Movement buffer
double SumPlusVM[]; //Sum of VI_Length PlusVM values
double SumMinusVM[]; //Sum of VI_Length MinusVM values
double SumTR[]; //True Range buffer
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
IndicatorBuffers(8);
IndicatorDigits(Digits);
//---- Set visible buffer properties
SetIndexBuffer(0,VortexOsc);
SetIndexStyle(0,DRAW_HISTOGRAM);
SetIndexLabel(0,"Vortex Osc(" + VI_Length + ")");
SetIndexDrawBegin(0,VI_Length);
//---- Set indices of caching buffers
SetIndexBuffer(1,PlusVI);
SetIndexBuffer(2,MinusVI);
SetIndexBuffer(3,PlusVM);
SetIndexBuffer(4,MinusVM);
SetIndexBuffer(5,SumPlusVM);
SetIndexBuffer(6,SumMinusVM);
SetIndexBuffer(7,SumTR);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int Limit;
int CountedBars = IndicatorCounted();
//---- Check for possible errors
if(CountedBars < 0) return(-1);
//---- Last counted bar will be recounted
if(CountedBars > 0) CountedBars--;
Limit = Bars - CountedBars;
//---- Clear caching buffers
for(int i = 0; i < Limit; i++)
{
SumPlusVM[i] = 0;
SumMinusVM[i] = 0;
SumTR[i]= 0;
}
//---- Store the values of PlusVM and MinusVM
for(i = 0; i < Limit; i++)
{
//PlusVM = |Today's High - Yesterday's Low|
PlusVM[i] = MathAbs(High[i] - Low[i + 1]);
//MinusVM = |Today's Low - Yesterday's High|
MinusVM[i] = MathAbs(Low[i] - High[i +1]);
}
//---- Sum VI_Length values of PlusVM, MinusVM and the True Range
for(i = 0; i < Limit; i++)
{
for(int j = 0; j <= VI_Length - 1; j++)
{
SumPlusVM[i] += PlusVM[i + j];
SumMinusVM[i] += MinusVM[i + j];
SumTR[i] += iATR(NULL,0,1,i + j); //Sum VI_Length values of the True Range by using a 1-period ATR
}
}
//---- Draw the indicator
for(i = 0; i < Limit; i++)
{
PlusVI[i] = SumPlusVM[i] / SumTR[i];
MinusVI[i] = SumMinusVM[i] / SumTR[i];
VortexOsc[i] = PlusVI[i] - MinusVI[i];
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments