Re: Tame the Whipsaws: Ridge Regression Regularized Moving Average (RRRMA)
Posted: Sun Sep 27, 2026 6:38 pm
MetaTrader 5 (MQL5)
In MQL5, custom indicator price arrays default to chronological ordering (0 is the oldest historical bar, rates_total - 1 is the current forming tick). The indexing mirrors the C# logic perfectly.
In MQL5, custom indicator price arrays default to chronological ordering (0 is the oldest historical bar, rates_total - 1 is the current forming tick). The indexing mirrors the C# logic perfectly.
Code: Select all
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDarkOrange
#property indicator_width1 2
#property indicator_label1 "Ridge MA"
input int InpPeriod = 14; // Regression Period (P)
input double InpBlendK = 0.5; // Ridge Blend 'k' (0.0 to 1.0)
double RidgeBuffer[];
double Sxx;
double HalfP;
int OnInit()
{
if(InpPeriod < 2) return INIT_PARAMETERS_INCORRECT;
SetIndexBuffer(0, RidgeBuffer, INDICATOR_DATA);
// Calculate sequence variance and the X-axis boundary
Sxx = (InpPeriod * (MathPow(InpPeriod, 2) - 1)) / 12.0;
HalfP = (InpPeriod - 1.0) / 2.0;
return INIT_SUCCEEDED;
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
if(rates_total < InpPeriod) return 0;
// Start at the first calculable bar, or recalculate the last forming bar
int limit = prev_calculated == 0 ? InpPeriod - 1 : prev_calculated - 1;
for(int i = limit; i < rates_total; i++)
{
double sum_y = 0;
double sum_xy = 0;
for(int j = 0; j < InpPeriod; j++)
{
// price[i] is the newest bar in the current window iteration
double y = price[i - j];
sum_y += y;
// Centered X-coordinate mapping
double x_centered = HalfP - j;
sum_xy += x_centered * y;
}
double sma = sum_y / InpPeriod;
double slope = sum_xy / Sxx;
// Apply the structural blend directly to the slope
RidgeBuffer[i] = sma + (InpBlendK * slope * HalfP);
}
return rates_total;
}