forked from MasoodIqbal/RSI-Stoch-MA-EA
188 lines
4.7 KiB
MQL5
188 lines
4.7 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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<n; i++)
|
|
{
|
|
json += DoubleToString(feat[i], 8);
|
|
if(i < n-1) json += ",";
|
|
}
|
|
json += "]}";
|
|
return json;
|
|
}
|
|
|
|
// Extract numeric field: "confidence":72.5
|
|
bool NN_ExtractNumber(const string &json, const string &key, double &out)
|
|
{
|
|
int k = StringFind(json, "\"" + key + "\"");
|
|
if(k < 0) return false;
|
|
|
|
int colon = StringFind(json, ":", k);
|
|
if(colon < 0) return false;
|
|
|
|
int endComma = StringFind(json, ",", colon);
|
|
int endBrace = StringFind(json, "}", colon);
|
|
|
|
int end = endComma;
|
|
if(end < 0 || (endBrace >= 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;
|
|
}
|