Article-22610-Joint-Recurre.../Include/RQA/RQA.mqh

454 lines
19 KiB
MQL5
Raw Permalink Normal View History

2026-05-30 13:14:34 +05:00
//+------------------------------------------------------------------+
//| RQA.mqh |
//| RQA Library for MQL5 |
//| |
//| FULL LIBRARY — Main include file |
//| |
//| Usage: |
//| #include <RQA\RQA.mqh> |
//| |
//| ── Standard RQA classes (single series) ────────────────────── |
//| CRQAMatrix — builds the NxN recurrence matrix |
//| CRQAMetrics — computes all RQA measures |
//| CRQAEpsilon — automatic epsilon selection |
//| CRQAWindow — rolling/windowed RQA analysis |
//| CRQA — high-level all-in-one RQA facade |
//| |
//| ── Cross-RQA classes (two series) ──────────────────────────── |
//| CCRQAMatrix — builds the NxM cross-recurrence matrix |
//| CCRQAMetrics — computes all CRQA measures |
//| CCRQAWindow — rolling/windowed CRQA analysis |
//| CCRQA — high-level all-in-one CRQA facade |
//| |
//| ── Joint-RQA classes (two series, joint recurrence) ────────── |
//| CJRQAMatrix — builds NxN joint recurrence matrix (AND of RPs)|
//| CJRQAMetrics — computes all JRQA measures |
//| CJRQAWindow — rolling/windowed JRQA analysis |
//| CJRQA — high-level all-in-one JRQA facade |
//| |
//| ── Structs ──────────────────────────────────────────────────── |
//| SRQAResult — holds all RQA metric values |
//| SRQAWindowResult — per-window RQA metric values |
//| SCRQAResult — holds all CRQA metric values |
//| SCRQAWindowResult — per-window CRQA metric values |
//| SJRQAResult — holds all JRQA metric values |
//| SJRQAWindowResult — per-window JRQA metric values |
//| |
//| ── Enums ────────────────────────────────────────────────────── |
//| ENUM_RQA_NORM — distance norm choice |
//| ENUM_EPSILON_METHOD — epsilon auto-selection |
//+------------------------------------------------------------------+
#ifndef RQA_MQH
#define RQA_MQH
// --- Standard RQA modules ---
#include "RQAMatrix.mqh"
#include "RQAMetrics.mqh"
#include "RQAEpsilon.mqh"
#include "RQAWindow.mqh"
// --- Cross-RQA modules ---
#include "CRQAMatrix.mqh"
#include "CRQAMetrics.mqh"
#include "CRQAWindow.mqh"
// --- Joint-RQA modules ---
#include "JRQAMatrix.mqh"
#include "JRQAMetrics.mqh"
#include "JRQAWindow.mqh"
//+------------------------------------------------------------------+
//| CRQA — high-level facade for single-series RQA |
//+------------------------------------------------------------------+
class CRQA
{
private:
CRQAMatrix m_matrix;
CRQAMetrics m_metrics;
SRQAResult m_result;
bool m_computed;
double m_epsilon;
int m_embDim;
int m_delay;
ENUM_RQA_NORM m_norm;
ENUM_EPSILON_METHOD m_epsilonMethod;
double m_epsilonParam;
public:
CRQA();
void SetEpsilon(double eps)
{ m_epsilon = eps; m_epsilonMethod = EPSILON_FIXED; }
void SetEpsilonAuto(ENUM_EPSILON_METHOD method, double param = 0.05)
{ m_epsilonMethod = method; m_epsilonParam = param; }
void SetEmbedding(int dim, int delay)
{ m_embDim = dim; m_delay = delay; }
void SetNorm(ENUM_RQA_NORM norm) { m_norm = norm; }
void SetMinDiagLine(int v) { m_metrics.SetMinDiagLine(v); }
void SetMinVertLine(int v) { m_metrics.SetMinVertLine(v); }
bool Compute(const double &series[], int N);
void GetResult(SRQAResult &out) const { out = m_result; }
double RR() const { return m_result.RR; }
double DET() const { return m_result.DET; }
double LAM() const { return m_result.LAM; }
double TT() const { return m_result.TT; }
double L() const { return m_result.L; }
double Lmax() const { return m_result.Lmax; }
double Vmax() const { return m_result.Vmax; }
double ENTR() const { return m_result.ENTR; }
double DIV() const { return m_result.DIV; }
double RATIO() const { return m_result.RATIO; }
double TREND() const { return m_result.TREND; }
double COMPLEXITY() const { return m_result.COMPLEXITY; }
void PrintSummary() const;
int MatrixSize() const { return m_matrix.Size(); }
double Epsilon() const { return m_epsilon; }
};
//+------------------------------------------------------------------+
//| Default constructor |
//+------------------------------------------------------------------+
CRQA::CRQA()
: m_computed(false),
m_epsilon(0.1),
m_embDim(1),
m_delay(1),
m_norm(RQA_NORM_EUCLIDEAN),
m_epsilonMethod(EPSILON_FIXED),
m_epsilonParam(0.05)
{
}
//+------------------------------------------------------------------+
//| Build recurrence matrix and compute all RQA metrics |
//+------------------------------------------------------------------+
bool CRQA::Compute(const double &series[], int N)
{
m_computed = false;
m_result.Reset();
if(N < 4)
{
Print("CRQA::Compute — series too short (min 4 bars)");
return false;
}
double eps = m_epsilon;
if(m_epsilonMethod != EPSILON_FIXED)
eps = CRQAEpsilon::Select(series, N, m_epsilonMethod, m_epsilonParam);
m_epsilon = eps;
if(!m_matrix.Build(series, N, eps, m_embDim, m_delay, m_norm))
return false;
if(!m_metrics.Compute(m_matrix, m_result))
return false;
m_computed = true;
return true;
}
//+------------------------------------------------------------------+
//| Print all RQA metrics to the Experts log |
//+------------------------------------------------------------------+
void CRQA::PrintSummary() const
{
if(!m_computed)
{
Print("CRQA: Not computed yet — call Compute() first");
return;
}
PrintFormat("===== RQA Summary =====");
PrintFormat("Epsilon : %.6f (embDim=%d, delay=%d)",
m_epsilon, m_embDim, m_delay);
PrintFormat("RR : %.4f (%.2f%%)", m_result.RR, m_result.RR * 100.0);
PrintFormat("DET : %.4f", m_result.DET);
PrintFormat("LAM : %.4f", m_result.LAM);
PrintFormat("TT : %.4f", m_result.TT);
PrintFormat("L (avg diag): %.4f", m_result.L);
PrintFormat("Lmax : %.0f", m_result.Lmax);
PrintFormat("Vmax : %.0f", m_result.Vmax);
PrintFormat("ENTR : %.4f", m_result.ENTR);
PrintFormat("DIV : %.4f", m_result.DIV);
PrintFormat("RATIO : %.4f", m_result.RATIO);
PrintFormat("TREND : %.6f", m_result.TREND);
PrintFormat("COMPLEXITY : %.6f", m_result.COMPLEXITY);
PrintFormat("=======================");
}
//+------------------------------------------------------------------+
//| CCRQA — high-level facade for Cross-RQA (two series) |
//| |
//| Measures shared dynamic structure between two time series, |
//| e.g. two instruments, price vs indicator, or two timeframes. |
//| |
//| Quick usage: |
//| CCRQA crqa; |
//| crqa.SetEpsilon(0.05); |
//| crqa.SetEmbedding(2, 1); |
//| if(crqa.Compute(closeX, lenX, closeY, lenY)) |
//| crqa.PrintSummary(); |
//| double sync = crqa.CRR(); // cross recurrence rate |
//| double det = crqa.CDET(); // cross determinism |
//+------------------------------------------------------------------+
class CCRQA
{
private:
CCRQAMatrix m_matrix;
CCRQAMetrics m_metrics;
SCRQAResult m_result;
bool m_computed;
double m_epsilon;
int m_embDim;
int m_delay;
ENUM_RQA_NORM m_norm;
public:
CCRQA();
//--- Configuration
void SetEpsilon(double eps) { m_epsilon = eps; }
void SetEmbedding(int dim, int delay) { m_embDim = dim; m_delay = delay; }
void SetNorm(ENUM_RQA_NORM norm) { m_norm = norm; }
void SetMinDiagLine(int v) { m_metrics.SetMinDiagLine(v); }
void SetMinVertLine(int v) { m_metrics.SetMinVertLine(v); }
//--- Main compute — two series (can differ in length)
bool Compute(const double &seriesX[], int lenX,
const double &seriesY[], int lenY);
//--- Results access
void GetResult(SCRQAResult &out) const { out = m_result; }
double CRR() const { return m_result.CRR; }
double CDET() const { return m_result.CDET; }
double CL() const { return m_result.CL; }
double CLmax() const { return m_result.CLmax; }
double CENTR() const { return m_result.CENTR; }
double CDIV() const { return m_result.CDIV; }
double CLAM() const { return m_result.CLAM; }
double CTT() const { return m_result.CTT; }
double CVmax() const { return m_result.CVmax; }
double CRATIO() const { return m_result.CRATIO; }
//--- Print summary
void PrintSummary() const;
//--- Underlying objects
int MatrixRows() const { return m_matrix.SizeN(); }
int MatrixCols() const { return m_matrix.SizeM(); }
double Epsilon() const { return m_epsilon; }
};
//+------------------------------------------------------------------+
//| Default constructor |
//+------------------------------------------------------------------+
CCRQA::CCRQA()
: m_computed(false),
m_epsilon(0.1),
m_embDim(1),
m_delay(1),
m_norm(RQA_NORM_EUCLIDEAN)
{
}
//+------------------------------------------------------------------+
//| Build cross-recurrence matrix and compute all CRQA metrics |
//+------------------------------------------------------------------+
bool CCRQA::Compute(const double &seriesX[], int lenX,
const double &seriesY[], int lenY)
{
m_computed = false;
m_result.Reset();
if(lenX < 4 || lenY < 4)
{
Print("CCRQA::Compute — series too short (min 4 bars each)");
return false;
}
if(!m_matrix.Build(seriesX, lenX, seriesY, lenY,
m_epsilon, m_embDim, m_delay, m_norm))
return false;
if(!m_metrics.Compute(m_matrix, m_result))
return false;
m_computed = true;
return true;
}
//+------------------------------------------------------------------+
//| Print all CRQA metrics to the Experts log |
//+------------------------------------------------------------------+
void CCRQA::PrintSummary() const
{
if(!m_computed)
{
Print("CCRQA: Not computed yet — call Compute() first");
return;
}
PrintFormat("===== Cross-RQA Summary =====");
PrintFormat("Epsilon : %.6f (embDim=%d, delay=%d)",
m_epsilon, m_embDim, m_delay);
PrintFormat("Matrix : %d x %d", m_matrix.SizeN(), m_matrix.SizeM());
PrintFormat("CRR : %.4f (%.2f%%)", m_result.CRR, m_result.CRR * 100.0);
PrintFormat("CDET : %.4f", m_result.CDET);
PrintFormat("CLAM : %.4f", m_result.CLAM);
PrintFormat("CTT : %.4f", m_result.CTT);
PrintFormat("CL (avg diag): %.4f", m_result.CL);
PrintFormat("CLmax : %.0f", m_result.CLmax);
PrintFormat("CVmax : %.0f", m_result.CVmax);
PrintFormat("CENTR : %.4f", m_result.CENTR);
PrintFormat("CDIV : %.4f", m_result.CDIV);
PrintFormat("CRATIO : %.4f", m_result.CRATIO);
PrintFormat("=============================");
}
//+------------------------------------------------------------------+
//| CJRQA — high-level facade for Joint-RQA (two series) |
//| |
//| Measures simultaneous recurrence in two dynamical systems. |
//| JR(i,j) = 1 only when BOTH systems recur at (i,j). |
//| |
//| Quick usage: |
//| CJRQA jrqa; |
//| jrqa.SetEpsilon(0.05); // shared epsilon |
//| jrqa.SetEmbedding(2, 1); |
//| if(jrqa.Compute(closeX, closeY, len)) |
//| jrqa.PrintSummary(); |
//| double jrr = jrqa.JRR(); |
//+------------------------------------------------------------------+
class CJRQA
{
private:
CJRQAMatrix m_matrix;
CJRQAMetrics m_metrics;
SJRQAResult m_result;
bool m_computed;
double m_epsilonX;
double m_epsilonY;
int m_embDim;
int m_delay;
ENUM_RQA_NORM m_norm;
public:
CJRQA();
//--- Configuration
void SetEpsilon(double eps) { m_epsilonX = eps; m_epsilonY = eps; }
void SetEpsilon(double epsX, double epsY){ m_epsilonX = epsX; m_epsilonY = epsY; }
void SetEmbedding(int dim, int delay) { m_embDim = dim; m_delay = delay; }
void SetNorm(ENUM_RQA_NORM norm) { m_norm = norm; }
void SetMinDiagLine(int v) { m_metrics.SetMinDiagLine(v); }
void SetMinVertLine(int v) { m_metrics.SetMinVertLine(v); }
//--- Main compute — two series of equal length
bool Compute(const double &seriesX[], const double &seriesY[],
int seriesLen);
//--- Results access
void GetResult(SJRQAResult &out) const { out = m_result; }
double JRR() const { return m_result.JRR; }
double JDET() const { return m_result.JDET; }
double JLAM() const { return m_result.JLAM; }
double JTT() const { return m_result.JTT; }
double JL() const { return m_result.JL; }
double JLmax() const { return m_result.JLmax; }
double JVmax() const { return m_result.JVmax; }
double JENTR() const { return m_result.JENTR; }
double JDIV() const { return m_result.JDIV; }
double JRATIO() const { return m_result.JRATIO; }
double JTREND() const { return m_result.JTREND; }
double JCOMPLEXITY() const { return m_result.JCOMPLEXITY; }
void PrintSummary() const;
int MatrixSize() const { return m_matrix.Size(); }
double EpsilonX() const { return m_epsilonX; }
double EpsilonY() const { return m_epsilonY; }
};
//+------------------------------------------------------------------+
//| Default constructor |
//+------------------------------------------------------------------+
CJRQA::CJRQA()
: m_computed(false),
m_epsilonX(0.1),
m_epsilonY(0.1),
m_embDim(1),
m_delay(1),
m_norm(RQA_NORM_EUCLIDEAN)
{
}
//+------------------------------------------------------------------+
//| Build joint recurrence matrix and compute all JRQA metrics |
//+------------------------------------------------------------------+
bool CJRQA::Compute(const double &seriesX[], const double &seriesY[],
int seriesLen)
{
m_computed = false;
m_result.Reset();
if(seriesLen < 4)
{
Print("CJRQA::Compute — series too short (min 4 bars)");
return false;
}
if(!m_matrix.Build(seriesX, seriesY, seriesLen,
m_epsilonX, m_epsilonY,
m_embDim, m_delay, m_norm))
return false;
if(!m_metrics.Compute(m_matrix, m_result))
return false;
m_computed = true;
return true;
}
//+------------------------------------------------------------------+
//| Print all JRQA metrics to the Experts log |
//+------------------------------------------------------------------+
void CJRQA::PrintSummary() const
{
if(!m_computed)
{
Print("CJRQA: Not computed yet — call Compute() first");
return;
}
PrintFormat("===== Joint-RQA Summary =====");
PrintFormat("EpsilonX : %.6f EpsilonY: %.6f (embDim=%d, delay=%d)",
m_epsilonX, m_epsilonY, m_embDim, m_delay);
PrintFormat("Matrix : %d x %d", m_matrix.Size(), m_matrix.Size());
PrintFormat("JRR : %.4f (%.2f%%)", m_result.JRR, m_result.JRR * 100.0);
PrintFormat("JDET : %.4f", m_result.JDET);
PrintFormat("JLAM : %.4f", m_result.JLAM);
PrintFormat("JTT : %.4f", m_result.JTT);
PrintFormat("JL (avg diag): %.4f", m_result.JL);
PrintFormat("JLmax : %.0f", m_result.JLmax);
PrintFormat("JVmax : %.0f", m_result.JVmax);
PrintFormat("JENTR : %.4f", m_result.JENTR);
PrintFormat("JDIV : %.4f", m_result.JDIV);
PrintFormat("JRATIO : %.4f", m_result.JRATIO);
PrintFormat("JTREND : %.6f", m_result.JTREND);
PrintFormat("JCOMPLEXITY : %.6f", m_result.JCOMPLEXITY);
PrintFormat("=============================");
}
#endif // RQA_MQH