//+------------------------------------------------------------------+ //| NeuralNet.mqh | //| Neural Network integration layer (Python REST inference) | //+------------------------------------------------------------------+ #property strict #include "GlobalVariables.mqh" #include "InputParams.mqh" #include "NNFeatures.mqh" // Trim helper string NN_Trim(const string s) { string x = s; StringTrimLeft(x); StringTrimRight(x); return x; } // Build JSON payload: {"symbol":"XAUUSD","tf":"M5","features":[...]} string NN_BuildPayload(const double &feat[]) { string tf = EnumToString((ENUM_TIMEFRAMES)Period()); string json = "{"; json += "\"symbol\":\"" + _Symbol + "\","; json += "\"tf\":\"" + tf + "\","; json += "\"features\":["; int n = ArraySize(feat); for(int i=0; i= 0 && endBrace < end)) end = endBrace; if(end < 0) return false; string val = StringSubstr(json, colon+1, end - (colon+1)); val = NN_Trim(val); out = StringToDouble(val); return true; } bool NN_ExtractInt(const string &json, const string &key, int &out) { double tmp=0.0; if(!NN_ExtractNumber(json, key, tmp)) return false; out = (int)MathRound(tmp); return true; } // Extract string: "explain":"text..." bool NN_ExtractString(const string &json, const string &key, string &out) { int k = StringFind(json, "\"" + key + "\""); if(k < 0) return false; int colon = StringFind(json, ":", k); if(colon < 0) return false; int q1 = StringFind(json, "\"", colon+1); if(q1 < 0) return false; int q2 = StringFind(json, "\"", q1+1); if(q2 < 0) return false; out = StringSubstr(json, q1+1, q2-q1-1); return true; } bool NN_WebPredict(const string url, const string jsonPayload, string &response) { char post[], result[]; string headers = "Content-Type: application/json\r\n"; int timeout = NN_TimeoutMs; StringToCharArray(jsonPayload, post); ResetLastError(); string result_headers; int res = WebRequest("POST", url, headers, timeout, post, result, result_headers); if(res == -1) { if(NN_DebugPrint) Print("NN WebRequest failed. Error=", GetLastError(), " | URL=", url); return false; } response = CharArrayToString(result); return true; } bool InitializeNeuralNet() { if(!Use_NeuralNet) return false; // Ensure these globals exist in GlobalVariables.mqh: // NN_Initialized, NN_LastRun, NN_Bias, NN_Confidence, NN_RiskScore, NN_Explain NN_Initialized = true; NN_LastRun = 0; NN_Bias = 0; NN_Confidence = 0.0; NN_RiskScore = 50.0; NN_Explain = "NN init ok"; return true; } bool UpdateNeuralNetSignal() { if(!Use_NeuralNet || !NN_Initialized) return false; datetime now = TimeCurrent(); if(NN_LastRun > 0 && (now - NN_LastRun) < NN_CooldownSeconds) return false; double feat[]; int n = BuildNNFeatures(feat); if(n <= 0) return false; string payload = NN_BuildPayload(feat); string resp; if(!NN_WebPredict(NN_ServerURL, payload, resp)) { NN_Explain = "NN request failed"; return false; } int bias=0; double conf=0.0, risk=50.0; string explain=""; bool ok1 = NN_ExtractInt(resp, "bias", bias); bool ok2 = NN_ExtractNumber(resp, "confidence", conf); bool ok3 = NN_ExtractNumber(resp, "risk", risk); NN_ExtractString(resp, "explain", explain); if(!(ok1 && ok2 && ok3)) { NN_Explain = "NN parse failed: " + resp; return false; } if(bias > 1) bias = 1; if(bias < -1) bias = -1; conf = NN_Clamp(conf, 0.0, 100.0); risk = NN_Clamp(risk, 0.0, 100.0); NN_Bias = bias; NN_Confidence = conf; NN_RiskScore = risk; NN_Explain = (explain == "" ? "ok" : explain); NN_LastRun = now; if(NN_DebugPrint) Print("NN => bias=", NN_Bias, " conf=", DoubleToString(NN_Confidence,1), " risk=", DoubleToString(NN_RiskScore,1), " | ", NN_Explain); return true; } bool NN_IsUsable() { if(!Use_NeuralNet || !NN_Initialized) return false; if(NN_Confidence < NN_MinConfidenceToUse) return false; if(NN_RiskScore > NN_MaxRiskToUse) return false; return true; }