#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; }