StochasticRVI_v1
Download scriptThe Stochastic RVI is a technical analysis indicator designed to help traders identify momentum and potential price reversals by combining two distinct mathematical concepts: the Relative Vigor Index (RVI) and Stochastic oscillators.
Core Logic Breakdown
The indicator functions by processing market data through three primary stages:
1. Measuring Market Energy (The RVI Component) The script first looks at the relationship between a security's price movement (the difference between the opening and closing prices) and its total volatility (the range between the highest high and lowest low).
- It uses a weighted average to calculate these values, giving slightly more importance to the most recent candles.
- By dividing the price "energy" by the "volatility," the indicator determines the strength of the current trend. This helps distinguish whether a price move is driven by solid momentum or simply wide, erratic fluctuations.
2. Normalizing the Movement (The Stochastic Component) Once the RVI value is established, the script evaluates it over a specific timeframe (determined by the "Length" setting).
- It identifies the highest and lowest RVI values within that period.
- It then calculates where the current RVI sits relative to those extremes. This "normalizes" the data into a readable scale, making it easier to see if the momentum is currently at an extreme peak or a deep valley compared to recent history.
3. Smoothing and Signal Generation To filter out "noise" and prevent the indicator from reacting too erratically to minor price flickers, the script applies two final refinements:
- Weighted Smoothing: The result is passed through a weighted moving average. This ensures that the final line on your chart moves smoothly while still prioritizing the most recent data points.
- The Trigger Line: Finally, the script generates a "Trigger" line. This serves as a secondary reference point derived from the smoothed data, allowing traders to observe the relationship between current momentum and its immediate preceding values.
Summary for the Trader
In practical terms, this indicator doesn't just show you where the price is; it shows you the quality of the move. By combining RVI's ability to measure trend strength with the Stochastic oscillator's ability to identify overbought or oversold conditions, the script provides a visual representation of whether a trend is gaining healthy momentum or becoming exhausted.
//+------------------------------------------------------------------+
//| StochasticRVI.mq4 |
//| |
//| Stochastic RVI |
//| |
//| Algorithm taken from book |
//| "Cybernetics Analysis for Stock and Futures" |
//| by John F. Ehlers |
//| |
//| contact@mqlsoft.com |
//| http://www.mqlsoft.com/ |
//+------------------------------------------------------------------+
#property copyright "Coded by Witold Wozniak"
#property link "www.mqlsoft.com"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_level1 0
#property indicator_minimum -1
#property indicator_maximum 1
double StocRVI[];
double Trigger[];
double RVI[];
double Value1[];
double Value2[];
double Value3[];
extern int Length = 8;
int buffers = 0;
int drawBegin = 0;
int init() {
drawBegin = Length;
initBuffer(StocRVI, "Stochastic RVI", DRAW_LINE);
initBuffer(Trigger, "Trigger", DRAW_LINE);
initBuffer(RVI);
initBuffer(Value1);
initBuffer(Value2);
initBuffer(Value3);
IndicatorBuffers(buffers);
IndicatorShortName("Stochastic RVI [" + Length + "]");
return (0);
}
int start() {
if (Bars <= drawBegin) return (0);
int countedBars = IndicatorCounted();
if (countedBars < 0) return (-1);
if (countedBars > 0) countedBars--;
int s, limit = Bars - countedBars - 1;
for (s = limit; s >= 0; s--) {
Value1[s] = ((Close[s] - Open[s]) +
2.0 * (Close[s + 1] - Open[s + 1]) +
2.0 * (Close[s + 2] - Open[s + 2]) +
(Close[s + 3] - Open[s + 3])) / 6.0;
Value2[s] = ((High[s] - Low[s]) +
2.0 * (High[s + 1] - Low[s + 1]) +
2.0 * (High[s + 2] - Low[s + 2]) +
(High[s + 3] - Low[s + 3])) / 6.0;
double Num = 0.0;
double Denom = 0.0;
for (int count = 0; count < Length; count++) {
Num += Value1[s + count];
Denom += Value2[s + count];
}
if (Denom != 0.0) {
RVI[s] = Num / Denom;
} else {
RVI[s] = 0.0;
}
double rvi = RVI[s];
double hh = rvi, ll = rvi;
for (int i = 0; i < Length; i++) {
double tmp = RVI[s + i];
hh = MathMax(hh, tmp);
ll = MathMin(ll, tmp);
}
Value3[s] = 0.0;
if (hh != ll) {
Value3[s] = (rvi - ll) / (hh - ll);
}
StocRVI[s] = (4.0 * Value3[s] + 3.0 * Value3[s + 1] + 2.0 * Value3[s + 2] + Value3[s + 3]) / 10.0;
StocRVI[s] = 2.0 * (StocRVI[s] - 0.5);
Trigger[s] = 0.96 * (StocRVI[s + 1] + 0.02);
}
return (0);
}
void initBuffer(double array[], string label = "", int type = DRAW_NONE, int arrow = 0, int style = EMPTY, int width = EMPTY, color clr = CLR_NONE) {
SetIndexBuffer(buffers, array);
SetIndexLabel(buffers, label);
SetIndexEmptyValue(buffers, EMPTY_VALUE);
SetIndexDrawBegin(buffers, drawBegin);
SetIndexShift(buffers, 0);
SetIndexStyle(buffers, type, style, width);
SetIndexArrow(buffers, arrow);
buffers++;
}
Comments