//+------------------------------------------------------------------+ //| KronosVerifyPredictorS1.mq5 | //| MMQ — Muhammad Minhas Qamar | //| www.mql5.com | //+------------------------------------------------------------------+ #property copyright "MMQ — Muhammad Minhas Qamar" #property link "https://www.mql5.com" #property version "1.00" #property script_show_inputs #property strict #include #define KR_PRED_D_MODEL 512 #define KR_PRED_N_HEADS 8 #define KR_PRED_N_LAYERS 8 #define KR_PRED_FF_DIM 1024 #define KR_PRED_WEIGHT_DIR "kronos_weights\\predictor\\" input string InpRefDir = "kronos_refs\\"; input int InpLookback = 256; input double InpTol = 1e-3; // logits accumulate more rounding than recon; allow 1e-3 //+------------------------------------------------------------------+ //| Read a [rows,cols] float32 .bin into a matrix(double). | //+------------------------------------------------------------------+ bool LoadF32Matrix(const string fname, ulong rows, ulong cols, matrix &out) { int h = FileOpen(fname, FILE_READ | FILE_BIN); if(h == INVALID_HANDLE) { PrintFormat("LoadF32Matrix: cannot open %s (err %d)", fname, GetLastError()); return false; } ulong n = rows * cols; float buf[]; ArrayResize(buf, (int)n); uint got = FileReadArray(h, buf, 0, (int)n); FileClose(h); if(got != n) { PrintFormat("LoadF32Matrix: short read %s", fname); return false; } out = matrix::Zeros(rows, cols); for(ulong r = 0; r < rows; r++) for(ulong c = 0; c < cols; c++) out[r][c] = (double)buf[r * cols + c]; return true; } //+------------------------------------------------------------------+ //| Read N float32 values from a .bin into a double[]. | //+------------------------------------------------------------------+ bool LoadF32Vector(const string fname, int n, double &out[]) { int h = FileOpen(fname, FILE_READ | FILE_BIN); if(h == INVALID_HANDLE) { PrintFormat("LoadF32Vector: cannot open %s (err %d)", fname, GetLastError()); return false; } float buf[]; ArrayResize(buf, n); uint got = FileReadArray(h, buf, 0, n); FileClose(h); if(got != (uint)n) { PrintFormat("LoadF32Vector: short read %s", fname); return false; } ArrayResize(out, n); for(int i = 0; i < n; i++) out[i] = (double)buf[i]; return true; } //+------------------------------------------------------------------+ //| Read N int32 values from a .bin into an int[]. | //+------------------------------------------------------------------+ bool LoadI32Array(const string fname, int n, int &out[]) { int h = FileOpen(fname, FILE_READ | FILE_BIN); if(h == INVALID_HANDLE) { PrintFormat("LoadI32Array: cannot open %s (err %d)", fname, GetLastError()); return false; } ArrayResize(out, n); uint got = FileReadArray(h, out, 0, n); FileClose(h); if(got != (uint)n) { PrintFormat("LoadI32Array: short read %s", fname); return false; } return true; } //+------------------------------------------------------------------+ //| Script entry point. | //+------------------------------------------------------------------+ void OnStart() { Print("============ Kronos predictor decode_s1 verification ============"); const int L = InpLookback; const int V = KR_PRED_VOCAB; // 1024 int s1[], s2[]; if(!LoadI32Array(InpRefDir + "s1_ids.bin", L, s1)) { Print("ABORT: s1_ids.bin"); return; } if(!LoadI32Array(InpRefDir + "s2_ids.bin", L, s2)) { Print("ABORT: s2_ids.bin"); return; } matrix stamp; if(!LoadF32Matrix(InpRefDir + "x_stamp.bin", (ulong)L, 5, stamp)) { Print("ABORT: x_stamp.bin"); return; } double ref[]; if(!LoadF32Vector(InpRefDir + "s1_logits_last.bin", V, ref)) { Print("ABORT: s1_logits_last.bin"); return; } CKronosPredictorS1 pred; if(!pred.Init(KR_PRED_WEIGHT_DIR, KR_PRED_N_LAYERS, KR_PRED_D_MODEL, KR_PRED_N_HEADS, KR_PRED_FF_DIM)) { Print("ABORT: predictor Init failed"); return; } Print("Predictor (s1) weights loaded."); matrix s1_logits, context; if(!pred.DecodeS1(s1, s2, stamp, s1_logits, context)) { Print("ABORT: DecodeS1 failed"); return; } PrintFormat("s1_logits %I64u x %I64u, context %I64u x %I64u", s1_logits.Rows(), s1_logits.Cols(), context.Rows(), context.Cols()); if(s1_logits.Rows() != (ulong)L || s1_logits.Cols() != (ulong)V) { Print("ABORT: logits shape mismatch"); return; } //--- compare LAST time-step logits (row L-1) to the reference vector int last = L - 1; double maxerr = 0.0, sumerr = 0.0; int wcol = -1; for(int j = 0; j < V; j++) { double e = MathAbs(s1_logits[last][j] - ref[j]); sumerr += e; if(e > maxerr) { maxerr = e; wcol = j; } } double meanerr = sumerr / (double)V; PrintFormat("last-step s1 logits: max abs err = %.3e (col %d), mean abs err = %.3e", maxerr, wcol, meanerr); if(wcol >= 0) PrintFormat("worst cell: mql=%.6f ref=%.6f", s1_logits[last][wcol], ref[wcol]); //--- crucial sanity: do MQL5 and reference pick the SAME argmax token? int amx_mql = 0, amx_ref = 0; double bm = s1_logits[last][0], br = ref[0]; for(int j = 1; j < V; j++) { if(s1_logits[last][j] > bm) { bm = s1_logits[last][j]; amx_mql = j; } if(ref[j] > br) { br = ref[j]; amx_ref = j; } } PrintFormat("argmax token: mql=%d ref=%d %s", amx_mql, amx_ref, (amx_mql == amx_ref ? "(MATCH)" : "(DIFFER!)")); if(maxerr <= InpTol && amx_mql == amx_ref) PrintFormat(">>> DECODE_S1 VERIFIED: max abs err %.3e <= tol %.3e, argmax matches. <<<", maxerr, InpTol); else Print(">>> DECODE_S1 MISMATCH: check embedding lookup/scale, temporal sum, " "block count (8, not 7), final norm, or proj_s1 transpose. <<<"); Print("================================================================"); } //+------------------------------------------------------------------+