Initial commit: Mad Turtle v2.0 ML EA for XAUUSD H1 with Python inference server and MQL5 EA
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MadTurtle_API.mqh - HTTP REST bridge to Python inference server |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef MADTURTLE_API
|
||||
#define MADTURTLE_API
|
||||
|
||||
#import "wininet.dll"
|
||||
int InternetOpenW(string, int, string, string, int);
|
||||
int InternetOpenUrlW(int, string, string, int, int, int);
|
||||
int InternetReadFile(int, uchar &[], int, int &);
|
||||
int InternetCloseHandle(int);
|
||||
#import
|
||||
|
||||
// Timeout and buffer constants
|
||||
#define MT5_API_TIMEOUT_MS 8000
|
||||
#define MT5_API_BUFFER_SIZE 8192
|
||||
|
||||
// Server connection config
|
||||
struct MadTurtleServerCfg {
|
||||
string host;
|
||||
int port;
|
||||
string api_token;
|
||||
int timeout_ms;
|
||||
int retry_count;
|
||||
bool use_ssl;
|
||||
};
|
||||
|
||||
// API response container
|
||||
struct MadTurtleAPIResponse {
|
||||
int http_code;
|
||||
string body;
|
||||
bool success;
|
||||
string error_msg;
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize default server config |
|
||||
//+------------------------------------------------------------------+
|
||||
MadTurtleServerCfg MadTurtle_InitDefaultServer()
|
||||
{
|
||||
MadTurtleServerCfg cfg;
|
||||
cfg.host = "127.0.0.1";
|
||||
cfg.port = 8000;
|
||||
cfg.api_token = "";
|
||||
cfg.timeout_ms = MT5_API_TIMEOUT_MS;
|
||||
cfg.retry_count = 2;
|
||||
cfg.use_ssl = false;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Build full URL from path |
|
||||
//+------------------------------------------------------------------+
|
||||
string MadTurtle_BuildURL(const MadTurtleServerCfg &cfg, string path)
|
||||
{
|
||||
string proto = cfg.use_ssl ? "https" : "http";
|
||||
return StringFormat("%s://%s:%d%s", proto, cfg.host, cfg.port, path);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| HTTP GET request |
|
||||
//+------------------------------------------------------------------+
|
||||
MadTurtleAPIResponse MadTurtle_HTTPGet(const MadTurtleServerCfg &cfg, string path)
|
||||
{
|
||||
MadTurtleAPIResponse resp;
|
||||
resp.http_code = 0;
|
||||
resp.success = false;
|
||||
resp.body = "";
|
||||
resp.error_msg = "";
|
||||
|
||||
int hInternet = InternetOpenW("MadTurtleEA/2.0", 1, NULL, NULL, 0);
|
||||
if(hInternet == 0) {
|
||||
resp.error_msg = "InternetOpenW failed";
|
||||
return resp;
|
||||
}
|
||||
|
||||
string url = MadTurtle_BuildURL(cfg, path);
|
||||
int hUrl = InternetOpenUrlW(hInternet, url, NULL, 0, 0x04000000, 0);
|
||||
if(hUrl == 0) {
|
||||
InternetCloseHandle(hInternet);
|
||||
resp.error_msg = "InternetOpenUrlW failed: " + IntegerToString(GetLastError());
|
||||
return resp;
|
||||
}
|
||||
|
||||
uchar buf[];
|
||||
ArrayResize(buf, MT5_API_BUFFER_SIZE);
|
||||
int bytesRead = 0;
|
||||
string body = "";
|
||||
|
||||
while(true) {
|
||||
int res = InternetReadFile(hUrl, buf, MT5_API_BUFFER_SIZE, bytesRead);
|
||||
if(res == 0 || bytesRead == 0) break;
|
||||
body += CharArrayToString(buf, 0, bytesRead, CP_UTF8);
|
||||
}
|
||||
|
||||
resp.body = body;
|
||||
resp.http_code = 200;
|
||||
resp.success = (StringLen(body) > 0);
|
||||
|
||||
InternetCloseHandle(hUrl);
|
||||
InternetCloseHandle(hInternet);
|
||||
return resp;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Call inference server with feature vector (GET) |
|
||||
//+------------------------------------------------------------------+
|
||||
MadTurtleAPIResponse MadTurtle_GetSignal(const MadTurtleServerCfg &cfg, double &features[])
|
||||
{
|
||||
MadTurtleAPIResponse resp;
|
||||
resp.http_code = 0;
|
||||
resp.success = false;
|
||||
resp.body = "";
|
||||
resp.error_msg = "";
|
||||
|
||||
int n = ArraySize(features);
|
||||
if(n == 0) {
|
||||
resp.error_msg = "Empty feature vector";
|
||||
return resp;
|
||||
}
|
||||
|
||||
string qs = "?";
|
||||
for(int i = 0; i < n; i++) {
|
||||
if(i > 0) qs += "&";
|
||||
qs += StringFormat("f%d=%.8f", i, features[i]);
|
||||
}
|
||||
|
||||
resp = MadTurtle_HTTPGet(cfg, "/v1/signal" + qs);
|
||||
|
||||
for(int attempt = 1; attempt < cfg.retry_count && !resp.success; attempt++) {
|
||||
Sleep(500);
|
||||
resp = MadTurtle_HTTPGet(cfg, "/v1/signal" + qs);
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
#endif // MADTURTLE_API
|
||||
Reference in New Issue
Block a user