mql5/Experts/Advisors/Modules/Dashboard_SelfContained.mqh
2025-09-01 16:55:52 +01:00

569 lines
No EOL
21 KiB
MQL5

//+------------------------------------------------------------------+
//| Dashboard_SelfContained.mqh |
//| Fully Self-Contained Dashboard with Internal Colors |
//| Complete Implementation with All Functions |
//+------------------------------------------------------------------+
#ifndef DASHBOARD_SELF_CONTAINED_MQH
#define DASHBOARD_SELF_CONTAINED_MQH
#include "DataTypes.mqh"
//+------------------------------------------------------------------+
//| Dashboard Theme Enumeration |
//+------------------------------------------------------------------+
enum ENUM_DASH_THEME
{
DASH_THEME_DARK, // Dark Professional
DASH_THEME_LIGHT, // Light Modern
DASH_THEME_CONTRAST, // High Contrast
DASH_THEME_MATRIX, // Matrix Green
DASH_THEME_OCEAN, // Ocean Blue
DASH_THEME_AUTO // Auto-Adjust to Market
};
//+------------------------------------------------------------------+
//| Self-Contained Dashboard Class |
//+------------------------------------------------------------------+
class CDashboardSelfContained
{
private:
//--- Dashboard Properties
string m_prefix; // Object name prefix
int m_x; // X position
int m_y; // Y position
int m_width; // Dashboard width
int m_height; // Dashboard height
bool m_visible; // Visibility flag
bool m_compact; // Compact mode flag
ENUM_DASH_THEME m_theme; // Current theme
//--- Color Properties
color m_colorBackground; // Background color
color m_colorBorder; // Border color
color m_colorText; // Text color
color m_colorHeader; // Header color
color m_colorSuccess; // Success color (green)
color m_colorDanger; // Danger color (red)
color m_colorWarning; // Warning color (orange)
color m_colorInfo; // Info color (blue)
//--- Object Management
string m_objects[100]; // Array of object names
int m_objCount; // Number of objects
//--- Cache for Performance
double m_lastBalance; // Last balance value
double m_lastEquity; // Last equity value
double m_lastDrawdown; // Last drawdown value
datetime m_lastUpdate; // Last update time
//--- Private Methods
void CreateBackground();
void CreateHeader();
void CreateLabels();
void ApplyTheme(ENUM_DASH_THEME theme);
color GetRiskColor(double riskPercent);
color GetPnLColor(double value);
string FormatMoney(double value);
string FormatPercent(double value);
void UpdateLabel(string suffix, string text, color clr = clrNONE);
bool ObjectExists(string name);
void AddObject(string name);
public:
//--- Constructor/Destructor
CDashboardSelfContained();
~CDashboardSelfContained();
//--- Main Public Methods
bool Create(string name, int x, int y, int width = 320, int height = 200);
void Update(const RiskMetrics &risk, const PerformanceMetrics &perf);
void Destroy();
//--- Additional Public Methods
void RefreshColors();
void Resize(int newWidth = 0, int newHeight = 0);
void ShowHide(bool show);
void SetTheme(ENUM_DASH_THEME theme);
void SetCompact(bool compact);
bool IsVisible() { return m_visible; }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CDashboardSelfContained::CDashboardSelfContained()
{
m_prefix = "DSC_" + IntegerToString(GetTickCount()) + "_";
m_x = 10;
m_y = 30;
m_width = 320;
m_height = 200;
m_visible = true;
m_compact = false;
m_theme = DASH_THEME_DARK;
m_objCount = 0;
// Initialize cache
m_lastBalance = 0;
m_lastEquity = 0;
m_lastDrawdown = 0;
m_lastUpdate = 0;
// Apply default theme
ApplyTheme(DASH_THEME_DARK);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CDashboardSelfContained::~CDashboardSelfContained()
{
Destroy();
}
//+------------------------------------------------------------------+
//| Create Dashboard |
//+------------------------------------------------------------------+
bool CDashboardSelfContained::Create(string name, int x, int y, int width, int height)
{
// Store position and size
m_x = x;
m_y = y;
m_width = width;
m_height = height;
// Update prefix with name
m_prefix = "DSC_" + name + "_";
// Create visual elements
CreateBackground();
CreateHeader();
CreateLabels();
return true;
}
//+------------------------------------------------------------------+
//| Create Background Panel |
//+------------------------------------------------------------------+
void CDashboardSelfContained::CreateBackground()
{
string bgName = m_prefix + "BG";
if(ObjectCreate(0, bgName, OBJ_RECTANGLE_LABEL, 0, 0, 0))
{
ObjectSetInteger(0, bgName, OBJPROP_XDISTANCE, m_x);
ObjectSetInteger(0, bgName, OBJPROP_YDISTANCE, m_y);
ObjectSetInteger(0, bgName, OBJPROP_XSIZE, m_width);
ObjectSetInteger(0, bgName, OBJPROP_YSIZE, m_height);
ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, m_colorBackground);
ObjectSetInteger(0, bgName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, bgName, OBJPROP_COLOR, m_colorBorder);
ObjectSetInteger(0, bgName, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, bgName, OBJPROP_BACK, true);
ObjectSetInteger(0, bgName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, bgName, OBJPROP_HIDDEN, false);
AddObject(bgName);
}
}
//+------------------------------------------------------------------+
//| Create Header |
//+------------------------------------------------------------------+
void CDashboardSelfContained::CreateHeader()
{
string headerName = m_prefix + "HEADER";
if(ObjectCreate(0, headerName, OBJ_LABEL, 0, 0, 0))
{
ObjectSetInteger(0, headerName, OBJPROP_XDISTANCE, m_x + m_width/2);
ObjectSetInteger(0, headerName, OBJPROP_YDISTANCE, m_y + 10);
ObjectSetString(0, headerName, OBJPROP_TEXT, "ERMT Dashboard");
ObjectSetString(0, headerName, OBJPROP_FONT, "Arial Bold");
ObjectSetInteger(0, headerName, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, headerName, OBJPROP_COLOR, m_colorHeader);
ObjectSetInteger(0, headerName, OBJPROP_ANCHOR, ANCHOR_CENTER);
ObjectSetInteger(0, headerName, OBJPROP_SELECTABLE, false);
AddObject(headerName);
}
}
//+------------------------------------------------------------------+
//| Create Labels |
//+------------------------------------------------------------------+
void CDashboardSelfContained::CreateLabels()
{
int yPos = m_y + 35;
int xLabel = m_x + 10;
int xValue = m_x + 150;
int lineHeight = 20;
// Define label pairs
string labels[][2] = {
{"Balance:", "BALANCE"},
{"Equity:", "EQUITY"},
{"Profit/Loss:", "PNL"},
{"Drawdown:", "DRAWDOWN"},
{"Risk Level:", "RISK"},
{"Open Positions:", "POSITIONS"},
{"Win Rate:", "WINRATE"}
};
int numLabels = m_compact ? 4 : ArrayRange(labels, 0);
for(int i = 0; i < numLabels; i++)
{
// Create label text
string labelName = m_prefix + labels[i][1] + "_L";
if(ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0))
{
ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, xLabel);
ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, yPos);
ObjectSetString(0, labelName, OBJPROP_TEXT, labels[i][0]);
ObjectSetString(0, labelName, OBJPROP_FONT, "Consolas");
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, m_colorText);
ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false);
AddObject(labelName);
}
// Create value text
string valueName = m_prefix + labels[i][1] + "_V";
if(ObjectCreate(0, valueName, OBJ_LABEL, 0, 0, 0))
{
ObjectSetInteger(0, valueName, OBJPROP_XDISTANCE, xValue);
ObjectSetInteger(0, valueName, OBJPROP_YDISTANCE, yPos);
ObjectSetString(0, valueName, OBJPROP_TEXT, "---");
ObjectSetString(0, valueName, OBJPROP_FONT, "Consolas");
ObjectSetInteger(0, valueName, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, valueName, OBJPROP_COLOR, m_colorInfo);
ObjectSetInteger(0, valueName, OBJPROP_SELECTABLE, false);
AddObject(valueName);
}
yPos += lineHeight;
}
}
//+------------------------------------------------------------------+
//| Update Dashboard |
//+------------------------------------------------------------------+
void CDashboardSelfContained::Update(const RiskMetrics &risk, const PerformanceMetrics &perf)
{
// Get current account info
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double pnl = equity - balance;
// Update Balance
UpdateLabel("BALANCE_V", FormatMoney(balance), m_colorText);
// Update Equity
UpdateLabel("EQUITY_V", FormatMoney(equity),
equity >= balance ? m_colorSuccess : m_colorDanger);
// Update P&L
UpdateLabel("PNL_V", FormatMoney(pnl), GetPnLColor(pnl));
// Update Drawdown
UpdateLabel("DRAWDOWN_V", FormatPercent(risk.currentDrawdown),
GetRiskColor(risk.currentDrawdown));
// Update Risk Level
UpdateLabel("RISK_V", FormatPercent(risk.totalRisk),
GetRiskColor(risk.totalRisk));
// Update Open Positions
UpdateLabel("POSITIONS_V", IntegerToString(risk.openPositions), m_colorInfo);
// Update Win Rate
if(!m_compact)
{
UpdateLabel("WINRATE_V", FormatPercent(perf.winRate),
perf.winRate >= 50 ? m_colorSuccess : m_colorWarning);
}
// Store last update time
m_lastUpdate = TimeCurrent();
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Refresh Colors |
//+------------------------------------------------------------------+
void CDashboardSelfContained::RefreshColors()
{
// Update background
string bgName = m_prefix + "BG";
if(ObjectExists(bgName))
{
ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, m_colorBackground);
ObjectSetInteger(0, bgName, OBJPROP_COLOR, m_colorBorder);
}
// Update header
string headerName = m_prefix + "HEADER";
if(ObjectExists(headerName))
{
ObjectSetInteger(0, headerName, OBJPROP_COLOR, m_colorHeader);
}
// Update all labels
for(int i = 0; i < m_objCount; i++)
{
if(StringFind(m_objects[i], "_L") > 0)
{
ObjectSetInteger(0, m_objects[i], OBJPROP_COLOR, m_colorText);
}
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Resize Dashboard |
//+------------------------------------------------------------------+
void CDashboardSelfContained::Resize(int newWidth, int newHeight)
{
// Update dimensions if provided
if(newWidth > 0) m_width = newWidth;
if(newHeight > 0) m_height = newHeight;
// Update background size
string bgName = m_prefix + "BG";
if(ObjectExists(bgName))
{
ObjectSetInteger(0, bgName, OBJPROP_XSIZE, m_width);
ObjectSetInteger(0, bgName, OBJPROP_YSIZE, m_height);
}
// Update header position
string headerName = m_prefix + "HEADER";
if(ObjectExists(headerName))
{
ObjectSetInteger(0, headerName, OBJPROP_XDISTANCE, m_x + m_width/2);
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Show or Hide Dashboard |
//+------------------------------------------------------------------+
void CDashboardSelfContained::ShowHide(bool show)
{
m_visible = show;
long visibility = show ? OBJ_ALL_PERIODS : OBJ_NO_PERIODS;
for(int i = 0; i < m_objCount; i++)
{
if(ObjectExists(m_objects[i]))
{
ObjectSetInteger(0, m_objects[i], OBJPROP_TIMEFRAMES, visibility);
}
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Set Theme |
//+------------------------------------------------------------------+
void CDashboardSelfContained::SetTheme(ENUM_DASH_THEME theme)
{
m_theme = theme;
ApplyTheme(theme);
RefreshColors();
}
//+------------------------------------------------------------------+
//| Set Compact Mode |
//+------------------------------------------------------------------+
void CDashboardSelfContained::SetCompact(bool compact)
{
if(m_compact != compact)
{
m_compact = compact;
// Destroy and recreate with new layout
Destroy();
Create(m_prefix, m_x, m_y, m_width, m_compact ? 120 : 200);
}
}
//+------------------------------------------------------------------+
//| Apply Theme Colors |
//+------------------------------------------------------------------+
void CDashboardSelfContained::ApplyTheme(ENUM_DASH_THEME theme)
{
switch(theme)
{
case DASH_THEME_DARK:
m_colorBackground = C'20,20,20';
m_colorBorder = clrDimGray;
m_colorText = clrWhiteSmoke;
m_colorHeader = clrGold;
m_colorSuccess = clrLime;
m_colorDanger = clrRed;
m_colorWarning = clrOrange;
m_colorInfo = clrDodgerBlue;
break;
case DASH_THEME_LIGHT:
m_colorBackground = clrWhite;
m_colorBorder = clrLightGray;
m_colorText = clrBlack;
m_colorHeader = clrNavy;
m_colorSuccess = clrGreen;
m_colorDanger = clrCrimson;
m_colorWarning = clrDarkOrange;
m_colorInfo = clrRoyalBlue;
break;
case DASH_THEME_CONTRAST:
m_colorBackground = clrBlack;
m_colorBorder = clrWhite;
m_colorText = clrWhite;
m_colorHeader = clrYellow;
m_colorSuccess = clrLime;
m_colorDanger = clrRed;
m_colorWarning = clrMagenta;
m_colorInfo = clrCyan;
break;
case DASH_THEME_MATRIX:
m_colorBackground = clrBlack;
m_colorBorder = clrDarkGreen;
m_colorText = clrLightGreen;
m_colorHeader = clrLime;
m_colorSuccess = clrLightGreen;
m_colorDanger = clrDarkRed;
m_colorWarning = clrYellow;
m_colorInfo = clrSpringGreen;
break;
case DASH_THEME_OCEAN:
m_colorBackground = C'10,25,40';
m_colorBorder = clrSteelBlue;
m_colorText = clrLightCyan;
m_colorHeader = clrAqua;
m_colorSuccess = clrAquamarine;
m_colorDanger = clrCoral;
m_colorWarning = clrGold;
m_colorInfo = clrDeepSkyBlue;
break;
default:
ApplyTheme(DASH_THEME_DARK);
break;
}
}
//+------------------------------------------------------------------+
//| Get Risk Color Based on Percentage |
//+------------------------------------------------------------------+
color CDashboardSelfContained::GetRiskColor(double riskPercent)
{
if(riskPercent <= 1.0) return m_colorSuccess;
else if(riskPercent <= 2.0) return m_colorWarning;
else return m_colorDanger;
}
//+------------------------------------------------------------------+
//| Get P&L Color |
//+------------------------------------------------------------------+
color CDashboardSelfContained::GetPnLColor(double value)
{
if(value > 0) return m_colorSuccess;
else if(value < 0) return m_colorDanger;
else return m_colorText;
}
//+------------------------------------------------------------------+
//| Format Money Value |
//+------------------------------------------------------------------+
string CDashboardSelfContained::FormatMoney(double value)
{
string sign = value < 0 ? "-$" : "$";
value = MathAbs(value);
if(value >= 1000000)
return sign + DoubleToString(value/1000000, 2) + "M";
else if(value >= 10000)
return sign + DoubleToString(value/1000, 1) + "K";
else
return sign + DoubleToString(value, 2);
}
//+------------------------------------------------------------------+
//| Format Percentage |
//+------------------------------------------------------------------+
string CDashboardSelfContained::FormatPercent(double value)
{
return DoubleToString(value, 2) + "%";
}
//+------------------------------------------------------------------+
//| Update Label |
//+------------------------------------------------------------------+
void CDashboardSelfContained::UpdateLabel(string suffix, string text, color clr)
{
string objName = m_prefix + suffix;
if(ObjectExists(objName))
{
// Only update if changed
if(ObjectGetString(0, objName, OBJPROP_TEXT) != text)
ObjectSetString(0, objName, OBJPROP_TEXT, text);
// Update color if specified
if(clr != clrNONE)
{
if((color)ObjectGetInteger(0, objName, OBJPROP_COLOR) != clr)
ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
}
}
}
//+------------------------------------------------------------------+
//| Check if Object Exists |
//+------------------------------------------------------------------+
bool CDashboardSelfContained::ObjectExists(string name)
{
return ObjectFind(0, name) >= 0;
}
//+------------------------------------------------------------------+
//| Add Object to Management Array |
//+------------------------------------------------------------------+
void CDashboardSelfContained::AddObject(string name)
{
if(m_objCount < ArraySize(m_objects))
{
m_objects[m_objCount++] = name;
}
}
//+------------------------------------------------------------------+
//| Destroy Dashboard |
//+------------------------------------------------------------------+
void CDashboardSelfContained::Destroy()
{
// Delete all objects
for(int i = 0; i < m_objCount; i++)
{
if(ObjectExists(m_objects[i]))
{
ObjectDelete(0, m_objects[i]);
}
}
// Reset counter
m_objCount = 0;
ChartRedraw();
}
#endif // DASHBOARD_SELF_CONTAINED_MQH