2026-02-05 23:31:20 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| InsightsLoader.mqh - Load insights from JSON for LiveEA gating |
|
| | | //+------------------------------------------------------------------+
|
| | | #ifndef INSIGHTSLOADER_MQH
|
| | | #define INSIGHTSLOADER_MQH
|
2025-08-14 19:15:34 -04:00 | | |
|
2026-02-05 23:31:20 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Load insights from insights.json in Common Files |
|
| | | //+------------------------------------------------------------------+
|
| | | int Insights_Load_Default(
|
| | | string &out_strat[],
|
| | | string &out_sym[],
|
| | | int &out_tf[],
|
| | | int &out_cnt[],
|
| | | double &out_wr[],
|
| | | double &out_avgR[],
|
| | | double &out_pf[],
|
| | | double &out_dd[]
|
| | | )
|
2025-08-14 19:15:34 -04:00 | | | {
|
2026-02-05 23:31:20 -05:00 | | | // Reset arrays
|
| | | ArrayResize(out_strat, 0);
|
| | | ArrayResize(out_sym, 0);
|
| | | ArrayResize(out_tf, 0);
|
| | | ArrayResize(out_cnt, 0);
|
| | | ArrayResize(out_wr, 0);
|
| | | ArrayResize(out_avgR, 0);
|
| | | ArrayResize(out_pf, 0);
|
| | | ArrayResize(out_dd, 0);
|
| | |
|
| | | string path = "DualEA\\insights.json";
|
2026-02-24 12:47:37 -05:00 | | | FolderCreate("DualEA", FILE_COMMON);
|
| | | if(!FileIsExist(path, FILE_COMMON))
|
| | | {
|
| | | return 0; // Cold start: insights not generated yet
|
| | | }
|
2026-02-05 23:31:20 -05:00 | | | int h = FileOpen(path, FILE_READ|FILE_TXT|FILE_COMMON|FILE_ANSI);
|
| | | if(h == INVALID_HANDLE)
|
| | | {
|
2026-02-24 12:47:37 -05:00 | | | int err = GetLastError();
|
| | | static datetime s_last_warn = 0;
|
| | | static int s_last_err = -1;
|
| | | datetime now = TimeCurrent();
|
| | | if((now - s_last_warn) >= 300 || err != s_last_err)
|
| | | {
|
| | | PrintFormat("[InsightsLoader] Cannot open %s (Common). Err=%d", path, err);
|
| | | s_last_warn = now;
|
| | | s_last_err = err;
|
| | | }
|
| | | return 0; // Treat as no insights available
|
2026-02-05 23:31:20 -05:00 | | | }
|
| | |
|
| | | string cur_s = "", cur_y = "";
|
| | | int cur_tf = -1, cur_cnt = 0;
|
| | | double cur_wr = 0.0, cur_avgR = 0.0, cur_pf = 0.0, cur_dd = 0.0;
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | while(!FileIsEnding(h))
|
| | | {
|
| | | string line = FileReadString(h);
|
2026-02-05 23:31:20 -05:00 | | | if(line == "" && FileIsEnding(h)) break;
|
| | |
|
| | | int p;
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // strategy
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"strategy\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int q = StringFind(line, ",", p+1);
|
| | | string seg = (q > p ? StringSubstr(line, p, q-p) : StringSubstr(line, p));
|
| | | int c3 = StringFind(seg, "\"", 0);
|
| | | c3 = StringFind(seg, "\"", c3+1);
|
| | | int c4 = StringFind(seg, "\"", c3+1);
|
| | | int c5 = StringFind(seg, "\"", c4+1);
|
| | | if(c4 > 0 && c5 > c4)
|
| | | cur_s = StringSubstr(seg, c4+1, c5-c4-1);
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // symbol
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"symbol\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int q = StringFind(line, ",", p+1);
|
| | | string seg = (q > p ? StringSubstr(line, p, q-p) : StringSubstr(line, p));
|
| | | int c3 = StringFind(seg, "\"", 0);
|
| | | c3 = StringFind(seg, "\"", c3+1);
|
| | | int c4 = StringFind(seg, "\"", c3+1);
|
| | | int c5 = StringFind(seg, "\"", c4+1);
|
| | | if(c4 > 0 && c5 > c4)
|
| | | cur_y = StringSubstr(seg, c4+1, c5-c4-1);
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // timeframe
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"timeframe\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_tf = (int)StringToInteger(num);
|
| | | }
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // trade_count
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"trade_count\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_cnt = (int)StringToInteger(num);
|
| | | }
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // win_rate
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"win_rate\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_wr = StringToDouble(num);
|
| | | }
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // avg_R
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"avg_R\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_avgR = StringToDouble(num);
|
| | | }
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // profit_factor
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"profit_factor\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_pf = StringToDouble(num);
|
| | | }
|
| | | }
|
| | |
|
2025-08-14 19:15:34 -04:00 | | | // max_drawdown_R
|
2026-02-05 23:31:20 -05:00 | | | p = StringFind(line, "\"max_drawdown_R\"", 0);
|
| | | if(p >= 0)
|
| | | {
|
| | | int c = StringFind(line, ":", p);
|
| | | if(c >= 0)
|
| | | {
|
| | | string num = StringSubstr(line, c+1);
|
| | | StringTrimLeft(num);
|
| | | cur_dd = StringToDouble(num);
|
| | | }
|
| | | }
|
| | |
|
| | | // Commit when we have strategy and symbol
|
| | | if(cur_s != "" && cur_y != "" && cur_tf >= 0)
|
2025-08-14 19:15:34 -04:00 | | | {
|
| | | int n = ArraySize(out_strat);
|
2026-02-05 23:31:20 -05:00 | | | ArrayResize(out_strat, n+1);
|
| | | ArrayResize(out_sym, n+1);
|
| | | ArrayResize(out_tf, n+1);
|
| | | ArrayResize(out_cnt, n+1);
|
| | | ArrayResize(out_wr, n+1);
|
| | | ArrayResize(out_avgR, n+1);
|
| | | ArrayResize(out_pf, n+1);
|
| | | ArrayResize(out_dd, n+1);
|
| | |
|
| | | out_strat[n] = cur_s;
|
| | | out_sym[n] = cur_y;
|
| | | out_tf[n] = cur_tf;
|
| | | out_cnt[n] = cur_cnt;
|
| | | out_wr[n] = cur_wr;
|
| | | out_avgR[n] = cur_avgR;
|
| | | out_pf[n] = cur_pf;
|
| | | out_dd[n] = cur_dd;
|
| | |
|
| | | // Reset for next slice
|
| | | cur_s = "";
|
| | | cur_y = "";
|
| | | cur_tf = -1;
|
| | | cur_cnt = 0;
|
| | | cur_wr = 0.0;
|
| | | cur_avgR = 0.0;
|
| | | cur_pf = 0.0;
|
| | | cur_dd = 0.0;
|
2025-08-14 19:15:34 -04:00 | | | }
|
| | | }
|
2026-02-05 23:31:20 -05:00 | | |
|
2025-08-14 19:15:34 -04:00 | | | FileClose(h);
|
2026-02-05 23:31:20 -05:00 | | |
|
| | | int loaded = ArraySize(out_strat);
|
| | | if(loaded > 0)
|
| | | PrintFormat("[InsightsLoader] Loaded %d insight slices", loaded);
|
| | | else
|
| | | Print("[InsightsLoader] No slices loaded (cold start mode)");
|
| | |
|
| | | return loaded;
|
2025-08-14 19:15:34 -04:00 | | | }
|
| | |
|
2026-02-05 23:31:20 -05:00 | | | #endif // INSIGHTSLOADER_MQH
|