//+------------------------------------------------------------------+ //| KronosBench.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_TOK_DIR "kronos_weights\\tokenizer\\" #define KR_PRED_DIR "kronos_weights\\predictor\\" input string InpRefDir = "kronos_refs\\"; // reuse x_norm/x_stamp for input input int InpLookback = 64; // context bars input int InpPredLen = 4; input int InpSampleCount = 1; input bool InpGreedy = true; //+------------------------------------------------------------------+ //| 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("open fail %s (%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("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; } //+------------------------------------------------------------------+ //| Script entry point. | //+------------------------------------------------------------------+ void OnStart() { const int L = InpLookback, P = InpPredLen; Print("============ Kronos benchmark ============"); PrintFormat("config: lookback=%d pred_len=%d sample_count=%d greedy=%s", L, P, InpSampleCount, (InpGreedy ? "true" : "false")); //--- input: take the first L rows of the reference x_norm window (already normalized) matrix x_norm_full, x_stamp_full; if(!LoadF32Matrix(InpRefDir + "x_norm.bin", 256, KR_NFEAT, x_norm_full)) return; if(!LoadF32Matrix(InpRefDir + "x_stamp.bin", 256, 5, x_stamp_full)) return; if(L > 256) { Print("lookback>256 not available from refs"); return; } matrix x_norm = matrix::Zeros((ulong)L, KR_NFEAT); for(int i = 0; i < L; i++) for(int j = 0; j < KR_NFEAT; j++) x_norm[i][j] = x_norm_full[i][j]; matrix full_stamp = matrix::Zeros((ulong)(L + P), 5); for(int i = 0; i < L; i++) for(int j = 0; j < 5; j++) full_stamp[i][j] = x_stamp_full[i][j]; //--- reuse last context stamp for the horizon (timing only, values irrelevant) for(int i = 0; i < P; i++) for(int j = 0; j < 5; j++) full_stamp[L + i][j] = x_stamp_full[L - 1][j]; CKronosModel model; uint t0 = GetTickCount(); if(!model.Init(KR_TOK_DIR, 4, 4, 256, 4, 512, KR_PRED_DIR, 8, 512, 8, 1024, 512)) { Print("Init failed"); return; } PrintFormat("weight load: %u ms", GetTickCount() - t0); //--- one full path (greedy, 1 sample) uint t1 = GetTickCount(); matrix pred; int g1[], g2[]; if(!model.GeneratePathNorm(x_norm, full_stamp, P, 1.0, 0, 1.0, InpGreedy, pred, g1, g2)) { Print("GeneratePathNorm failed"); return; } uint dt = GetTickCount() - t1; PrintFormat("ONE path (L=%d, P=%d): %u ms -> ~%.1f ms/step", L, P, dt, (double)dt / P); PrintFormat("=> full forecast at sample_count=%d would be ~%u ms", InpSampleCount, dt * InpSampleCount); Print("=========================================="); } //+------------------------------------------------------------------+