70 lines
4.1 KiB
MQL5
#property strict
| |||
#include "..\Include\ModelPredictor.mqh"
| |||
#include "..\Include\PolicyHttpBridge.mqh"
| |||
| |||
// Test-only identity graph: checks native inference and scaler plumbing.
| |||
// This fixture is not a trained trading model and is never installed in DualEA.
| |||
const uchar SyntheticModel[]={8,8,18,46,68,117,97,108,69,65,32,114,101,103,114,101,115,115,105,111,110,32,102,105,120,116,117,114,101,44,32,110,111,116,32,97,32,116,114,97,105,110,101,100,32,109,111,100,101,108,58,119,10,33,10,8,102,101,97,116,117,114,101,115,18,11,112,114,111,98,97,98,105,108,105,116,121,34,8,73,100,101,110,116,105,116,121,18,23,83,89,78,84,72,69,84,73,67,95,67,79,78,84,82,65,67,84,95,79,78,76,89,90,26,10,8,102,101,97,116,117,114,101,115,18,14,10,12,8,1,18,8,10,2,8,1,10,2,8,2,98,29,10,11,112,114,111,98,97,98,105,108,105,116,121,18,14,10,12,8,1,18,8,10,2,8,1,10,2,8,2,66,2,16,13};
| |||
int g_checks=0;
| |||
int g_failures=0;
| |||
void Check(bool passed,string name)
| |||
{
| |||
g_checks++;
| |||
Print("[NATIVE-CONTRACT] ",passed ? "PASS: " : "FAIL: ",name);
| |||
if(!passed) g_failures++;
| |||
}
| |||
bool WriteText(string path,string text)
| |||
{
| |||
int file=FileOpen(path,FILE_WRITE|FILE_BIN);
| |||
if(file==INVALID_HANDLE) return false;
| |||
uchar bytes[];
| |||
int length=StringToCharArray(text,bytes,0,WHOLE_ARRAY,CP_UTF8)-1;
| |||
bool ok=(FileWriteArray(file,bytes,0,length)==(uint)length);
| |||
FileClose(file);
| |||
return ok;
| |||
}
| |||
int OnInit()
| |||
{
| |||
FolderCreate("NativeContract");
| |||
string model_path="NativeContract\\synthetic_identity.onnx";
| |||
string config_path="NativeContract\\synthetic.ini";
| |||
int file=FileOpen(model_path,FILE_WRITE|FILE_BIN);
| |||
if(file==INVALID_HANDLE) return INIT_FAILED;
| |||
uint written=FileWriteArray(file,SyntheticModel,0,ArraySize(SyntheticModel));
| |||
FileClose(file);
| |||
Check(written==ArraySize(SyntheticModel),"write test-only model fixture");
| |||
Check(WriteText(config_path,"feature_count=2\nfeature_names=a|b\nscaler_mean=1|2\nscaler_scale=2|4\n"),"write UTF-8 INI fixture");
| |||
CModelPredictor predictor;
| |||
Check(!predictor.IsReady(),"new predictor is not ready");
| |||
Check(!predictor.Init("NativeContract\\absent.onnx","",config_path),"missing model fails initialization");
| |||
Check(!predictor.IsReady(),"missing model cannot mark predictor ready");
| |||
Check(predictor.Init(model_path,"",config_path),"native identity model initializes without DLL");
| |||
Check(predictor.FeatureCount()==2,"INI feature count is exact");
| |||
string names[];
| |||
predictor.GetFeatureNames(names);
| |||
Check(ArraySize(names)==2 && names[0]=="a" && names[1]=="b","feature order preserved");
| |||
double features[]={1.4,5.2};
| |||
double probability=predictor.Predict(features,2);
| |||
Check(MathAbs(probability-0.8)<0.00001,"raw features standardize to [0.2,0.8] and infer probability 0.8");
| |||
Check(predictor.Predict(features,1)<0,"wrong feature count returns failure sentinel");
| |||
features[0]=1.0e300;
| |||
Check(predictor.Predict(features,2)<0,"overflowing float input rejected");
| |||
predictor.Shutdown();
| |||
Check(!predictor.IsReady(),"shutdown releases native session");
| |||
Check(predictor.Predict(features,2)<0,"prediction after shutdown fails");
| |||
Check(WriteText(config_path,"feature_count=2\nfeature_names=a|b\nscaler_mean=1|2\nscaler_scale=2\n"),"write malformed metadata fixture");
| |||
Check(!predictor.Init(model_path,"",config_path),"inconsistent scaler length rejected");
| |||
Check(WriteText(config_path,"feature_count=2\nfeature_names=a|b\nscaler_mean=1|2\nscaler_scale=2|0\n"),"write zero-scale metadata fixture");
| |||
Check(!predictor.Init(model_path,"",config_path),"zero scaler denominator rejected");
| |||
CPolicyHttpBridge policy;
| |||
policy.Configure("NativeContract\\absent_policy.json",1);
| |||
if(MQLInfoInteger(MQL_TESTER))
| |||
{
| |||
Check(!policy.VerifyAccess("http://127.0.0.1:1/never-called"),"tester VerifyAccess returns without WebRequest");
| |||
Check(!policy.Pull("http://127.0.0.1:1/never-called"),"tester Pull returns without WebRequest");
| |||
}
| |||
PrintFormat("[NATIVE-CONTRACT] RESULT checks=%d failures=%d",g_checks,g_failures);
| |||
return g_failures==0 ? INIT_SUCCEEDED : INIT_FAILED;
| |||
}
| |||
void OnTick() {}
| |||
double OnTester() { return g_failures==0 ? (double)g_checks : -(double)g_failures; }
|