Initial commit: Mad Turtle v2.0 ML EA for XAUUSD H1 with Python inference server and MQL5 EA

This commit is contained in:
Visi
2026-06-13 15:27:41 +01:00
commit a5bfac82e4
21 changed files with 13055 additions and 0 deletions
+138
View File
@@ -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
+134
View File
@@ -0,0 +1,134 @@
//+------------------------------------------------------------------+
//| MadTurtle_MTF.mqh - Multi-Timeframe confirmation filters |
//+------------------------------------------------------------------+
#ifndef MADTURTLE_MTF
#define MADTURTLE_MTF
struct MadTurtleMTFState {
double h4_sma_fast;
double h4_sma_slow;
double h4_rsi;
double h4_macd;
double h4_volume_ratio;
ENUM_ORDER_TYPE h4_bias;
double d1_sma_fast;
double d1_sma_slow;
double d1_rsi;
double d1_volume_ratio;
ENUM_ORDER_TYPE d1_bias;
datetime h4_updated;
datetime d1_updated;
};
//+------------------------------------------------------------------+
//| Indicator value helpers (MQL5 handle + CopyBuffer) |
//+------------------------------------------------------------------+
double MadTurtle_GetMA(ENUM_TIMEFRAMES tf, int period, int shift)
{
int h = iMA(_Symbol, tf, period, 0, MODE_SMA, PRICE_CLOSE);
if(h == INVALID_HANDLE) return 0;
double buf[];
if(CopyBuffer(h, 0, shift, 1, buf) != 1) { IndicatorRelease(h); return 0; }
IndicatorRelease(h);
return buf[0];
}
double MadTurtle_GetRSI(ENUM_TIMEFRAMES tf, int period, int shift)
{
int h = iRSI(_Symbol, tf, period, PRICE_CLOSE);
if(h == INVALID_HANDLE) return 0;
double buf[];
if(CopyBuffer(h, 0, shift, 1, buf) != 1) { IndicatorRelease(h); return 0; }
IndicatorRelease(h);
return buf[0];
}
double MadTurtle_GetATR(ENUM_TIMEFRAMES tf, int period, int shift)
{
int h = iATR(_Symbol, tf, period);
if(h == INVALID_HANDLE) return 0;
double buf[];
if(CopyBuffer(h, 0, shift, 1, buf) != 1) { IndicatorRelease(h); return 0; }
IndicatorRelease(h);
return buf[0];
}
double MadTurtle_GetMACD(ENUM_TIMEFRAMES tf, int fast, int slow, int signal, int shift)
{
int h = iMACD(_Symbol, tf, fast, slow, signal, PRICE_CLOSE);
if(h == INVALID_HANDLE) return 0;
double buf[];
if(CopyBuffer(h, 0, shift, 1, buf) != 1) { IndicatorRelease(h); return 0; }
IndicatorRelease(h);
return buf[0];
}
double MadTurtle_GetVolume(ENUM_TIMEFRAMES tf, int shift)
{
long vol = iVolume(_Symbol, tf, shift);
return (double)vol;
}
ENUM_ORDER_TYPE MadTurtle_MTF_BiasFromSMA(double sma_fast, double sma_slow)
{
if(sma_fast > sma_slow && sma_fast > 0 && sma_slow > 0) return ORDER_TYPE_BUY;
if(sma_fast < sma_slow && sma_fast > 0 && sma_slow > 0) return ORDER_TYPE_SELL;
return -1;
}
//+------------------------------------------------------------------+
//| Update multi-timeframe state |
//+------------------------------------------------------------------+
void MadTurtle_UpdateMTFState(MadTurtleMTFState &state)
{
datetime now = TimeCurrent();
if(now - state.h4_updated >= 60) {
state.h4_sma_fast = MadTurtle_GetMA(PERIOD_H4, 10, 1);
state.h4_sma_slow = MadTurtle_GetMA(PERIOD_H4, 50, 1);
state.h4_rsi = MadTurtle_GetRSI(PERIOD_H4, 14, 1);
state.h4_macd = MadTurtle_GetMACD(PERIOD_H4, 12, 26, 9, 1);
state.h4_volume_ratio = MadTurtle_GetVolume(PERIOD_H4, 1);
state.h4_bias = MadTurtle_MTF_BiasFromSMA(state.h4_sma_fast, state.h4_sma_slow);
state.h4_updated = now;
}
if(now - state.d1_updated >= 60) {
state.d1_sma_fast = MadTurtle_GetMA(PERIOD_D1, 10, 1);
state.d1_sma_slow = MadTurtle_GetMA(PERIOD_D1, 50, 1);
state.d1_rsi = MadTurtle_GetRSI(PERIOD_D1, 14, 1);
state.d1_volume_ratio = MadTurtle_GetVolume(PERIOD_D1, 1);
state.d1_bias = MadTurtle_MTF_BiasFromSMA(state.d1_sma_fast, state.d1_sma_slow);
state.d1_updated = now;
}
}
//+------------------------------------------------------------------+
//| Check if MTF confirmation allows a BUY |
//+------------------------------------------------------------------+
bool MadTurtle_MTF_ConfirmBuy(const MadTurtleMTFState &state)
{
if(state.h4_bias != ORDER_TYPE_BUY) return false;
if(state.d1_bias == ORDER_TYPE_SELL) return false;
if(state.h4_rsi > 75.0) return false;
if(state.d1_rsi > 75.0) return false;
if(state.h4_macd < 0 && state.d1_sma_fast < state.d1_sma_slow) return false;
return true;
}
//+------------------------------------------------------------------+
//| Check if MTF confirmation allows a SELL |
//+------------------------------------------------------------------+
bool MadTurtle_MTF_ConfirmSell(const MadTurtleMTFState &state)
{
if(state.h4_bias != ORDER_TYPE_SELL) return false;
if(state.d1_bias == ORDER_TYPE_BUY) return false;
if(state.h4_rsi < 25.0) return false;
if(state.d1_rsi < 25.0) return false;
if(state.h4_macd > 0 && state.d1_sma_fast > state.d1_sma_slow) return false;
return true;
}
#endif // MADTURTLE_MTF
+154
View File
@@ -0,0 +1,154 @@
//+------------------------------------------------------------------+
//| MadTurtle_UI.mqh - Status Dashboard, P&L, Signal Oscillator |
//+------------------------------------------------------------------+
#ifndef MADTURTLE_UI
#define MADTURTLE_UI
// UI color theme
#define UI_COLOR_BG clrBlack
#define UI_COLOR_PANEL clrDarkSlateGray
#define UI_COLOR_TEXT clrWhite
#define UI_COLOR_PROFIT clrLime
#define UI_COLOR_LOSS clrRed
#define UI_COLOR_BUY clrDodgerBlue
#define UI_COLOR_SELL clrOrangeRed
#define UI_COLOR_HOLD clrGray
#define UI_COLOR_ACCENT clrAqua
// Panel layout (x, y, w, h)
#define UI_STATUS_X 10
#define UI_STATUS_Y 10
#define UI_STATUS_W 280
#define UI_STATUS_H 180
#define UI_METRICS_X 10
#define UI_METRICS_Y 200
#define UI_METRICS_W 280
#define UI_METRICS_H 120
#define UI_OSC_X 300
#define UI_OSC_Y 10
#define UI_OSC_W 220
#define UI_OSC_H 140
//+------------------------------------------------------------------+
//| Draw rounded rectangle panel |
//+------------------------------------------------------------------+
void MadTurtle_DrawPanel(int x, int y, int w, int h, color bg = UI_COLOR_PANEL, color border = UI_COLOR_ACCENT)
{
string name = StringFormat("panel_bg_%d_%d", x, y);
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_RECTANGLE, 0, 0, 0);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetInteger(0, name, OBJPROP_COLOR, border);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, name, OBJPROP_FILL, true);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| Draw label text on panel |
//+------------------------------------------------------------------+
void MadTurtle_DrawLabel(string objName, string text, int x, int y, int fontSize = 9,
color clr = UI_COLOR_TEXT, int anchor = ANCHOR_LEFT_UPPER)
{
if(ObjectFind(0, objName) < 0) {
ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0);
}
ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, y);
ObjectSetString(0, objName, OBJPROP_TEXT, text);
ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, objName, OBJPROP_ANCHOR, anchor);
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| Draw mini equity curve (simple text + bar) |
//+------------------------------------------------------------------+
void MadTurtle_DrawEquityCurve(double &equity[], int x, int y, int w, int h, color lineClr = UI_COLOR_PROFIT)
{
int n = ArraySize(equity);
if(n < 2) return;
double minE = equity[ArrayMinimum(equity)];
double maxE = equity[ArrayMaximum(equity)];
if(maxE - minE < 1e-6) maxE = minE + 1.0;
// Draw as vertical bars in a rectangle
int barW = (int)((double)w / n);
if(barW < 1) barW = 1;
for(int i = 0; i < n; i++) {
int barH = (int)((equity[i] - minE) / (maxE - minE) * h);
if(barH < 1) barH = 1;
string barName = StringFormat("eq_bar_%d", i);
if(ObjectFind(0, barName) < 0) {
ObjectCreate(0, barName, OBJ_RECTANGLE, 0, 0, 0);
}
ObjectSetInteger(0, barName, OBJPROP_XDISTANCE, x + i * barW);
ObjectSetInteger(0, barName, OBJPROP_YDISTANCE, y + h - barH);
ObjectSetInteger(0, barName, OBJPROP_XSIZE, barW);
ObjectSetInteger(0, barName, OBJPROP_YSIZE, barH);
ObjectSetInteger(0, barName, OBJPROP_COLOR, lineClr);
ObjectSetInteger(0, barName, OBJPROP_FILL, true);
ObjectSetInteger(0, barName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, barName, OBJPROP_HIDDEN, true);
}
}
//+------------------------------------------------------------------+
//| Draw signal oscillator bars (buy/sell confidence) |
//+------------------------------------------------------------------+
void MadTurtle_DrawOscillator(double buyConf, double sellConf, int x, int y, int w, int h)
{
string objBuy = "osc_buy_bar";
string objSell = "osc_sell_bar";
if(ObjectFind(0, objBuy) < 0) ObjectCreate(0, objBuy, OBJ_RECTANGLE, 0, 0, 0);
if(ObjectFind(0, objSell) < 0) ObjectCreate(0, objSell, OBJ_RECTANGLE, 0, 0, 0);
int buyH = (int)(buyConf / 100.0 * h);
int sellH = (int)(sellConf / 100.0 * h);
ObjectSetInteger(0, objBuy, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, objBuy, OBJPROP_YDISTANCE, y + h - buyH);
ObjectSetInteger(0, objBuy, OBJPROP_XSIZE, w / 2 - 2);
ObjectSetInteger(0, objBuy, OBJPROP_YSIZE, buyH);
ObjectSetInteger(0, objBuy, OBJPROP_COLOR, UI_COLOR_BUY);
ObjectSetInteger(0, objBuy, OBJPROP_FILL, true);
ObjectSetInteger(0, objBuy, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objBuy, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, objSell, OBJPROP_XDISTANCE, x + w / 2 + 2);
ObjectSetInteger(0, objSell, OBJPROP_YDISTANCE, y + h - sellH);
ObjectSetInteger(0, objSell, OBJPROP_XSIZE, w / 2 - 2);
ObjectSetInteger(0, objSell, OBJPROP_YSIZE, sellH);
ObjectSetInteger(0, objSell, OBJPROP_COLOR, UI_COLOR_SELL);
ObjectSetInteger(0, objSell, OBJPROP_FILL, true);
ObjectSetInteger(0, objSell, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objSell, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| Clean up all UI objects on deinit |
//+------------------------------------------------------------------+
void MadTurtle_CleanupUI()
{
ObjectsDeleteAll(0, "panel_bg_");
ObjectsDeleteAll(0, "ui_label_");
ObjectsDeleteAll(0, "eq_bar_");
ObjectsDeleteAll(0, "osc_");
ObjectsDeleteAll(0, "sig_arrow_");
}
#endif // MADTURTLE_UI