123 lines
4.2 KiB
MQL5
123 lines
4.2 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Catch22Validate.mq5 |
|
||
|
|
//| MMQ — Muhammad Minhas Qamar |
|
||
|
|
//| www.mql5.com/en/articles/23488 |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "MMQ — Muhammad Minhas Qamar"
|
||
|
|
#property link "https://www.mql5.com/en/articles/23488"
|
||
|
|
#property version "1.00"
|
||
|
|
#property strict
|
||
|
|
#property script_show_inputs
|
||
|
|
|
||
|
|
#include <Catch22\Catch22.mqh>
|
||
|
|
|
||
|
|
//--- pick what to feed the engine: a deterministic fixture (for
|
||
|
|
//--- cross-checking against pycatch22) or live symbol returns.
|
||
|
|
enum ENUM_C22_SOURCE
|
||
|
|
{
|
||
|
|
SRC_FIXTURE, // reproducible sine+noise vector defined below
|
||
|
|
SRC_RETURNS // log returns of the current symbol/timeframe
|
||
|
|
};
|
||
|
|
|
||
|
|
input ENUM_C22_SOURCE InpSource = SRC_FIXTURE; // input data source
|
||
|
|
input int InpLength = 200; // window length
|
||
|
|
input int InpSeed = 12345; // RNG seed for the fixture
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Deterministic fixture: x[i] = sin(2*pi*i/20) + 0.5*sin(i/7) |
|
||
|
|
//| plus a seeded uniform noise term. Fully reproducible so the |
|
||
|
|
//| printed feature vector can be compared to a pycatch22 run on the |
|
||
|
|
//| identical vector (which the script also dumps to a CSV). |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void BuildFixture(double &x[],int n,int seed)
|
||
|
|
{
|
||
|
|
ArrayResize(x,n);
|
||
|
|
MathSrand(seed);
|
||
|
|
for(int i=0;i<n;i++)
|
||
|
|
{
|
||
|
|
double noise=((double)MathRand()/32767.0-0.5)*0.6;
|
||
|
|
x[i]=MathSin(2.0*M_PI*i/20.0)+0.5*MathSin(i/7.0)+noise;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Fill x[] with log returns of the current symbol. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool BuildReturns(double &x[],int n)
|
||
|
|
{
|
||
|
|
int need=n+1;
|
||
|
|
double close[];
|
||
|
|
if(CopyClose(_Symbol,_Period,1,need,close)<need)
|
||
|
|
return false;
|
||
|
|
ArraySetAsSeries(close,false);
|
||
|
|
ArrayResize(x,n);
|
||
|
|
for(int i=0;i<n;i++)
|
||
|
|
{
|
||
|
|
if(close[i]<=0.0 || close[i+1]<=0.0)
|
||
|
|
{
|
||
|
|
x[i]=0.0;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
x[i]=MathLog(close[i+1]/close[i]);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Dump the input vector to Files\ so it can be re-run through |
|
||
|
|
//| pycatch22 for an external, side-by-side comparison. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void DumpInput(const double &x[],int n,string tag)
|
||
|
|
{
|
||
|
|
string fname="Catch22\\input_"+tag+".csv";
|
||
|
|
int h=FileOpen(fname,FILE_WRITE|FILE_CSV|FILE_ANSI,",");
|
||
|
|
if(h==INVALID_HANDLE)
|
||
|
|
{
|
||
|
|
PrintFormat("Could not write %s (err %d)",fname,GetLastError());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for(int i=0;i<n;i++)
|
||
|
|
FileWrite(h,DoubleToString(x[i],10));
|
||
|
|
FileClose(h);
|
||
|
|
PrintFormat("Wrote input vector to MQL5\\Files\\%s",fname);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Script entry: build the data, compute catch22, print the named |
|
||
|
|
//| vector, and persist the input for external validation. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnStart()
|
||
|
|
{
|
||
|
|
double x[];
|
||
|
|
string tag;
|
||
|
|
if(InpSource==SRC_FIXTURE)
|
||
|
|
{
|
||
|
|
BuildFixture(x,InpLength,InpSeed);
|
||
|
|
tag="fixture";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if(!BuildReturns(x,InpLength))
|
||
|
|
{
|
||
|
|
Print("Not enough history to build returns.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
tag="returns";
|
||
|
|
}
|
||
|
|
|
||
|
|
CCatch22 c;
|
||
|
|
double feats[];
|
||
|
|
if(!c.Compute(x,InpLength,feats))
|
||
|
|
{
|
||
|
|
Print("Compute() failed: degenerate window (constant or too short).");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Print("=== catch22 feature vector (",tag,", n=",InpLength,") ===");
|
||
|
|
for(int i=0;i<CATCH22_N;i++)
|
||
|
|
PrintFormat("%2d %-46s = % .8f",i,CCatch22::Name(i),feats[i]);
|
||
|
|
|
||
|
|
DumpInput(x,InpLength,tag);
|
||
|
|
Print("=== done ===");
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|