mql5/Include/Dashboard/EnhancedMultiSymbolDashboard.mqh
Salman Khan 2b2e3f6905 🚀 Revolutionary AI Trading System - MQL5 Professional Edition
 Complete Expert Advisor with AI intelligence
 Professional MQL5 library structure
 Advanced risk management and trade execution
 Comprehensive installation documentation

🎯 MQL5 Features:
- Conviction-based trading intelligence
- Probability-driven position sizing (Kelly Criterion)
- Market edge strength analysis
- Dynamic TP/SL management based on risk scenarios
- AI-powered market narratives dashboard
- Multi-layered risk management system

📦 Installation:
- Copy RevolutionaryAI_EA_FINAL.mq5 to MQL5/Experts/
- Copy Include/ folder to MQL5/Include/
- Compile and attach to chart
- Works standalone - no external dependencies required

🧠 Built for the MQL5 community with professional standards

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-29 17:02:40 -04:00

361 lines
No EOL
15 KiB
MQL5

//+------------------------------------------------------------------+
//| Enhanced Multi-Symbol Trading Story Dashboard |
//| Displays comprehensive portfolio story on single chart |
//+------------------------------------------------------------------+
#include <Utils/JAson.mqh>
#define COLOR_PROFIT C'32,133,66'
#define COLOR_LOSS C'187,44,44'
#define COLOR_NEUTRAL C'128,128,128'
#define COLOR_WARNING C'255,165,0'
#define COLOR_CRYPTO C'255,215,0'
#define COLOR_GOLD C'255,223,0'
#define FONT_SIZE_NORMAL 9
#define FONT_SIZE_LARGE 11
#define FONT_SIZE_SMALL 8
struct SymbolStory {
string symbol;
string narrative;
string signal;
double confidence;
bool hasExecutionPlan;
double riskContribution;
int chaptersCount;
datetime lastUpdate;
};
struct PortfolioStory {
string globalNarrative;
string marketRegime;
double riskAppetite;
string dominantTheme;
SymbolStory symbols[5];
int activeExecutionPlans;
double totalRiskExposure;
datetime lastUpdate;
};
class EnhancedMultiSymbolDashboard {
private:
string m_symbol;
string m_fontName;
int m_window;
string m_serverUrl;
// Enhanced layout for multi-symbol display
struct DashboardLayout {
int x, y;
int width, height;
int margin;
int rowHeight;
int symbolPanelHeight;
int portfolioPanelHeight;
} layout;
PortfolioStory portfolioStory;
public:
EnhancedMultiSymbolDashboard(string symbol, string serverUrl = "http://localhost:8000") {
m_symbol = symbol;
m_serverUrl = serverUrl;
m_fontName = "Consolas";
InitializeLayout();
m_window = 0;
InitializePortfolioStory();
}
void Update() {
FetchPortfolioStory();
DrawEnhancedDashboard();
}
private:
void InitializeLayout() {
layout.x = 15;
layout.y = 15;
layout.width = 420;
layout.height = 650;
layout.margin = 8;
layout.rowHeight = 20;
layout.symbolPanelHeight = 100;
layout.portfolioPanelHeight = 120;
}
void InitializePortfolioStory() {
portfolioStory.globalNarrative = "Initializing multi-symbol trading story engine...";
portfolioStory.marketRegime = "DISCOVERY";
portfolioStory.riskAppetite = 0.5;
portfolioStory.dominantTheme = "INITIALIZATION";
portfolioStory.activeExecutionPlans = 0;
portfolioStory.totalRiskExposure = 0.0;
portfolioStory.lastUpdate = TimeCurrent();
// Initialize symbol stories
string symbols[] = {"EURUSD", "USDJPY", "AUDUSD", "BTCUSD", "XAUUSD"};
for(int i = 0; i < 5; i++) {
portfolioStory.symbols[i].symbol = symbols[i];
portfolioStory.symbols[i].narrative = "Establishing baseline analysis...";
portfolioStory.symbols[i].signal = "HOLD";
portfolioStory.symbols[i].confidence = 0.5;
portfolioStory.symbols[i].hasExecutionPlan = false;
portfolioStory.symbols[i].riskContribution = 0.0;
portfolioStory.symbols[i].chaptersCount = 0;
portfolioStory.symbols[i].lastUpdate = TimeCurrent();
}
}
void FetchPortfolioStory() {
string url = m_serverUrl + "/api/portfolio-story";
string headers = "Content-Type: application/json\r\n";
char result[];
string response = "";
string cookie = NULL, referer = NULL;
uchar data[];
int res = WebRequest("GET", url, cookie, referer, 5000, data, ArraySize(data), result, headers);
if(res == 200) {
response = CharArrayToString(result);
ParsePortfolioStoryResponse(response);
} else {
Print("❌ Failed to fetch portfolio story: HTTP ", res);
}
}
void ParsePortfolioStoryResponse(string response) {
CJAVal json;
if(!json.Deserialize(response)) {
Print("❌ Failed to parse portfolio story JSON");
return;
}
if(!json["success"].ToBool()) {
Print("❌ Portfolio story API returned error");
return;
}
// Update portfolio-level data
portfolioStory.globalNarrative = json["portfolioStory"].ToStr();
portfolioStory.activeExecutionPlans = (int)json["activeExecutionPlans"].ToInt();
portfolioStory.totalRiskExposure = json["totalRiskExposure"].ToDbl();
portfolioStory.lastUpdate = TimeCurrent();
// Update global context
if(json["globalContext"].m_type == jtOBJ) {
portfolioStory.marketRegime = json["globalContext"]["marketRegime"].ToStr();
portfolioStory.riskAppetite = json["globalContext"]["riskAppetite"].ToDbl();
portfolioStory.dominantTheme = json["globalContext"]["dominantTheme"].ToStr();
}
// Update individual symbol stories
if(json["instruments"].m_type == jtARRAY) {
int size = json["instruments"].Size();
for(int i = 0; i < MathMin(size, 5); i++) {
CJAVal instrument = json["instruments"][i];
if(i < 5) {
portfolioStory.symbols[i].symbol = instrument["symbol"].ToStr();
portfolioStory.symbols[i].narrative = instrument["narrative"].ToStr();
portfolioStory.symbols[i].hasExecutionPlan = instrument["hasExecutionPlan"].ToBool();
portfolioStory.symbols[i].chaptersCount = (int)instrument["chaptersCount"].ToInt();
portfolioStory.symbols[i].lastUpdate = TimeCurrent();
}
}
}
Print("✅ Portfolio story updated: ", portfolioStory.activeExecutionPlans, " active plans");
}
void DrawEnhancedDashboard() {
// Clear previous objects
ClearDashboard();
int y = layout.y;
// Draw main background
DrawMainBackground();
// Draw portfolio header
DrawPortfolioHeader(y);
y += layout.portfolioPanelHeight;
// Draw individual symbol panels
for(int i = 0; i < 5; i++) {
DrawSymbolPanel(portfolioStory.symbols[i], y, i);
y += layout.symbolPanelHeight;
}
// Draw portfolio summary footer
DrawPortfolioSummary(y);
}
void DrawMainBackground() {
string name = "dashboard_main_bg_" + m_symbol;
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, layout.x - 5);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, layout.y - 5);
ObjectSetInteger(0, name, OBJPROP_XSIZE, layout.width + 10);
ObjectSetInteger(0, name, OBJPROP_YSIZE, layout.height + 10);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, C'20,20,25');
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, C'65,105,225');
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
}
void DrawPortfolioHeader(int &y) {
// Portfolio title
DrawLabel("portfolio_title", "🚀 Multi-Symbol Trading Stories", layout.x + 10, y + 5, FONT_SIZE_LARGE, clrWhite);
y += layout.rowHeight + 5;
// Global narrative (word-wrapped)
string narrative = portfolioStory.globalNarrative;
if(StringLen(narrative) > 60) {
narrative = StringSubstr(narrative, 0, 57) + "...";
}
DrawLabel("portfolio_narrative", narrative, layout.x + 10, y, FONT_SIZE_NORMAL, C'200,200,200');
y += layout.rowHeight;
// Market regime and stats
string regimeText = "📊 " + portfolioStory.marketRegime + " | 🎯 " + IntegerToString(portfolioStory.activeExecutionPlans) + " Plans";
DrawLabel("portfolio_regime", regimeText, layout.x + 10, y, FONT_SIZE_NORMAL, COLOR_NEUTRAL);
y += layout.rowHeight;
// Risk appetite indicator
color riskColor = portfolioStory.riskAppetite > 0.7 ? COLOR_LOSS :
portfolioStory.riskAppetite > 0.3 ? COLOR_WARNING : COLOR_PROFIT;
string riskText = "🛡️ Risk: " + DoubleToString(portfolioStory.riskAppetite * 100, 1) + "%";
DrawLabel("portfolio_risk", riskText, layout.x + 10, y, FONT_SIZE_NORMAL, riskColor);
y += layout.rowHeight + 5;
}
void DrawSymbolPanel(SymbolStory &story, int y, int index) {
// Symbol panel background
string bgName = "symbol_bg_" + story.symbol;
color bgColor = GetSymbolColor(story.symbol, true);
ObjectCreate(0, bgName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, bgName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, bgName, OBJPROP_XDISTANCE, layout.x);
ObjectSetInteger(0, bgName, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, bgName, OBJPROP_XSIZE, layout.width);
ObjectSetInteger(0, bgName, OBJPROP_YSIZE, layout.symbolPanelHeight - 5);
ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, bgColor);
ObjectSetInteger(0, bgName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, bgName, OBJPROP_BORDER_COLOR, GetSymbolColor(story.symbol, false));
// Symbol name with icon
string symbolIcon = GetSymbolIcon(story.symbol);
string symbolText = symbolIcon + " " + story.symbol;
DrawLabel("symbol_name_" + story.symbol, symbolText, layout.x + 10, y + 5, FONT_SIZE_NORMAL, clrWhite);
// Execution plan indicator
if(story.hasExecutionPlan) {
DrawLabel("plan_indicator_" + story.symbol, "🎯 PLAN", layout.x + layout.width - 50, y + 5, FONT_SIZE_SMALL, COLOR_PROFIT);
} else {
DrawLabel("plan_indicator_" + story.symbol, "⏳ WAIT", layout.x + layout.width - 50, y + 5, FONT_SIZE_SMALL, COLOR_NEUTRAL);
}
// Signal and confidence
color signalColor = story.signal == "BUY" ? COLOR_PROFIT :
story.signal == "SELL" ? COLOR_LOSS : COLOR_NEUTRAL;
string signalText = story.signal + " (" + DoubleToString(story.confidence * 100, 1) + "%)";
DrawLabel("signal_" + story.symbol, signalText, layout.x + 10, y + 25, FONT_SIZE_NORMAL, signalColor);
// Chapters count
string chaptersText = "📚 " + IntegerToString(story.chaptersCount) + " chapters";
DrawLabel("chapters_" + story.symbol, chaptersText, layout.x + layout.width - 100, y + 25, FONT_SIZE_SMALL, COLOR_NEUTRAL);
// Narrative (truncated)
string narrative = story.narrative;
if(StringLen(narrative) > 50) {
narrative = StringSubstr(narrative, 0, 47) + "...";
}
DrawLabel("narrative_" + story.symbol, narrative, layout.x + 10, y + 45, FONT_SIZE_SMALL, C'180,180,180');
// Last update time
string timeText = "🕐 " + TimeToString(story.lastUpdate, TIME_MINUTES);
DrawLabel("time_" + story.symbol, timeText, layout.x + 10, y + 65, FONT_SIZE_SMALL, COLOR_NEUTRAL);
}
void DrawPortfolioSummary(int y) {
// Summary background
string name = "portfolio_summary_bg";
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, layout.x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, layout.width);
ObjectSetInteger(0, name, OBJPROP_YSIZE, 40);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, C'30,30,40');
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, C'65,105,225');
// Summary stats
string summaryText = "📊 " + IntegerToString(portfolioStory.activeExecutionPlans) + "/5 Active | " +
"🎯 Risk: " + DoubleToString(portfolioStory.totalRiskExposure, 1) + "% | " +
"🕐 " + TimeToString(portfolioStory.lastUpdate, TIME_MINUTES);
DrawLabel("portfolio_summary", summaryText, layout.x + 10, y + 10, FONT_SIZE_NORMAL, clrWhite);
// Status indicator
color statusColor = portfolioStory.activeExecutionPlans > 0 ? COLOR_PROFIT : COLOR_NEUTRAL;
DrawStatusDot("portfolio_status", layout.x + layout.width - 25, y + 15, statusColor);
}
void DrawLabel(string name, string text, int x, int y, int fontSize, color clr) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetString(0, name, OBJPROP_FONT, m_fontName);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
void DrawStatusDot(string name, int x, int y, color clr) {
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, 12);
ObjectSetInteger(0, name, OBJPROP_YSIZE, 12);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, clrBlack);
}
color GetSymbolColor(string symbol, bool isBackground) {
if(StringFind(symbol, "BTC") >= 0) {
return isBackground ? C'25,25,35' : COLOR_CRYPTO;
}
if(StringFind(symbol, "XAU") >= 0) {
return isBackground ? C'35,30,25' : COLOR_GOLD;
}
if(StringFind(symbol, "USD") >= 0) {
return isBackground ? C'25,35,25' : COLOR_PROFIT;
}
return isBackground ? C'30,30,30' : COLOR_NEUTRAL;
}
string GetSymbolIcon(string symbol) {
if(StringFind(symbol, "BTC") >= 0) return "";
if(StringFind(symbol, "XAU") >= 0) return "🥇";
if(StringFind(symbol, "EUR") >= 0) return "";
if(StringFind(symbol, "GBP") >= 0) return "£";
if(StringFind(symbol, "JPY") >= 0) return "¥";
if(StringFind(symbol, "AUD") >= 0) return "🇦🇺";
return "💱";
}
void ClearDashboard() {
// Remove all dashboard objects
ObjectsDeleteAll(0, "dashboard_", -1, OBJ_RECTANGLE_LABEL);
ObjectsDeleteAll(0, "portfolio_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "symbol_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "plan_indicator_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "signal_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "chapters_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "narrative_", -1, OBJ_LABEL);
ObjectsDeleteAll(0, "time_", -1, OBJ_LABEL);
}
};