64 lines
2.3 KiB
MQL5
64 lines
2.3 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| RSquared.mqh |
|
||
|
//| Copyright 2022, MetaQuotes Ltd. |
|
||
|
//| https://www.mql5.com |
|
||
|
//| Coefficient of determination (R²) implementation |
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| R² and its LR-line angle |
|
||
|
//+------------------------------------------------------------------+
|
||
|
struct R2A
|
||
|
{
|
||
|
double r2;
|
||
|
double angle; // tangent
|
||
|
R2A(): r2(0), angle(0) { }
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Calculate R² and its LR-line angle |
|
||
|
//+------------------------------------------------------------------+
|
||
|
R2A RSquared(const double &data[])
|
||
|
{
|
||
|
int size = ArraySize(data);
|
||
|
if(size <= 2) return R2A();
|
||
|
double x, y, div;
|
||
|
int k = 0;
|
||
|
double Sx = 0, Sy = 0, Sxy = 0, Sx2 = 0, Sy2 = 0;
|
||
|
for(int i = 0; i < size; ++i)
|
||
|
{
|
||
|
if(data[i] == EMPTY_VALUE
|
||
|
|| !MathIsValidNumber(data[i])) continue;
|
||
|
x = i + 1;
|
||
|
y = data[i];
|
||
|
Sx += x;
|
||
|
Sy += y;
|
||
|
Sxy += x * y;
|
||
|
Sx2 += x * x;
|
||
|
Sy2 += y * y;
|
||
|
++k;
|
||
|
}
|
||
|
size = k;
|
||
|
const double Sx22 = Sx * Sx / size;
|
||
|
const double Sy22 = Sy * Sy / size;
|
||
|
const double SxSy = Sx * Sy / size;
|
||
|
div = (Sx2 - Sx22) * (Sy2 - Sy22);
|
||
|
if(fabs(div) < DBL_EPSILON) return R2A();
|
||
|
R2A result;
|
||
|
result.r2 = (Sxy - SxSy) * (Sxy - SxSy) / div;
|
||
|
result.angle = (Sxy - SxSy) / (Sx2 - Sx22);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Special criterion for tester, using R² and its LR-line angle |
|
||
|
//+------------------------------------------------------------------+
|
||
|
double RSquaredTest(const double &data[])
|
||
|
{
|
||
|
const R2A result = RSquared(data);
|
||
|
const double weight = 1.0 - 1.0 / sqrt(ArraySize(data) + 1);
|
||
|
if(result.angle < 0) return -fabs(result.r2) * weight;
|
||
|
return result.r2 * weight;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|