mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-11-02 11:16:15 +00:00
feat: add RVScore_Pro
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RVScore_Calculator.mqh |
|
||||
//| Engine for Rolling Volume-Weighted Z-Score (RV-Score) |
|
||||
//| Copyright 2026, xxxxxxxx|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026, xxxxxxxx"
|
||||
#property version "1.00"
|
||||
|
||||
#ifndef RVSCORE_CALCULATOR_MQH
|
||||
#define RVSCORE_CALCULATOR_MQH
|
||||
|
||||
#include <MyIncludes\Rolling_VWAP_Calculator.mqh>
|
||||
|
||||
//+==================================================================+
|
||||
//| CLASS: CRVScoreCalculator |
|
||||
//| Continuous Statistical Dispersion Engine around Rolling VWAP |
|
||||
//+==================================================================+
|
||||
class CRVScoreCalculator
|
||||
{
|
||||
protected:
|
||||
int m_sigma_period;
|
||||
CRollingVWAPCalculator *m_rolling_vwap_calc;
|
||||
|
||||
// Persistent Buffers for State Preservation
|
||||
double m_vwap_buf[];
|
||||
double m_diff_sq_buf[];
|
||||
|
||||
public:
|
||||
CRVScoreCalculator(void);
|
||||
virtual ~CRVScoreCalculator(void);
|
||||
|
||||
bool Init(const int sigma_period,
|
||||
const ENUM_ROLLING_TYPE rolling_type,
|
||||
const int rolling_window,
|
||||
const ENUM_APPLIED_VOLUME vol_type,
|
||||
const bool is_heikin_ashi = false);
|
||||
|
||||
void Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const datetime &time[],
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
const long &tick_volume[],
|
||||
const long &volume[],
|
||||
double &out_rvscore[]);
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRVScoreCalculator::CRVScoreCalculator(void) :
|
||||
m_sigma_period(20),
|
||||
m_rolling_vwap_calc(NULL)
|
||||
{
|
||||
ArraySetAsSeries(m_vwap_buf, false);
|
||||
ArraySetAsSeries(m_diff_sq_buf, false);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRVScoreCalculator::~CRVScoreCalculator(void)
|
||||
{
|
||||
if(CheckPointer(m_rolling_vwap_calc) != POINTER_INVALID)
|
||||
{
|
||||
delete m_rolling_vwap_calc;
|
||||
m_rolling_vwap_calc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Engine Initialization |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRVScoreCalculator::Init(const int sigma_period,
|
||||
const ENUM_ROLLING_TYPE rolling_type,
|
||||
const int rolling_window,
|
||||
const ENUM_APPLIED_VOLUME vol_type,
|
||||
const bool is_heikin_ashi)
|
||||
{
|
||||
m_sigma_period = (sigma_period < 2) ? 2 : sigma_period;
|
||||
|
||||
if(CheckPointer(m_rolling_vwap_calc) != POINTER_INVALID)
|
||||
{
|
||||
delete m_rolling_vwap_calc;
|
||||
m_rolling_vwap_calc = NULL;
|
||||
}
|
||||
|
||||
if(is_heikin_ashi)
|
||||
m_rolling_vwap_calc = new CRollingVWAPCalculator_HA();
|
||||
else
|
||||
m_rolling_vwap_calc = new CRollingVWAPCalculator();
|
||||
|
||||
if(CheckPointer(m_rolling_vwap_calc) == POINTER_INVALID)
|
||||
return false;
|
||||
|
||||
return m_rolling_vwap_calc.Init(rolling_type, rolling_window, vol_type, true);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Incremental Dispersion Calculation (O(1)) |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRVScoreCalculator::Calculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const datetime &time[],
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
const long &tick_volume[],
|
||||
const long &volume[],
|
||||
double &out_rvscore[])
|
||||
{
|
||||
if(rates_total < 2 || CheckPointer(m_rolling_vwap_calc) == POINTER_INVALID)
|
||||
return;
|
||||
|
||||
// 1. Safe Allocation of Internal Registers
|
||||
if(ArraySize(m_vwap_buf) != rates_total)
|
||||
{
|
||||
ArrayResize(m_vwap_buf, rates_total);
|
||||
ArrayResize(m_diff_sq_buf, rates_total);
|
||||
ArraySetAsSeries(m_vwap_buf, false);
|
||||
ArraySetAsSeries(m_diff_sq_buf, false);
|
||||
}
|
||||
|
||||
if(ArraySize(out_rvscore) != rates_total)
|
||||
{
|
||||
ArrayResize(out_rvscore, rates_total);
|
||||
ArraySetAsSeries(out_rvscore, false);
|
||||
ArrayInitialize(out_rvscore, 0.0);
|
||||
}
|
||||
|
||||
// 2. Compute Continuous Underlying Rolling VWAP Stream
|
||||
m_rolling_vwap_calc.Calculate(rates_total, prev_calculated, time, open, high, low, close,
|
||||
tick_volume, volume, m_vwap_buf);
|
||||
|
||||
int start = (prev_calculated > 0) ? (prev_calculated - 1) : 0;
|
||||
|
||||
// 3. Compute Squared Deviations
|
||||
for(int i = start; i < rates_total; i++)
|
||||
{
|
||||
double diff = close[i] - m_vwap_buf[i];
|
||||
m_diff_sq_buf[i] = diff * diff;
|
||||
}
|
||||
|
||||
// 4. Compute Normalized Sigma Z-Score
|
||||
for(int i = start; i < rates_total; i++)
|
||||
{
|
||||
double sum_sq = 0.0;
|
||||
int count = 0;
|
||||
|
||||
// Sliding lookback across continuous series
|
||||
int lookback_limit = MathMin(i + 1, m_sigma_period);
|
||||
for(int j = 0; j < lookback_limit; j++)
|
||||
{
|
||||
sum_sq += m_diff_sq_buf[i - j];
|
||||
count++;
|
||||
}
|
||||
|
||||
double std_dev = (count > 0) ? MathSqrt(sum_sq / (double)count) : 0.0;
|
||||
|
||||
// Strict Floating-Point Epsilon Guard
|
||||
if(std_dev > 1.0e-9)
|
||||
out_rvscore[i] = (close[i] - m_vwap_buf[i]) / std_dev;
|
||||
else
|
||||
out_rvscore[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RVSCORE_CALCULATOR_MQH
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,572 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RVScore_Pro.mq5|
|
||||
//| Copyright 2026, xxxxxxxx|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026, xxxxxxxx"
|
||||
#property version "3.20"
|
||||
#property description "Statistical RV-Score Oscillator (Rolling VWAP Z-Score)."
|
||||
#property description "Measures standardized dispersion from continuous Volume-Weighted Average Price."
|
||||
|
||||
#property indicator_separate_window
|
||||
#property indicator_buffers 3
|
||||
#property indicator_plots 2
|
||||
|
||||
//--- Plot 1: RV-Score Histogram (Institutional Swapped Thermal Matrix)
|
||||
#property indicator_label1 "RV-Score"
|
||||
#property indicator_type1 DRAW_COLOR_HISTOGRAM
|
||||
// Swapped Palette Index:
|
||||
// 0: Noise/Neutral (Gray)
|
||||
// 1: Bullish Flow (LightSkyBlue)
|
||||
// 2: Bullish Climax (DeepSkyBlue)
|
||||
// 3: Bearish Flow (Coral)
|
||||
// 4: Bearish Climax (OrangeRed)
|
||||
#property indicator_color1 clrGray, clrLightSkyBlue, clrDeepSkyBlue, clrCoral, clrOrangeRed
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 2
|
||||
|
||||
//--- Plot 2: Optional Smoothed Signal Line
|
||||
#property indicator_label2 "Signal"
|
||||
#property indicator_type2 DRAW_LINE
|
||||
#property indicator_color2 clrFireBrick
|
||||
#property indicator_style2 STYLE_SOLID
|
||||
#property indicator_width2 1
|
||||
|
||||
//--- Included Core Engines & Frameworks
|
||||
#include <MyIncludes\RVScore_Calculator.mqh>
|
||||
#include <MyIncludes\MovingAverage_Engine.mqh>
|
||||
#include <MyIncludes\DataSync_Tools.mqh>
|
||||
|
||||
//--- Candle Source Enum
|
||||
#ifndef ENUM_CANDLE_SOURCE_DEFINED
|
||||
#define ENUM_CANDLE_SOURCE_DEFINED
|
||||
enum ENUM_CANDLE_SOURCE
|
||||
{
|
||||
CANDLE_STANDARD, // Standard OHLC Data
|
||||
CANDLE_HEIKIN_ASHI // Heikin Ashi Smoothed Data
|
||||
};
|
||||
#endif
|
||||
|
||||
//--- Inputs
|
||||
input group "--- Timeframe Settings ---"
|
||||
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // Calculation Timeframe (Current or HTF)
|
||||
|
||||
input group "--- Rolling VWAP Engine ---"
|
||||
input ENUM_ROLLING_TYPE InpRollingType = ROLLING_BARS; // Rolling Window Type
|
||||
input int InpRollingWindow = 144; // Rolling Window (Bars or Minutes)
|
||||
input int InpSigmaPeriod = 20; // Volatility Lookback (Sigma)
|
||||
|
||||
input group "--- Calculation Sources ---"
|
||||
input ENUM_APPLIED_VOLUME InpVolumeType = VOLUME_TICK; // Applied Volume Type
|
||||
input ENUM_CANDLE_SOURCE InpCandleSource = CANDLE_STANDARD; // Candle Source
|
||||
|
||||
input group "--- Signal Line Settings ---"
|
||||
input bool InpShowSignal = true; // Show Signal Line?
|
||||
input int InpSignalPeriod = 5; // Signal Period
|
||||
input ENUM_MA_TYPE InpSignalType = EMA; // Signal MA Algorithm
|
||||
input color InpColorSignal = clrFireBrick; // Signal Line Color
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "--- Indicator Levels (Sigma Multiples) ---"
|
||||
input double InpLevelFlowHigh = 1.5; // High Warning Level (Bullish Flow)
|
||||
input double InpLevelFlowLow = -1.5; // Low Warning Level (Bearish Flow)
|
||||
input double InpLevelClimaxHigh = 2.0; // High Climax Level (Bullish Climax)
|
||||
input double InpLevelClimaxLow = -2.0; // Low Climax Level (Bearish Climax)
|
||||
input double InpLevelExtremeHigh = 2.5; // High Exhaustion Level
|
||||
input double InpLevelExtremeLow = -2.5; // Low Exhaustion Level
|
||||
input color InpLevelColor = clrSilver; // Levels Color
|
||||
input ENUM_LINE_STYLE InpLevelStyle = STYLE_DOT; // Levels Style
|
||||
|
||||
//--- Indicator Output Buffers
|
||||
double ExtRVScoreBuffer[];
|
||||
double ExtColorsBuffer[];
|
||||
double ExtSignalBuffer[];
|
||||
|
||||
//--- Volume Internal Cache (For Potential VWMA Signal Calculations)
|
||||
double g_double_volume[];
|
||||
|
||||
//--- HTF Synchronized Data Caches
|
||||
double h_open[], h_high[], h_low[], h_close[];
|
||||
long h_tick_vol[], h_vol[];
|
||||
double h_res_rvscore[], h_res_color[], h_res_signal[];
|
||||
datetime h_time[];
|
||||
|
||||
//--- Global Dynamic Calculation Pointers
|
||||
CRVScoreCalculator *g_calc = NULL;
|
||||
CMovingAverageCalculator *g_signal_calculator = NULL;
|
||||
|
||||
bool g_is_mtf_mode = false;
|
||||
ENUM_TIMEFRAMES g_calc_timeframe;
|
||||
bool g_data_ready = false;
|
||||
bool g_data_synced = false;
|
||||
int g_htf_count = 0;
|
||||
datetime g_last_htf_time = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
g_data_ready = false;
|
||||
g_data_synced = false;
|
||||
g_htf_count = 0;
|
||||
g_last_htf_time = 0;
|
||||
|
||||
// 1. Timeframe Resolution & Guard
|
||||
g_calc_timeframe = InpTimeframe;
|
||||
if(g_calc_timeframe == PERIOD_CURRENT)
|
||||
g_calc_timeframe = (ENUM_TIMEFRAMES)Period();
|
||||
|
||||
if(g_calc_timeframe < Period())
|
||||
{
|
||||
PrintFormat("RV-Score Error: Target timeframe (%s) must be >= current timeframe (%s).",
|
||||
EnumToString(g_calc_timeframe), EnumToString(Period()));
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
|
||||
g_is_mtf_mode = (g_calc_timeframe > Period());
|
||||
|
||||
// 2. Buffer Bindings
|
||||
SetIndexBuffer(0, ExtRVScoreBuffer, INDICATOR_DATA);
|
||||
SetIndexBuffer(1, ExtColorsBuffer, INDICATOR_COLOR_INDEX);
|
||||
SetIndexBuffer(2, ExtSignalBuffer, INDICATOR_DATA);
|
||||
|
||||
ArraySetAsSeries(ExtRVScoreBuffer, false);
|
||||
ArraySetAsSeries(ExtColorsBuffer, false);
|
||||
ArraySetAsSeries(ExtSignalBuffer, false);
|
||||
|
||||
ArrayInitialize(ExtRVScoreBuffer, 0.0);
|
||||
ArrayInitialize(ExtColorsBuffer, 0.0);
|
||||
ArrayInitialize(ExtSignalBuffer, EMPTY_VALUE);
|
||||
|
||||
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
||||
|
||||
// 3. Configure Dynamic Sigma Levels
|
||||
IndicatorSetInteger(INDICATOR_LEVELS, 6);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, InpLevelFlowHigh);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, InpLevelFlowLow);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, InpLevelClimaxHigh);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 3, InpLevelClimaxLow);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 4, InpLevelExtremeHigh);
|
||||
IndicatorSetDouble(INDICATOR_LEVELVALUE, 5, InpLevelExtremeLow);
|
||||
|
||||
IndicatorSetInteger(INDICATOR_LEVELCOLOR, InpLevelColor);
|
||||
IndicatorSetInteger(INDICATOR_LEVELSTYLE, InpLevelStyle);
|
||||
|
||||
// 4. Instantiate Core RV-Score Engine
|
||||
g_calc = new CRVScoreCalculator();
|
||||
if(CheckPointer(g_calc) == POINTER_INVALID)
|
||||
{
|
||||
Print("RV-Score Critical Error: Failed to allocate math engine.");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
bool is_ha = (InpCandleSource == CANDLE_HEIKIN_ASHI);
|
||||
if(!g_calc.Init(InpSigmaPeriod, InpRollingType, InpRollingWindow, InpVolumeType, is_ha))
|
||||
{
|
||||
Print("RV-Score Critical Error: Engine initialization failed.");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
// 5. Instantiate Signal Line Smoothing Calculator
|
||||
if(InpShowSignal)
|
||||
{
|
||||
PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
|
||||
PlotIndexSetInteger(1, PLOT_LINE_COLOR, InpColorSignal);
|
||||
PlotIndexSetString(1, PLOT_LABEL, "Signal");
|
||||
|
||||
g_signal_calculator = new CMovingAverageCalculator();
|
||||
if(CheckPointer(g_signal_calculator) == POINTER_INVALID ||
|
||||
!g_signal_calculator.Init(InpSignalPeriod, InpSignalType))
|
||||
{
|
||||
Print("RV-Score Critical Error: Failed to initialize Signal Engine.");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_NONE);
|
||||
PlotIndexSetString(1, PLOT_LABEL, NULL);
|
||||
}
|
||||
|
||||
// 6. Dynamic Indicator Title
|
||||
string ha_tag = is_ha ? " HA" : "";
|
||||
string tf_str = g_is_mtf_mode ? (" [" + EnumToString(g_calc_timeframe) + "]") : "";
|
||||
string type_str = (InpRollingType == ROLLING_BARS) ? "Bars" : "Min";
|
||||
string sig_str = "";
|
||||
if(InpShowSignal)
|
||||
{
|
||||
string sig_name = EnumToString(InpSignalType);
|
||||
StringToUpper(sig_name);
|
||||
sig_str = StringFormat(" | %s(%d)", sig_name, InpSignalPeriod);
|
||||
}
|
||||
|
||||
string short_name = StringFormat("RV-Score%s%s(%d %s, %dσ)%s",
|
||||
ha_tag, tf_str,
|
||||
InpRollingWindow, type_str,
|
||||
InpSigmaPeriod,
|
||||
sig_str);
|
||||
|
||||
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
|
||||
PlotIndexSetString(0, PLOT_LABEL, "RV-Score");
|
||||
|
||||
int draw_begin = InpSigmaPeriod + InpSignalPeriod + 5;
|
||||
if(g_is_mtf_mode)
|
||||
draw_begin = 0;
|
||||
|
||||
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin);
|
||||
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, draw_begin);
|
||||
IndicatorSetInteger(INDICATOR_DIGITS, 2);
|
||||
|
||||
// 7. Initialize Asynchronous Timer Daemon for MTF
|
||||
if(g_is_mtf_mode)
|
||||
EventSetTimer(1);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(g_is_mtf_mode)
|
||||
EventKillTimer();
|
||||
|
||||
if(CheckPointer(g_calc) != POINTER_INVALID)
|
||||
{
|
||||
delete g_calc;
|
||||
g_calc = NULL;
|
||||
}
|
||||
|
||||
if(CheckPointer(g_signal_calculator) != POINTER_INVALID)
|
||||
{
|
||||
delete g_signal_calculator;
|
||||
g_signal_calculator = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator calculation iteration |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnCalculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const datetime &time[],
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
const long &tick_volume[],
|
||||
const long &volume[],
|
||||
const int &spread[])
|
||||
{
|
||||
int required_bars = InpSigmaPeriod + InpSignalPeriod + 10;
|
||||
if(rates_total < required_bars || CheckPointer(g_calc) == POINTER_INVALID)
|
||||
return 0;
|
||||
|
||||
// Strict chronological alignment
|
||||
ArraySetAsSeries(time, false);
|
||||
ArraySetAsSeries(open, false);
|
||||
ArraySetAsSeries(high, false);
|
||||
ArraySetAsSeries(low, false);
|
||||
ArraySetAsSeries(close, false);
|
||||
ArraySetAsSeries(tick_volume, false);
|
||||
ArraySetAsSeries(volume, false);
|
||||
|
||||
//===================================================================
|
||||
// MODE 1: Direct Native Timeframe Calculation (Zero-Lag O(1))
|
||||
//===================================================================
|
||||
if(!g_is_mtf_mode)
|
||||
{
|
||||
long volume_limit = (long)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT);
|
||||
if(ArraySize(g_double_volume) != rates_total)
|
||||
{
|
||||
ArrayResize(g_double_volume, rates_total);
|
||||
ArraySetAsSeries(g_double_volume, false);
|
||||
}
|
||||
|
||||
int start_sync = (prev_calculated > 0) ? prev_calculated - 1 : 0;
|
||||
if(volume_limit > 0)
|
||||
{
|
||||
for(int i = start_sync; i < rates_total; i++)
|
||||
g_double_volume[i] = (double)volume[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = start_sync; i < rates_total; i++)
|
||||
g_double_volume[i] = (double)tick_volume[i];
|
||||
}
|
||||
|
||||
// 1. Calculate Continuous RV-Score
|
||||
g_calc.Calculate(rates_total, prev_calculated, time, open, high, low, close,
|
||||
tick_volume, volume, ExtRVScoreBuffer);
|
||||
|
||||
// 2. Calculate Signal MA Line
|
||||
if(InpShowSignal && CheckPointer(g_signal_calculator) != POINTER_INVALID)
|
||||
{
|
||||
g_signal_calculator.CalculateOnArray(rates_total, prev_calculated, ExtRVScoreBuffer,
|
||||
g_double_volume, ExtSignalBuffer, InpSigmaPeriod);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = start_sync; i < rates_total; i++)
|
||||
ExtSignalBuffer[i] = EMPTY_VALUE;
|
||||
}
|
||||
|
||||
// 3. Dynamic Swapped Thermal Palette Coloring
|
||||
int start_idx = (prev_calculated > 0) ? prev_calculated - 1 : InpSigmaPeriod;
|
||||
for(int i = start_idx; i < rates_total; i++)
|
||||
{
|
||||
double v = ExtRVScoreBuffer[i];
|
||||
|
||||
if(v >= InpLevelClimaxHigh)
|
||||
ExtColorsBuffer[i] = 2.0; // DeepSkyBlue (Bullish Climax)
|
||||
else
|
||||
if(v >= InpLevelFlowHigh)
|
||||
ExtColorsBuffer[i] = 1.0; // LightSkyBlue (Bullish Flow)
|
||||
else
|
||||
if(v <= InpLevelClimaxLow)
|
||||
ExtColorsBuffer[i] = 4.0; // OrangeRed (Bearish Climax)
|
||||
else
|
||||
if(v <= InpLevelFlowLow)
|
||||
ExtColorsBuffer[i] = 3.0; // Coral (Bearish Flow)
|
||||
else
|
||||
ExtColorsBuffer[i] = 0.0; // Gray (Neutral Noise Zone)
|
||||
}
|
||||
|
||||
return rates_total;
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// MODE 2: Synchronized MTF Engine
|
||||
//===================================================================
|
||||
int htf_required = (InpRollingType == ROLLING_BARS) ? (InpRollingWindow + InpSigmaPeriod + 10) : (InpSigmaPeriod + 50);
|
||||
if(!CDataSync::EnsureHTFDataReady(_Symbol, g_calc_timeframe, htf_required))
|
||||
{
|
||||
g_data_synced = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_data_synced = true;
|
||||
|
||||
datetime htf_time_current = iTime(_Symbol, g_calc_timeframe, 0);
|
||||
bool htf_updated = (htf_time_current != g_last_htf_time);
|
||||
|
||||
if(htf_updated || prev_calculated == 0)
|
||||
{
|
||||
g_last_htf_time = htf_time_current;
|
||||
|
||||
int htf_bars = iBars(_Symbol, g_calc_timeframe);
|
||||
if(htf_bars < htf_required)
|
||||
{
|
||||
g_data_ready = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_htf_count = MathMin(htf_bars, 3000); // Enterprise memory safeguard
|
||||
|
||||
// Resize all HTF caching arrays
|
||||
ArrayResize(h_time, g_htf_count);
|
||||
ArrayResize(h_open, g_htf_count);
|
||||
ArrayResize(h_high, g_htf_count);
|
||||
ArrayResize(h_low, g_htf_count);
|
||||
ArrayResize(h_close, g_htf_count);
|
||||
ArrayResize(h_tick_vol, g_htf_count);
|
||||
ArrayResize(h_vol, g_htf_count);
|
||||
ArrayResize(h_res_rvscore, g_htf_count);
|
||||
ArrayResize(h_res_color, g_htf_count);
|
||||
ArrayResize(h_res_signal, g_htf_count);
|
||||
|
||||
// Force chronological alignment
|
||||
ArraySetAsSeries(h_time, false);
|
||||
ArraySetAsSeries(h_open, false);
|
||||
ArraySetAsSeries(h_high, false);
|
||||
ArraySetAsSeries(h_low, false);
|
||||
ArraySetAsSeries(h_close, false);
|
||||
ArraySetAsSeries(h_tick_vol, false);
|
||||
ArraySetAsSeries(h_vol, false);
|
||||
ArraySetAsSeries(h_res_rvscore, false);
|
||||
ArraySetAsSeries(h_res_color, false);
|
||||
ArraySetAsSeries(h_res_signal, false);
|
||||
|
||||
// Copy pricing & volume data
|
||||
if(CopyTime(_Symbol, g_calc_timeframe, 0, g_htf_count, h_time) != g_htf_count ||
|
||||
CopyOpen(_Symbol, g_calc_timeframe, 0, g_htf_count, h_open) != g_htf_count ||
|
||||
CopyHigh(_Symbol, g_calc_timeframe, 0, g_htf_count, h_high) != g_htf_count ||
|
||||
CopyLow(_Symbol, g_calc_timeframe, 0, g_htf_count, h_low) != g_htf_count ||
|
||||
CopyClose(_Symbol, g_calc_timeframe, 0, g_htf_count, h_close) != g_htf_count ||
|
||||
CopyTickVolume(_Symbol, g_calc_timeframe, 0, g_htf_count, h_tick_vol) != g_htf_count)
|
||||
{
|
||||
g_data_ready = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long vol_limit = (long)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT);
|
||||
if(vol_limit > 0)
|
||||
CopyRealVolume(_Symbol, g_calc_timeframe, 0, g_htf_count, h_vol);
|
||||
else
|
||||
ArrayCopy(h_vol, h_tick_vol, 0, 0, g_htf_count);
|
||||
|
||||
// Compute HTF RV-Score Values
|
||||
g_calc.Calculate(g_htf_count, 0, h_time, h_open, h_high, h_low, h_close,
|
||||
h_tick_vol, h_vol, h_res_rvscore);
|
||||
|
||||
// Compute HTF Signal Line
|
||||
if(InpShowSignal && CheckPointer(g_signal_calculator) != POINTER_INVALID)
|
||||
{
|
||||
double htf_double_vol[];
|
||||
ArrayResize(htf_double_vol, g_htf_count);
|
||||
ArraySetAsSeries(htf_double_vol, false);
|
||||
for(int k = 0; k < g_htf_count; k++)
|
||||
htf_double_vol[k] = (double)h_vol[k];
|
||||
|
||||
g_signal_calculator.CalculateOnArray(g_htf_count, 0, h_res_rvscore,
|
||||
htf_double_vol, h_res_signal, InpSigmaPeriod);
|
||||
}
|
||||
|
||||
// Color HTF Cache
|
||||
for(int i = 0; i < g_htf_count; i++)
|
||||
{
|
||||
double v = h_res_rvscore[i];
|
||||
if(v >= InpLevelClimaxHigh)
|
||||
h_res_color[i] = 2.0;
|
||||
else
|
||||
if(v >= InpLevelFlowHigh)
|
||||
h_res_color[i] = 1.0;
|
||||
else
|
||||
if(v <= InpLevelClimaxLow)
|
||||
h_res_color[i] = 4.0;
|
||||
else
|
||||
if(v <= InpLevelFlowLow)
|
||||
h_res_color[i] = 3.0;
|
||||
else
|
||||
h_res_color[i] = 0.0;
|
||||
}
|
||||
|
||||
g_data_ready = true;
|
||||
}
|
||||
|
||||
if(!g_data_ready)
|
||||
return 0;
|
||||
|
||||
// Stateful live-bar update for active forming HTF candle
|
||||
int live_idx = g_htf_count - 1;
|
||||
if(live_idx >= htf_required)
|
||||
{
|
||||
double o[1], h[1], l[1], c[1];
|
||||
datetime t_bar[1];
|
||||
long tv[1], v[1];
|
||||
|
||||
int shift = iBarShift(_Symbol, g_calc_timeframe, htf_time_current, false);
|
||||
if(shift >= 0 &&
|
||||
CopyTime(_Symbol, g_calc_timeframe, shift, 1, t_bar) == 1 &&
|
||||
CopyOpen(_Symbol, g_calc_timeframe, shift, 1, o) == 1 &&
|
||||
CopyHigh(_Symbol, g_calc_timeframe, shift, 1, h) == 1 &&
|
||||
CopyLow(_Symbol, g_calc_timeframe, shift, 1, l) == 1 &&
|
||||
CopyClose(_Symbol, g_calc_timeframe, shift, 1, c) == 1 &&
|
||||
CopyTickVolume(_Symbol, g_calc_timeframe, shift, 1, tv) == 1)
|
||||
{
|
||||
h_time[live_idx] = t_bar[0];
|
||||
h_open[live_idx] = o[0];
|
||||
h_high[live_idx] = h[0];
|
||||
h_low[live_idx] = l[0];
|
||||
h_close[live_idx] = c[0];
|
||||
h_tick_vol[live_idx] = tv[0];
|
||||
|
||||
long vol_limit = (long)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT);
|
||||
if(vol_limit > 0 && CopyRealVolume(_Symbol, g_calc_timeframe, shift, 1, v) == 1)
|
||||
h_vol[live_idx] = v[0];
|
||||
else
|
||||
h_vol[live_idx] = tv[0];
|
||||
|
||||
// Mock update on live bar
|
||||
g_calc.Calculate(g_htf_count, g_htf_count, h_time, h_open, h_high, h_low, h_close,
|
||||
h_tick_vol, h_vol, h_res_rvscore);
|
||||
|
||||
if(InpShowSignal && CheckPointer(g_signal_calculator) != POINTER_INVALID)
|
||||
{
|
||||
double htf_double_vol[];
|
||||
ArrayResize(htf_double_vol, g_htf_count);
|
||||
ArraySetAsSeries(htf_double_vol, false);
|
||||
for(int k = 0; k < g_htf_count; k++)
|
||||
htf_double_vol[k] = (double)h_vol[k];
|
||||
|
||||
g_signal_calculator.CalculateOnArray(g_htf_count, g_htf_count, h_res_rvscore,
|
||||
htf_double_vol, h_res_signal, InpSigmaPeriod);
|
||||
}
|
||||
|
||||
double v_val = h_res_rvscore[live_idx];
|
||||
if(v_val >= InpLevelClimaxHigh)
|
||||
h_res_color[live_idx] = 2.0;
|
||||
else
|
||||
if(v_val >= InpLevelFlowHigh)
|
||||
h_res_color[live_idx] = 1.0;
|
||||
else
|
||||
if(v_val <= InpLevelClimaxLow)
|
||||
h_res_color[live_idx] = 4.0;
|
||||
else
|
||||
if(v_val <= InpLevelFlowLow)
|
||||
h_res_color[live_idx] = 3.0;
|
||||
else
|
||||
h_res_color[live_idx] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Forming LTF Block Flat-Force Anchor (The Staircase Solution)
|
||||
int start = (prev_calculated > 0) ? prev_calculated - 1 : 0;
|
||||
|
||||
int first_bar_of_forming_htf = rates_total - 1;
|
||||
while(first_bar_of_forming_htf > 0 &&
|
||||
iBarShift(_Symbol, g_calc_timeframe, time[first_bar_of_forming_htf], false) == 0)
|
||||
{
|
||||
first_bar_of_forming_htf--;
|
||||
}
|
||||
first_bar_of_forming_htf++;
|
||||
|
||||
if(start > first_bar_of_forming_htf)
|
||||
start = first_bar_of_forming_htf;
|
||||
|
||||
// Chronological Mapping Loop to Chart Timeframe
|
||||
for(int i = start; i < rates_total; i++)
|
||||
{
|
||||
datetime t = time[i];
|
||||
int shift_htf = iBarShift(_Symbol, g_calc_timeframe, t, false);
|
||||
|
||||
if(shift_htf >= 0)
|
||||
{
|
||||
int idx_htf = g_htf_count - 1 - shift_htf;
|
||||
if(idx_htf >= 0 && idx_htf < g_htf_count)
|
||||
{
|
||||
ExtRVScoreBuffer[i] = h_res_rvscore[idx_htf];
|
||||
ExtColorsBuffer[i] = h_res_color[idx_htf];
|
||||
ExtSignalBuffer[i] = InpShowSignal ? h_res_signal[idx_htf] : EMPTY_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtRVScoreBuffer[i] = 0.0;
|
||||
ExtColorsBuffer[i] = 0.0;
|
||||
ExtSignalBuffer[i] = EMPTY_VALUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtRVScoreBuffer[i] = 0.0;
|
||||
ExtColorsBuffer[i] = 0.0;
|
||||
ExtSignalBuffer[i] = EMPTY_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
return rates_total;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| OnTimer Event Handler (Data Synchronization Daemon) |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
int htf_required = (InpRollingType == ROLLING_BARS) ? (InpRollingWindow + InpSigmaPeriod + 10) : (InpSigmaPeriod + 50);
|
||||
CDataSync::OnTimerUpdate(_Symbol, g_calc_timeframe, htf_required, g_data_synced);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,338 @@
|
||||
# Rolling Volume-Weighted Z-Score (RV-Score) Pro (v3.20)
|
||||
|
||||
Quantitative Continuous Volume-Weighted Dispersion & Stationary Fair-Value Oscillator
|
||||
|
||||
---
|
||||
|
||||
## 1. Summary (Introduction)
|
||||
|
||||
**RV-Score Pro** is an institutional-grade statistical momentum oscillator that measures normalized price dispersion from a **continuous Rolling Volume-Weighted Average Price (Rolling VWAP)** in standardized units of standard deviation ($\sigma$).
|
||||
|
||||
While traditional session-anchored indicators (such as standard V-Score) reset their memory at daily or weekly boundaries—causing artificial volatility pinching at session opens and late-day inertia—**RV-Score evaluates price against a continuously moving, volume-weighted institutional liquidity anchor**.
|
||||
|
||||
By calculating dispersion over a rolling historical horizon (e.g., last 144 bars or continuous 24 hours), RV-Score generates a **strictly stationary, zero-boundary oscillator** that eliminates opening-bell distortion while preserving volume-weighted market truth.
|
||||
|
||||
```text
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────┐
|
||||
│ RV-SCORE DISPERSION MODEL │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ RV-Score(t) = [ Close(t) - RollingVWAP(t) ] / RollingStdDev(t) │
|
||||
│ Expressed in standardized Sigma Multiples (σ) │
|
||||
│ │
|
||||
│ • Continuous Zero-Boundary Horizon (No Session Cutoff Distortion) │
|
||||
│ • Amortized O(1) Prefix-Sum Integration │
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
```
|
||||
|
||||
### The Four Z-Score Indicator Paradigms
|
||||
|
||||
- **Z-Score Pro:** Measures Gaussian dispersion from a static Moving Average (Price/Time axis).
|
||||
- **K-Score Pro:** Measures kinetic elasticity from Kaufman's Adaptive Moving Average (Efficiency/Regime axis).
|
||||
- **V-Score Pro:** Measures statistical overextension from Anchored/Session VWAP (Session-Volume axis).
|
||||
- **RV-Score Pro:** Measures continuous statistical dispersion from Rolling VWAP (Stationary Volume-Weighted axis).
|
||||
|
||||
### Key Capabilities
|
||||
|
||||
- **Stationary Volume-Weighted Baseline:** Eliminates session-open false spikes and late-day paralysis by continuously sliding both the VWAP anchor and volatility lookback window.
|
||||
- **Swapped Thermal 5-Zone Palette:** Visually classifies market states into noise/equilibrium, active institutional flow, and statistical climax exhaustion.
|
||||
- **Integrated Signal Smoothing Engine:** Direct composition with `CMovingAverageCalculator`, providing 8 advanced smoothing algorithms (SMA, EMA, SMMA, LWMA, TMA, DEMA, TEMA, VWMA) over the raw RV-Score histogram.
|
||||
- **Unified 2026 MTF Architecture:** Maps higher-timeframe RV-Score histograms (e.g., H1 RV-Score) onto lower-timeframe execution charts (M5, M1) via `DataSync_Tools.mqh` with non-warping staircase flat-force synchronization.
|
||||
|
||||
---
|
||||
|
||||
## 2. Mathematical Foundations & Continuous Normalization
|
||||
|
||||
```text
|
||||
|
||||
+2.5σ (Extreme Exhaustion / Climax)
|
||||
───────────────────────────────────────────────────────────── DeepSkyBlue (Bull Climax)
|
||||
+1.5σ (Bullish Flow Threshold)
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LightSkyBlue (Bull Flow)
|
||||
0.0σ (Rolling VWAP Equilibrium)
|
||||
───────────────────────────────────────────────────────────── Gray (Noise / Fair Value)
|
||||
-1.5σ (Bearish Flow Threshold)
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Coral (Bear Flow)
|
||||
-2.5σ (Extreme Exhaustion / Climax)
|
||||
───────────────────────────────────────────────────────────── OrangeRed (Bear Climax)
|
||||
|
||||
```
|
||||
|
||||
### 2.1. Continuous Rolling VWAP Baseline ($\mu_{\text{RVWAP}, t}$)
|
||||
|
||||
Calculated via cumulative prefix sums over the sliding window $W$ (bars or elapsed seconds):
|
||||
$$\mu_{\text{RVWAP}, t} = \frac{\text{SumTPV}_t - \text{SumTPV}_{t - W}}{\text{SumVol}_t - \text{SumVol}_{t - W}}$$
|
||||
*where $\text{TP}_k = \frac{H_k + L_k + C_k}{3}$ and $V_k$ is the applied volume.*
|
||||
|
||||
### 2.2. Continuous Deviation Metric ($\text{Diff}_k$)
|
||||
|
||||
$$\text{Diff}_k = C_k - \mu_{\text{RVWAP}, k}$$
|
||||
|
||||
### 2.3. Rolling Standard Deviation Around Rolling VWAP ($\sigma_{\text{Rolling}, t}$)
|
||||
|
||||
Given the volatility lookback period $P = \text{InpSigmaPeriod}$:
|
||||
$$\sigma_{\text{Rolling}, t} = \sqrt{\frac{1}{P} \sum_{k=0}^{P - 1} \left( \text{Diff}_{t - k} \right)^2}$$
|
||||
|
||||
### 2.4. Normalized RV-Score Formulation
|
||||
|
||||
$$\text{RVScore}_t = \begin{cases} \frac{C_t - \mu_{\text{RVWAP}, t}}{\sigma_{\text{Rolling}, t}}, & \text{if } \sigma_{\text{Rolling}, t} > 10^{-9} \\ 0.0, & \text{otherwise} \end{cases}$$
|
||||
|
||||
---
|
||||
|
||||
### 2.5. Swapped Thermal 5-Zone Color Palette
|
||||
|
||||
| State Index | Color | Classification | Sigma Level Trigger | Institutional Market Action |
|
||||
| :---: | :---: | :--- | :--- | :--- |
|
||||
| **0.0** | `clrGray` | **Noise / Equilibrium** | $\|\text{RVScore}\| \le 1.5\sigma$ | Price oscillating within stationary fair-value bounds. |
|
||||
| **1.0** | `clrLightSkyBlue` | **Bullish Flow** | $+1.5\sigma < \text{RVScore} \le +2.0\sigma$ | Sustained institutional volume expansion to the upside. |
|
||||
| **2.0** | `clrDeepSkyBlue` | **Bullish Climax** | $\text{RVScore} > +2.0\sigma$ | Overbought statistical extremity; liquidity absorption warning. |
|
||||
| **3.0** | `clrCoral` | **Bearish Flow** | $-2.0\sigma \le \text{RVScore} < -1.5\sigma$ | Sustained institutional selling pressure active. |
|
||||
| **4.0** | `clrOrangeRed` | **Bearish Climax** | $\text{RVScore} < -2.0\sigma$ | Capitulation liquidation floor; high short-squeeze probability. |
|
||||
|
||||
---
|
||||
|
||||
## 3. MQL5 Architecture & Engineering Standards
|
||||
|
||||
```text
|
||||
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ RVScore_Calculator.mqh │
|
||||
│ (Core Math Engine - Prefix Sums & Dispersion) │
|
||||
└──────────────────────────┬─────────────────────────────┘
|
||||
│ Outputs RV-Score Values in O(1)
|
||||
▼
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ RVScore_Pro.mq5 │
|
||||
│ (Unified Wrapper: Native Timeframe & MTF Engine) │
|
||||
├──────────────────────────┬─────────────────────────────┤
|
||||
│ Buffer Layer (3) │ Centralized Framework │
|
||||
│ • ExtRVScoreBuffer │ • Rolling_VWAP_Engine │
|
||||
│ • ExtColorsBuffer │ • MovingAverage_Engine │
|
||||
│ • ExtSignalBuffer │ • DataSync_Tools.mqh │
|
||||
└──────────────────────────┴─────────────────────────────┘
|
||||
|
||||
```
|
||||
|
||||
1. **Zero Boundary Artifacts:** Unlike anchored VWAP systems, the absence of session cutoffs completely prevents array index desynchronization and variance pinching.
|
||||
2. **Separation of Concerns:** `CRVScoreCalculator` embeds `CRollingVWAPCalculator` via composition, maintaining independent memory spaces for volume integration and volatility standard deviation.
|
||||
3. **2026 MTF Framework (`DataSync_Tools.mqh`):** Higher-timeframe RV-Score histograms are projected onto lower-timeframe charts using flat-force step synchronization, guaranteeing zero repainting on closed candles.
|
||||
|
||||
---
|
||||
|
||||
## 4. Parameters Reference
|
||||
|
||||
### Timeframe Settings
|
||||
|
||||
- `InpTimeframe` (*default: `PERIOD_CURRENT`*): Calculation timeframe. Set to `PERIOD_CURRENT` for native zero-lag execution, or choose a higher timeframe (e.g., `PERIOD_H1`) to activate the synchronized MTF engine.
|
||||
|
||||
### Rolling VWAP Engine
|
||||
|
||||
- `InpRollingType` (*default: `ROLLING_BARS`*):
|
||||
- `ROLLING_BARS`: Sliding window of fixed bar length.
|
||||
- `ROLLING_TIME`: Continuous physical time window in minutes.
|
||||
- `InpRollingWindow` (*default: `144`*): Window length (bar count or minutes).
|
||||
- `InpSigmaPeriod` (*default: `20`*): Lookback period ($P$) for computing standard deviation variance around the Rolling VWAP.
|
||||
|
||||
### Calculation Sources
|
||||
|
||||
- `InpVolumeType` (*default: `VOLUME_TICK`*): Applied volume source (`VOLUME_TICK` or `VOLUME_REAL`).
|
||||
- `InpCandleSource` (*default: `CANDLE_STANDARD`*): Price series source (`CANDLE_STANDARD` or `CANDLE_HEIKIN_ASHI`).
|
||||
|
||||
### Signal Line Settings
|
||||
|
||||
- `InpShowSignal` (*default: `true`*): Toggles visibility of the smoothed Signal MA line.
|
||||
- `InpSignalPeriod` (*default: `5`*): Lookback period for the signal line.
|
||||
- `InpSignalType` (*default: `EMA`*): Smoothing algorithm (`SMA`, `EMA`, `SMMA`, `LWMA`, `TMA`, `DEMA`, `TEMA`, `VWMA`).
|
||||
- `InpColorSignal` (*default: `clrFireBrick`*): Color applied to the signal line plot.
|
||||
|
||||
### Indicator Levels (Sigma Multiples)
|
||||
|
||||
- `InpLevelFlowHigh` (*default: `1.5`*): Bullish Flow threshold boundary.
|
||||
- `InpLevelFlowLow` (*default: `-1.5`*): Bearish Flow threshold boundary.
|
||||
- `InpLevelClimaxHigh` (*default: `2.0`*): Bullish Climax threshold (`DeepSkyBlue`).
|
||||
- `InpLevelClimaxLow` (*default: `-2.0`*): Bearish Climax threshold (`OrangeRed`).
|
||||
- `InpLevelExtremeHigh` (*default: `2.5`*): Extreme statistical expansion ceiling.
|
||||
- `InpLevelExtremeLow` (*default: `-2.5`*): Extreme statistical capitulation floor.
|
||||
- `InpLevelColor` (*default: `clrSilver`*): Color of horizontal level lines.
|
||||
- `InpLevelStyle` (*default: `STYLE_DOT`*): Line style of horizontal level lines.
|
||||
|
||||
---
|
||||
|
||||
## 5. Quantitative Trading Playbooks
|
||||
|
||||
```text
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────┐
|
||||
│ RV-SCORE INSTITUTIONAL PLAYBOOKS │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ 1. Continuous Climax Fade: Fade statistical overextensions when │
|
||||
│ RV-Score > +2.0σ and hooks back. │
|
||||
│ 2. Volume Flow Expansion: Trend continuation when RV-Score holds │
|
||||
│ between +1.5σ and +2.0σ (Flow Zone). │
|
||||
│ 3. Signal Line Crossover: Zero-lag trend confirmation upon Signal MA │
|
||||
│ crossings inside/outside the flow zones. │
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
```
|
||||
|
||||
### 5.1. Continuous Climax Mean Reversion ($\pm 2.0\sigma \dots \pm 2.5\sigma$)
|
||||
|
||||
- **Context:** Price aggressively expands away from the Rolling VWAP, pushing the RV-Score into the Climax zone ($> +2.0\sigma$, `DeepSkyBlue` or $< -2.0\sigma$, `OrangeRed`).
|
||||
- **Short Reversal Setup:**
|
||||
1. RV-Score exceeds $+2.0\sigma$.
|
||||
2. Histogram bar prints lower than the preceding bar and crosses **below** the Signal MA line.
|
||||
3. Enter Short targeting the zero-line fair value ($0.0\sigma$).
|
||||
- **Long Capitulation Bounce:**
|
||||
1. RV-Score flushes below $-2.0\sigma$ or $-2.5\sigma$ during a panic selloff.
|
||||
2. Histogram prints a higher low and crosses **above** the Signal MA line.
|
||||
3. Enter Long targeting the $0.0\sigma$ equilibrium.
|
||||
|
||||
### 5.2. Volume Flow Expansion Continuation ($+1.5\sigma \dots +2.0\sigma$)
|
||||
|
||||
- **Context:** In strong institutional markup/markdown phases, prices stay persistently overextended without snapping back.
|
||||
- **Bullish Momentum Rule:**
|
||||
- As long as RV-Score holds between $+1.5\sigma$ (`LightSkyBlue`) and $+2.0\sigma$, maintain long trend-following exposure.
|
||||
- Exit or tighten trailing stops only when the histogram falls back below $+1.5\sigma$ into the neutral gray zone.
|
||||
|
||||
### 5.3. Multi-Timeframe Alignment (H1 RV-Score on M5 Execution)
|
||||
|
||||
- Load `RVScore_Pro` with `InpTimeframe = PERIOD_H1` on an M5 trading chart.
|
||||
- If H1 RV-Score is positive and above $+1.5\sigma$: Institutional money flow on the hourly horizon is bullish $\rightarrow$ Filter M5 execution to **Long signals only**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Indicator Buffer Map (For Developers & EA Integration)
|
||||
|
||||
### Buffer Allocation
|
||||
|
||||
| Buffer Index | Name | Type | Description |
|
||||
| :---: | :---: | :---: | :--- |
|
||||
| **0** | `ExtRVScoreBuffer` | `INDICATOR_DATA` | Standardized RV-Score Values in Sigma Units ($\sigma$) |
|
||||
| **1** | `ExtColorsBuffer` | `INDICATOR_COLOR_INDEX` | Swapped Thermal 5-Zone Palette Index ($0.0 \dots 4.0$) |
|
||||
| **2** | `ExtSignalBuffer` | `INDICATOR_DATA` | Smoothed Signal Moving Average Plot |
|
||||
|
||||
*All buffers maintain strict chronological indexing (`ArraySetAsSeries = false`), ensuring direct compatibility with Expert Advisors and multi-asset scanner dashboards.*
|
||||
|
||||
---
|
||||
|
||||
### MQL5 EA Integration Interface Template
|
||||
|
||||
```mql5
|
||||
//+------------------------------------------------------------------+
|
||||
//| EA_RVScore_Interface.mq5 |
|
||||
//| Copyright 2026, xxxxxxxx|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026, xxxxxxxx"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
//--- Include Rolling VWAP Window Type Definition
|
||||
#include <MyIncludes\Rolling_VWAP_Calculator.mqh>
|
||||
#include <MyIncludes\MovingAverage_Engine.mqh>
|
||||
|
||||
//--- EA Inputs
|
||||
input group "=== RV-Score Filter Settings ==="
|
||||
input ENUM_TIMEFRAMES InpRVTimeframe = PERIOD_CURRENT; // Timeframe
|
||||
input ENUM_ROLLING_TYPE InpRVType = ROLLING_BARS; // Rolling Type
|
||||
input int InpRVWindow = 144; // Rolling Window
|
||||
input int InpRVSigmaPeriod = 20; // Volatility Lookback (Sigma)
|
||||
input ENUM_APPLIED_VOLUME InpRVVolume = VOLUME_TICK; // Volume Type
|
||||
input ENUM_CANDLE_SOURCE InpRVSource = CANDLE_STANDARD; // Candle Source
|
||||
input bool InpShowSignal = true; // Enable Signal Line
|
||||
input int InpSignalPeriod = 5; // Signal Period
|
||||
input ENUM_MA_TYPE InpSignalType = EMA; // Signal MA Type
|
||||
|
||||
//--- Global Indicator Handle
|
||||
int g_rvscore_handle = INVALID_HANDLE;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
if(g_rvscore_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(g_rvscore_handle);
|
||||
|
||||
// Instantiate handle to RVScore_Pro via iCustom
|
||||
g_rvscore_handle = iCustom(_Symbol,
|
||||
InpRVTimeframe,
|
||||
"RVScore_Pro",
|
||||
InpRVTimeframe,
|
||||
InpRVType,
|
||||
InpRVWindow,
|
||||
InpRVSigmaPeriod,
|
||||
InpRVVolume,
|
||||
InpRVSource,
|
||||
InpShowSignal,
|
||||
InpSignalPeriod,
|
||||
InpSignalType,
|
||||
clrFireBrick,
|
||||
1.5, -1.5, 2.0, -2.0, 2.5, -2.5,
|
||||
clrSilver, STYLE_DOT);
|
||||
|
||||
if(g_rvscore_handle == INVALID_HANDLE)
|
||||
{
|
||||
PrintFormat("EA Error: Failed to create handle for RVScore_Pro. Error Code: %d", GetLastError());
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
Print("EA Success: RVScore_Pro handle initialized successfully.");
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(g_rvscore_handle != INVALID_HANDLE)
|
||||
{
|
||||
IndicatorRelease(g_rvscore_handle);
|
||||
g_rvscore_handle = INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Query last 2 closed bars and active live bar (3 values)
|
||||
double score_val[3], color_val[3], signal_val[3];
|
||||
ArraySetAsSeries(score_val, true); // Index 0 = Live, 1 = Closed bar
|
||||
ArraySetAsSeries(color_val, true);
|
||||
ArraySetAsSeries(signal_val, true);
|
||||
|
||||
// Read Buffer 0 (RV-Score), Buffer 1 (Colors), Buffer 2 (Signal)
|
||||
if(CopyBuffer(g_rvscore_handle, 0, 0, 3, score_val) < 3 ||
|
||||
CopyBuffer(g_rvscore_handle, 1, 0, 3, color_val) < 3 ||
|
||||
CopyBuffer(g_rvscore_handle, 2, 0, 3, signal_val) < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double closed_score = score_val[1];
|
||||
double closed_signal = signal_val[1];
|
||||
int closed_color = (int)color_val[1];
|
||||
|
||||
// Quantitative Signals
|
||||
bool is_bullish_climax = (closed_color == 2); // DeepSkyBlue (> +2.0σ)
|
||||
bool is_bearish_climax = (closed_color == 4); // OrangeRed (< -2.0σ)
|
||||
bool is_bullish_flow = (closed_color == 1); // LightSkyBlue (+1.5σ to +2.0σ)
|
||||
bool is_bearish_flow = (closed_color == 3); // Coral (-1.5σ to -2.0σ)
|
||||
|
||||
// Signal Crossover Execution Logic
|
||||
bool signal_cross_down = (score_val[2] >= signal_val[2] && score_val[1] < signal_val[1]);
|
||||
bool signal_cross_up = (score_val[2] <= signal_val[2] && score_val[1] > signal_val[1]);
|
||||
|
||||
// Telemetry Output
|
||||
Comment(StringFormat("RV-Score [Bar 1]: %.2fσ | Signal: %.2fσ | State: %s\n"
|
||||
"Climax Fade Short: %s | Climax Fade Long: %s",
|
||||
closed_score, closed_signal,
|
||||
is_bullish_climax ? "BULL CLIMAX" : (is_bearish_climax ? "BEAR CLIMAX" : (is_bullish_flow ? "BULL FLOW" : (is_bearish_flow ? "BEAR FLOW" : "EQUILIBRIUM"))),
|
||||
(is_bullish_climax && signal_cross_down) ? "TRIGGERED" : "NO",
|
||||
(is_bearish_climax && signal_cross_up) ? "TRIGGERED" : "NO"));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
```
|
||||
Reference in New Issue
Block a user