//+------------------------------------------------------------------+ //| Dashboard.mqh | //| Visual Dashboard Display | //+------------------------------------------------------------------+ #ifndef DASHBOARD_MQH #define DASHBOARD_MQH #include #include "DataTypes.mqh" //+------------------------------------------------------------------+ //| Dashboard Data Structure | //+------------------------------------------------------------------+ struct DashboardData { // Account info double balance; double equity; double free_margin; double margin_level; // Performance double profit; double daily_profit; int positions; double win_rate; double profit_factor; double drawdown; double sharpe_ratio; // Risk double risk_status; double exposure; // External trades int external_trades; double external_profit; // Market string market_condition; double spread; double volatility; // Additional stats int daily_trades; int winning_trades; int losing_trades; }; //+------------------------------------------------------------------+ //| Dashboard Class | //+------------------------------------------------------------------+ class CDashboard : public CObject { private: // Display settings int m_x_offset; int m_y_offset; int m_font_size; string m_font_name; color m_text_color; color m_positive_color; color m_negative_color; color m_header_color; color m_background_color; // Object prefixes string m_prefix; int m_line_height; int m_column_width; // Display flags bool m_is_visible; bool m_minimized; // Data cache DashboardData m_last_data; datetime m_last_update; // Helper methods void CreateLabel(string name, int x, int y, string text, color clr = clrNONE, int size = 0); void UpdateLabel(string name, string text, color clr = clrNONE); void DeleteLabel(string name); void CreateBackground(); void DrawSeparator(int y); string FormatCurrency(double value); string FormatPercent(double value); color GetColorByValue(double value, double threshold = 0); public: // Constructor/Destructor CDashboard(); ~CDashboard(); // Initialization bool Initialize(int x = 20, int y = 50); void Deinitialize(); // Display control void Show(); void Hide(); void Toggle() { if(m_is_visible) Hide(); else Show(); } void Minimize(); void Maximize(); // Settings void SetPosition(int x, int y) { m_x_offset = x; m_y_offset = y; } void SetFontSize(int size) { m_font_size = size; } void SetColors(color text, color negative, color positive); // Update void Update(const DashboardData &data); void UpdateAccountSection(); void UpdatePerformanceSection(); void UpdateRiskSection(); void UpdatePositionsSection(); void UpdateMarketSection(); // Getters bool IsVisible() const { return m_is_visible; } bool IsMinimized() const { return m_minimized; } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDashboard::CDashboard() { m_x_offset = 20; m_y_offset = 50; m_font_size = 9; m_font_name = "Arial"; m_text_color = clrWhite; m_positive_color = clrLime; m_negative_color = clrRed; m_header_color = clrGold; m_background_color = clrBlack; m_prefix = "DASH_"; m_line_height = 18; m_column_width = 200; m_is_visible = false; m_minimized = false; m_last_update = 0; ZeroMemory(m_last_data); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDashboard::~CDashboard() { Deinitialize(); } //+------------------------------------------------------------------+ //| Initialize | //+------------------------------------------------------------------+ bool CDashboard::Initialize(int x = 20, int y = 50) { m_x_offset = x; m_y_offset = y; // Create initial display Show(); return true; } //+------------------------------------------------------------------+ //| Deinitialize | //+------------------------------------------------------------------+ void CDashboard::Deinitialize() { // Delete all dashboard objects ObjectsDeleteAll(0, m_prefix); m_is_visible = false; } //+------------------------------------------------------------------+ //| Show Dashboard | //+------------------------------------------------------------------+ void CDashboard::Show() { if(m_is_visible) return; CreateBackground(); int y = m_y_offset; // Header CreateLabel(m_prefix + "HEADER", m_x_offset + 5, y, "ERMT DASHBOARD v6.8", m_header_color, m_font_size + 2); y += m_line_height + 5; DrawSeparator(y); y += 10; // Account Section CreateLabel(m_prefix + "ACC_TITLE", m_x_offset + 5, y, "ACCOUNT", m_header_color); y += m_line_height; CreateLabel(m_prefix + "ACC_BALANCE", m_x_offset + 5, y, "Balance:", m_text_color); CreateLabel(m_prefix + "ACC_BALANCE_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; CreateLabel(m_prefix + "ACC_EQUITY", m_x_offset + 5, y, "Equity:", m_text_color); CreateLabel(m_prefix + "ACC_EQUITY_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; CreateLabel(m_prefix + "ACC_MARGIN", m_x_offset + 5, y, "Free Margin:", m_text_color); CreateLabel(m_prefix + "ACC_MARGIN_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; DrawSeparator(y); y += 10; // Performance Section CreateLabel(m_prefix + "PERF_TITLE", m_x_offset + 5, y, "PERFORMANCE", m_header_color); y += m_line_height; CreateLabel(m_prefix + "PERF_PROFIT", m_x_offset + 5, y, "Total P/L:", m_text_color); CreateLabel(m_prefix + "PERF_PROFIT_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; CreateLabel(m_prefix + "PERF_DAILY", m_x_offset + 5, y, "Daily P/L:", m_text_color); CreateLabel(m_prefix + "PERF_DAILY_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; CreateLabel(m_prefix + "PERF_WINRATE", m_x_offset + 5, y, "Win Rate:", m_text_color); CreateLabel(m_prefix + "PERF_WINRATE_VAL", m_x_offset + 100, y, "0.0%", m_text_color); y += m_line_height; CreateLabel(m_prefix + "PERF_PF", m_x_offset + 5, y, "Profit Factor:", m_text_color); CreateLabel(m_prefix + "PERF_PF_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; DrawSeparator(y); y += 10; // Risk Section CreateLabel(m_prefix + "RISK_TITLE", m_x_offset + 5, y, "RISK STATUS", m_header_color); y += m_line_height; CreateLabel(m_prefix + "RISK_DD", m_x_offset + 5, y, "Drawdown:", m_text_color); CreateLabel(m_prefix + "RISK_DD_VAL", m_x_offset + 100, y, "0.0%", m_text_color); y += m_line_height; CreateLabel(m_prefix + "RISK_LEVEL", m_x_offset + 5, y, "Risk Level:", m_text_color); CreateLabel(m_prefix + "RISK_LEVEL_VAL", m_x_offset + 100, y, "0.0%", m_text_color); y += m_line_height; CreateLabel(m_prefix + "RISK_EXPOSURE", m_x_offset + 5, y, "Exposure:", m_text_color); CreateLabel(m_prefix + "RISK_EXPOSURE_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; DrawSeparator(y); y += 10; // Positions Section CreateLabel(m_prefix + "POS_TITLE", m_x_offset + 5, y, "POSITIONS", m_header_color); y += m_line_height; CreateLabel(m_prefix + "POS_OPEN", m_x_offset + 5, y, "Open Trades:", m_text_color); CreateLabel(m_prefix + "POS_OPEN_VAL", m_x_offset + 100, y, "0", m_text_color); y += m_line_height; CreateLabel(m_prefix + "POS_EXTERNAL", m_x_offset + 5, y, "External:", m_text_color); CreateLabel(m_prefix + "POS_EXTERNAL_VAL", m_x_offset + 100, y, "0", m_text_color); y += m_line_height; CreateLabel(m_prefix + "POS_EXTPL", m_x_offset + 5, y, "External P/L:", m_text_color); CreateLabel(m_prefix + "POS_EXTPL_VAL", m_x_offset + 100, y, "0.00", m_text_color); y += m_line_height; DrawSeparator(y); y += 10; // Market Section CreateLabel(m_prefix + "MKT_TITLE", m_x_offset + 5, y, "MARKET", m_header_color); y += m_line_height; CreateLabel(m_prefix + "MKT_COND", m_x_offset + 5, y, "Condition:", m_text_color); CreateLabel(m_prefix + "MKT_COND_VAL", m_x_offset + 100, y, "Unknown", m_text_color); y += m_line_height; CreateLabel(m_prefix + "MKT_SPREAD", m_x_offset + 5, y, "Spread:", m_text_color); CreateLabel(m_prefix + "MKT_SPREAD_VAL", m_x_offset + 100, y, "0.0", m_text_color); y += m_line_height; m_is_visible = true; } //+------------------------------------------------------------------+ //| Hide Dashboard | //+------------------------------------------------------------------+ void CDashboard::Hide() { ObjectsDeleteAll(0, m_prefix); m_is_visible = false; } //+------------------------------------------------------------------+ //| Update Dashboard | //+------------------------------------------------------------------+ void CDashboard::Update(const DashboardData &data) { if(!m_is_visible) return; m_last_data = data; m_last_update = TimeCurrent(); // Update Account Section UpdateLabel(m_prefix + "ACC_BALANCE_VAL", FormatCurrency(data.balance)); UpdateLabel(m_prefix + "ACC_EQUITY_VAL", FormatCurrency(data.equity), GetColorByValue(data.equity - data.balance)); UpdateLabel(m_prefix + "ACC_MARGIN_VAL", FormatCurrency(data.free_margin)); // Update Performance Section UpdateLabel(m_prefix + "PERF_PROFIT_VAL", FormatCurrency(data.profit), GetColorByValue(data.profit)); UpdateLabel(m_prefix + "PERF_DAILY_VAL", FormatCurrency(data.daily_profit), GetColorByValue(data.daily_profit)); UpdateLabel(m_prefix + "PERF_WINRATE_VAL", FormatPercent(data.win_rate)); UpdateLabel(m_prefix + "PERF_PF_VAL", DoubleToString(data.profit_factor, 2), GetColorByValue(data.profit_factor - 1.0)); // Update Risk Section UpdateLabel(m_prefix + "RISK_DD_VAL", FormatPercent(data.drawdown), data.drawdown > 10 ? m_negative_color : m_text_color); UpdateLabel(m_prefix + "RISK_LEVEL_VAL", FormatPercent(data.risk_status), data.risk_status > 5 ? m_negative_color : m_positive_color); UpdateLabel(m_prefix + "RISK_EXPOSURE_VAL", DoubleToString(data.exposure, 2)); // Update Positions Section UpdateLabel(m_prefix + "POS_OPEN_VAL", IntegerToString(data.positions)); UpdateLabel(m_prefix + "POS_EXTERNAL_VAL", IntegerToString(data.external_trades)); UpdateLabel(m_prefix + "POS_EXTPL_VAL", FormatCurrency(data.external_profit), GetColorByValue(data.external_profit)); // Update Market Section UpdateLabel(m_prefix + "MKT_COND_VAL", data.market_condition); UpdateLabel(m_prefix + "MKT_SPREAD_VAL", DoubleToString(data.spread, 1)); ChartRedraw(); } //+------------------------------------------------------------------+ //| Create Label | //+------------------------------------------------------------------+ void CDashboard::CreateLabel(string name, int x, int y, string text, color clr = clrNONE, int size = 0) { if(clr == clrNONE) clr = m_text_color; if(size == 0) size = m_font_size; ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetString(0, name, OBJPROP_FONT, m_font_name); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Update Label | //+------------------------------------------------------------------+ void CDashboard::UpdateLabel(string name, string text, color clr = clrNONE) { if(ObjectFind(0, name) >= 0) { ObjectSetString(0, name, OBJPROP_TEXT, text); if(clr != clrNONE) ObjectSetInteger(0, name, OBJPROP_COLOR, clr); } } //+------------------------------------------------------------------+ //| Delete Label | //+------------------------------------------------------------------+ void CDashboard::DeleteLabel(string name) { ObjectDelete(0, name); } //+------------------------------------------------------------------+ //| Create Background | //+------------------------------------------------------------------+ void CDashboard::CreateBackground() { string name = m_prefix + "BACKGROUND"; ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, m_x_offset - 5); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, m_y_offset - 5); ObjectSetInteger(0, name, OBJPROP_XSIZE, m_column_width); ObjectSetInteger(0, name, OBJPROP_YSIZE, 450); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_COLOR, m_background_color); ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Draw Separator | //+------------------------------------------------------------------+ void CDashboard::DrawSeparator(int y) { static int separator_count = 0; string name = m_prefix + "SEP_" + IntegerToString(separator_count++); ObjectCreate(0, name, OBJ_TREND, 0, TimeCurrent(), 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, m_x_offset); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, name, OBJPROP_WIDTH, m_column_width - 10); ObjectSetInteger(0, name, OBJPROP_COLOR, m_text_color); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Format Currency | //+------------------------------------------------------------------+ string CDashboard::FormatCurrency(double value) { string sign = value >= 0 ? "" : "-"; value = MathAbs(value); return sign + "$" + DoubleToString(value, 2); } //+------------------------------------------------------------------+ //| Format Percent | //+------------------------------------------------------------------+ string CDashboard::FormatPercent(double value) { return DoubleToString(value, 2) + "%"; } //+------------------------------------------------------------------+ //| Get Color by Value | //+------------------------------------------------------------------+ color CDashboard::GetColorByValue(double value, double threshold = 0) { if(value > threshold) return m_positive_color; else if(value < threshold) return m_negative_color; else return m_text_color; } //+------------------------------------------------------------------+ //| Set Colors | //+------------------------------------------------------------------+ void CDashboard::SetColors(color text, color negative, color positive) { m_text_color = text; m_negative_color = negative; m_positive_color = positive; } //+------------------------------------------------------------------+ //| Minimize Dashboard | //+------------------------------------------------------------------+ void CDashboard::Minimize() { if(!m_is_visible || m_minimized) return; // Hide all except header ObjectsDeleteAll(0, m_prefix); CreateBackground(); CreateLabel(m_prefix + "HEADER", m_x_offset + 5, m_y_offset, "ERMT DASHBOARD v6.8 [+]", m_header_color, m_font_size + 2); // Resize background string bg_name = m_prefix + "BACKGROUND"; ObjectSetInteger(0, bg_name, OBJPROP_YSIZE, 30); m_minimized = true; } //+------------------------------------------------------------------+ //| Maximize Dashboard | //+------------------------------------------------------------------+ void CDashboard::Maximize() { if(!m_is_visible || !m_minimized) return; m_minimized = false; Hide(); Show(); Update(m_last_data); } #endif // DASHBOARD_MQH