//+------------------------------------------------------------------+ //| Dashboard_Enhanced.mqh v1.0 | //| Optimized Visual Dashboard Module | //| Enhanced with better performance and features | //+------------------------------------------------------------------+ #ifndef DASHBOARD_ENHANCED_MQH #define DASHBOARD_ENHANCED_MQH #include "DataTypes.mqh" #include "SymbolManager.mqh" #include "PerformanceTracker.mqh" //+------------------------------------------------------------------+ //| Dashboard configuration | //+------------------------------------------------------------------+ struct DashboardConfig { int x_pos; int y_pos; int width; color text_color; color profit_color; color loss_color; color header_color; color bg_color; color border_color; int font_size; string font_name; bool show_account; bool show_performance; bool show_trades; bool show_risk; bool show_market; bool show_correlation; int max_trades_display; int update_frequency_ms; }; //+------------------------------------------------------------------+ //| Enhanced Dashboard Class | //+------------------------------------------------------------------+ class CDashboardEnhanced { private: //--- Configuration DashboardConfig m_config; //--- Display settings string m_prefix; int m_line_height; int m_section_gap; int m_current_y; //--- Component tracking string m_components[]; int m_component_count; datetime m_last_update; //--- Cache for expensive operations string m_cached_values[]; datetime m_cache_time; //--- References CSymbolManager *m_symbol_manager; CPerformanceTracker *m_performance_tracker; //--- Helper methods void CreateBackground(); void CreateLabel(string name, int x, int y, string text, color clr, int size = 0, string font = "", ENUM_ANCHOR_POINT anchor = ANCHOR_LEFT_UPPER); void UpdateLabel(string name, string text, color clr = clrNONE); void CreateButton(string name, int x, int y, int width, int height, string text, color bg_color, color text_color); void CreateSection(string title, int &y_offset); void CreateProgressBar(string name, int x, int y, int width, int height, double value, double max_value); //--- Formatting string FormatCurrency(double value); string FormatPercent(double value, int digits = 2); string FormatNumber(double value, int digits = 0); string FormatPips(double value, string symbol); color GetColorForValue(double value, bool inverse = false); color BlendColors(color c1, color c2, double ratio); //--- Update methods void UpdateAccountSection(); void UpdatePerformanceSection(); void UpdateTradesSection(const ManagedTrade &trades[]); void UpdateRiskSection(const ManagedTrade &trades[]); void UpdateMarketSection(const MarketConditions &market); void UpdateCorrelationSection(const ManagedTrade &trades[]); //--- Advanced displays void DrawMiniChart(string name, int x, int y, int width, int height); void DrawRiskMeter(string name, int x, int y, double risk_percent); void DrawPerformanceGraph(string name, int x, int y, int width, int height); public: CDashboardEnhanced(); ~CDashboardEnhanced(); //--- Main methods bool Create(int x_pos, int y_pos, color text_color, color profit_color, color loss_color); void Destroy(); void Update(const PerformanceMetrics &performance, const ManagedTrade &trades[], const MarketConditions &market); //--- Configuration void Configure(const DashboardConfig &config); void SetReferences(CSymbolManager *symbols, CPerformanceTracker *performance); //--- Display control void Show(); void Hide(); void Move(int x, int y); void Minimize(); void Restore(); //--- Interactive elements void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDashboardEnhanced::CDashboardEnhanced() { //--- Default configuration m_config.x_pos = 20; m_config.y_pos = 30; m_config.width = 380; m_config.text_color = clrWhiteSmoke; m_config.profit_color = clrLime; m_config.loss_color = clrRed; m_config.header_color = clrGold; m_config.bg_color = C'20,20,20'; m_config.border_color = clrDimGray; m_config.font_size = 9; m_config.font_name = "Arial"; m_config.show_account = true; m_config.show_performance = true; m_config.show_trades = true; m_config.show_risk = true; m_config.show_market = true; m_config.show_correlation = false; m_config.max_trades_display = 5; m_config.update_frequency_ms = 1000; //--- Internal settings m_prefix = "DASH_ENH_"; m_line_height = 16; m_section_gap = 20; m_current_y = 0; m_component_count = 0; m_last_update = 0; m_cache_time = 0; //--- References m_symbol_manager = NULL; m_performance_tracker = NULL; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDashboardEnhanced::~CDashboardEnhanced() { Destroy(); } //+------------------------------------------------------------------+ //| Create dashboard | //+------------------------------------------------------------------+ bool CDashboardEnhanced::Create(int x_pos, int y_pos, color text_color, color profit_color, color loss_color) { m_config.x_pos = x_pos; m_config.y_pos = y_pos; m_config.text_color = text_color; m_config.profit_color = profit_color; m_config.loss_color = loss_color; //--- Get references if not set if(m_symbol_manager == NULL) m_symbol_manager = CSymbolManager::GetInstance(); //--- Create background CreateBackground(); //--- Initialize component tracking ArrayResize(m_components, 200); m_component_count = 0; //--- Create header m_current_y = m_config.y_pos + 10; CreateLabel(m_prefix + "HEADER", m_config.x_pos + m_config.width/2, m_current_y, "RISK MANAGEMENT SYSTEM", m_config.header_color, 12, "Arial Bold", ANCHOR_CENTER); m_current_y += 25; //--- Create minimize button CreateButton(m_prefix + "BTN_MIN", m_config.x_pos + m_config.width - 25, m_config.y_pos + 5, 20, 20, "_", m_config.bg_color, m_config.text_color); //--- Create sections int section_y = m_current_y; if(m_config.show_account) { CreateSection("ACCOUNT", section_y); for(int i = 0; i < 4; i++) { CreateLabel(m_prefix + "ACC_" + IntegerToString(i), m_config.x_pos + 10, section_y + i * m_line_height, "", m_config.text_color); } section_y += 4 * m_line_height + m_section_gap; } if(m_config.show_performance) { CreateSection("PERFORMANCE", section_y); //--- Performance meters CreateLabel(m_prefix + "PERF_METERS", m_config.x_pos + 10, section_y, "", m_config.text_color); //--- Mini performance graph section_y += m_line_height; DrawPerformanceGraph(m_prefix + "PERF_GRAPH", m_config.x_pos + 10, section_y, m_config.width - 20, 60); section_y += 60 + m_line_height; //--- Performance stats for(int i = 0; i < 4; i++) { CreateLabel(m_prefix + "PERF_" + IntegerToString(i), m_config.x_pos + 10, section_y + i * m_line_height, "", m_config.text_color); } section_y += 4 * m_line_height + m_section_gap; } if(m_config.show_trades) { CreateSection("ACTIVE TRADES", section_y); for(int i = 0; i < m_config.max_trades_display; i++) { CreateLabel(m_prefix + "TRADE_" + IntegerToString(i), m_config.x_pos + 10, section_y + i * m_line_height, "", m_config.text_color, 8); } section_y += m_config.max_trades_display * m_line_height + m_section_gap; } if(m_config.show_risk) { CreateSection("RISK ANALYSIS", section_y); //--- Risk meter DrawRiskMeter(m_prefix + "RISK_METER", m_config.x_pos + 10, section_y, 0); section_y += 30; //--- Risk stats for(int i = 0; i < 3; i++) { CreateLabel(m_prefix + "RISK_" + IntegerToString(i), m_config.x_pos + 10, section_y + i * m_line_height, "", m_config.text_color); } section_y += 3 * m_line_height + m_section_gap; } if(m_config.show_market) { CreateSection("MARKET CONDITIONS", section_y); for(int i = 0; i < 3; i++) { CreateLabel(m_prefix + "MKT_" + IntegerToString(i), m_config.x_pos + 10, section_y + i * m_line_height, "", m_config.text_color); } section_y += 3 * m_line_height; } //--- Update background height ObjectSetInteger(0, m_prefix + "BG", OBJPROP_YSIZE, section_y - m_config.y_pos + 10); Print("Enhanced Dashboard created successfully"); return true; } //+------------------------------------------------------------------+ //| Update dashboard | //+------------------------------------------------------------------+ void CDashboardEnhanced::Update(const PerformanceMetrics &performance, const ManagedTrade &trades[], const MarketConditions &market) { //--- Check update frequency if(GetTickCount() - m_last_update < m_config.update_frequency_ms) return; m_last_update = GetTickCount(); //--- Update sections if(m_config.show_account) UpdateAccountSection(); if(m_config.show_performance) UpdatePerformanceSection(); if(m_config.show_trades) UpdateTradesSection(trades); if(m_config.show_risk) UpdateRiskSection(trades); if(m_config.show_market) UpdateMarketSection(market); if(m_config.show_correlation) UpdateCorrelationSection(trades); } //+------------------------------------------------------------------+ //| Update account section | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdateAccountSection() { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double equity = AccountInfoDouble(ACCOUNT_EQUITY); double margin = AccountInfoDouble(ACCOUNT_MARGIN); double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE); double margin_level = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); //--- Format and update UpdateLabel(m_prefix + "ACC_0", "Balance: " + FormatCurrency(balance), m_config.text_color); UpdateLabel(m_prefix + "ACC_1", "Equity: " + FormatCurrency(equity), GetColorForValue(equity - balance)); UpdateLabel(m_prefix + "ACC_2", StringFormat("Margin: %s / Free: %s", FormatCurrency(margin), FormatCurrency(free_margin)), m_config.text_color); //--- Margin level with color coding color margin_color = m_config.text_color; if(margin_level > 0) { if(margin_level < 100) margin_color = m_config.loss_color; else if(margin_level < 200) margin_color = clrOrange; else if(margin_level < 500) margin_color = clrYellow; else margin_color = m_config.profit_color; } UpdateLabel(m_prefix + "ACC_3", StringFormat("Margin Level: %s%%", margin_level > 0 ? FormatNumber(margin_level, 0) : "∞"), margin_color); } //+------------------------------------------------------------------+ //| Update performance section | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdatePerformanceSection() { if(m_performance_tracker == NULL) return; PerformanceMetrics metrics = m_performance_tracker.GetMetrics(); //--- Performance meters (visual indicators) string meters = ""; //--- Win rate meter int win_blocks = (int)(metrics.win_rate / 10); meters += "Win: "; for(int i = 0; i < 10; i++) { if(i < win_blocks) meters += "█"; else meters += "░"; } meters += StringFormat(" %.1f%% ", metrics.win_rate); //--- Profit factor meter int pf_blocks = (int)MathMin(metrics.profit_factor * 5, 10); meters += "PF: "; for(int i = 0; i < 10; i++) { if(i < pf_blocks) meters += "█"; else meters += "░"; } meters += StringFormat(" %.2f", metrics.profit_factor); UpdateLabel(m_prefix + "PERF_METERS", meters, m_config.text_color); //--- Performance stats UpdateLabel(m_prefix + "PERF_0", StringFormat("Net P/L: %s (%.2f%%)", FormatCurrency(metrics.net_profit), metrics.net_profit / AccountInfoDouble(ACCOUNT_BALANCE) * 100), GetColorForValue(metrics.net_profit)); UpdateLabel(m_prefix + "PERF_1", StringFormat("Trades: %d | W: %d (%.1f%%) | L: %d", metrics.total_trades, metrics.winning_trades, metrics.win_rate, metrics.losing_trades), m_config.text_color); UpdateLabel(m_prefix + "PERF_2", StringFormat("Sharpe: %.2f | Sortino: %.2f | Calmar: %.2f", metrics.sharpe_ratio, metrics.sortino_ratio, metrics.calmar_ratio), m_config.text_color); UpdateLabel(m_prefix + "PERF_3", StringFormat("Max DD: %.2f%% | Current: %.2f%% | Recovery: %.2f", metrics.max_drawdown_percent, metrics.current_drawdown, metrics.recovery_factor), GetColorForValue(-metrics.current_drawdown)); } //+------------------------------------------------------------------+ //| Update trades section | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdateTradesSection(const ManagedTrade &trades[]) { int trade_count = ArraySize(trades); int display_count = MathMin(trade_count, m_config.max_trades_display); //--- Sort trades by profit (best/worst on top) ManagedTrade sorted_trades[]; ArrayResize(sorted_trades, trade_count); ArrayCopy(sorted_trades, trades); //--- Simple sort by profit for(int i = 0; i < trade_count - 1; i++) { for(int j = i + 1; j < trade_count; j++) { if(MathAbs(sorted_trades[j].profit) > MathAbs(sorted_trades[i].profit)) { ManagedTrade temp = sorted_trades[i]; sorted_trades[i] = sorted_trades[j]; sorted_trades[j] = temp; } } } //--- Display trades for(int i = 0; i < m_config.max_trades_display; i++) { if(i < display_count) { ManagedTrade trade = sorted_trades[i]; //--- Format trade info string symbol_short = StringSubstr(trade.symbol, 0, 6); string type_str = (trade.type == POSITION_TYPE_BUY) ? "↑" : "↓"; string trade_info = StringFormat("%s %s %.2f | %s (%.1fR) | %s", symbol_short, type_str, trade.volume, FormatCurrency(trade.profit), trade.r_multiple, trade.is_external ? "EXT" : "INT"); //--- Color based on profit color trade_color = GetColorForValue(trade.profit); //--- Add warning if high risk if(trade.risk_percent > 2.0) { trade_info += " ⚠"; trade_color = clrOrange; } UpdateLabel(m_prefix + "TRADE_" + IntegerToString(i), trade_info, trade_color); } else { UpdateLabel(m_prefix + "TRADE_" + IntegerToString(i), "", m_config.text_color); } } //--- Show total if more trades exist if(trade_count > m_config.max_trades_display) { UpdateLabel(m_prefix + "TRADE_" + IntegerToString(m_config.max_trades_display - 1), StringFormat("... and %d more trades", trade_count - m_config.max_trades_display + 1), clrGray); } } //+------------------------------------------------------------------+ //| Update risk section | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdateRiskSection(const ManagedTrade &trades[]) { //--- Calculate total risk metrics double total_risk = 0; double max_single_risk = 0; int high_risk_count = 0; int external_count = 0; double correlation_risk = 0; int trade_count = ArraySize(trades); for(int i = 0; i < trade_count; i++) { total_risk += trades[i].risk_percent; if(trades[i].risk_percent > max_single_risk) max_single_risk = trades[i].risk_percent; if(trades[i].risk_percent > 2.0) high_risk_count++; if(trades[i].is_external) external_count++; } //--- Update risk meter DrawRiskMeter(m_prefix + "RISK_METER", m_config.x_pos + 10, ObjectGetInteger(0, m_prefix + "RISK_METER", OBJPROP_YDISTANCE), total_risk); //--- Update risk stats UpdateLabel(m_prefix + "RISK_0", StringFormat("Total Risk: %.2f%% | Max Single: %.2f%%", total_risk, max_single_risk), GetColorForValue(10 - total_risk, true)); UpdateLabel(m_prefix + "RISK_1", StringFormat("Positions: %d | External: %d | High Risk: %d", trade_count, external_count, high_risk_count), high_risk_count > 0 ? clrOrange : m_config.text_color); //--- Daily risk usage double daily_limit = 5.0; // From config double daily_used = 0; // Calculate from daily trades UpdateLabel(m_prefix + "RISK_2", StringFormat("Daily Risk: %.2f%% / %.2f%% (%.0f%% used)", daily_used, daily_limit, daily_used / daily_limit * 100), m_config.text_color); } //+------------------------------------------------------------------+ //| Update market section | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdateMarketSection(const MarketConditions &market) { //--- Market condition string condition_text = MarketConditionToString(market.condition); color condition_color = m_config.text_color; switch(market.condition) { case MARKET_TRENDING_UP: condition_color = m_config.profit_color; condition_text += " ↑↑"; break; case MARKET_TRENDING_DOWN: condition_color = m_config.loss_color; condition_text += " ↓↓"; break; case MARKET_VOLATILE: condition_color = clrOrange; condition_text += " ⚡"; break; case MARKET_QUIET: condition_color = clrGray; condition_text += " 💤"; break; case MARKET_RANGING: condition_color = clrYellow; condition_text += " ↔"; break; } UpdateLabel(m_prefix + "MKT_0", StringFormat("Market: %s | ADX: %.1f", condition_text, market.trend_strength), condition_color); //--- Volatility and spread string vol_status = ""; if(market.volatility_percentile > 80) vol_status = " (High!)"; else if(market.volatility_percentile < 20) vol_status = " (Low)"; UpdateLabel(m_prefix + "MKT_1", StringFormat("ATR: %s%s | Spread: %.1f pts", FormatNumber(market.volatility / _Point, 1), vol_status, market.spread / _Point), market.news_event ? clrRed : m_config.text_color); //--- Key levels int support_count = 0, resistance_count = 0; for(int i = 0; i < market.sr_count; i++) { if(market.sr_levels[i].type == "support") support_count++; else if(market.sr_levels[i].type == "resistance") resistance_count++; } UpdateLabel(m_prefix + "MKT_2", StringFormat("S/R Levels: %d↓ / %d↑ | RSI: %.1f", support_count, resistance_count, market.momentum), m_config.text_color); } //+------------------------------------------------------------------+ //| Create background | //+------------------------------------------------------------------+ void CDashboardEnhanced::CreateBackground() { string name = m_prefix + "BG"; ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, m_config.x_pos); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, m_config.y_pos); ObjectSetInteger(0, name, OBJPROP_XSIZE, m_config.width); ObjectSetInteger(0, name, OBJPROP_YSIZE, 600); // Initial height ObjectSetInteger(0, name, OBJPROP_BGCOLOR, m_config.bg_color); ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_RAISED); ObjectSetInteger(0, name, OBJPROP_COLOR, m_config.border_color); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_SELECTED, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); ObjectSetInteger(0, name, OBJPROP_ZORDER, 0); m_components[m_component_count++] = name; } //+------------------------------------------------------------------+ //| Create text label | //+------------------------------------------------------------------+ void CDashboardEnhanced::CreateLabel(string name, int x, int y, string text, color clr, int size, string font, ENUM_ANCHOR_POINT anchor) { if(size == 0) size = m_config.font_size; if(font == "") font = m_config.font_name; ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetString(0, name, OBJPROP_FONT, font); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); ObjectSetInteger(0, name, OBJPROP_ZORDER, 1); m_components[m_component_count++] = name; } //+------------------------------------------------------------------+ //| Update label text and color | //+------------------------------------------------------------------+ void CDashboardEnhanced::UpdateLabel(string name, string text, color clr) { if(ObjectFind(0, name) < 0) return; ObjectSetString(0, name, OBJPROP_TEXT, text); if(clr != clrNONE) ObjectSetInteger(0, name, OBJPROP_COLOR, clr); } //+------------------------------------------------------------------+ //| Create section header | //+------------------------------------------------------------------+ void CDashboardEnhanced::CreateSection(string title, int &y_offset) { string name = m_prefix + "SEC_" + title; CreateLabel(name, m_config.x_pos + 10, y_offset, "▼ " + title, m_config.header_color, 10, "Arial Bold"); y_offset += m_line_height + 5; } //+------------------------------------------------------------------+ //| Draw risk meter | //+------------------------------------------------------------------+ void CDashboardEnhanced::DrawRiskMeter(string name, int x, int y, double risk_percent) { int width = m_config.width - 20; int height = 20; //--- Background string bg_name = name + "_BG"; if(ObjectFind(0, bg_name) < 0) { ObjectCreate(0, bg_name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, bg_name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, bg_name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, bg_name, OBJPROP_XSIZE, width); ObjectSetInteger(0, bg_name, OBJPROP_YSIZE, height); ObjectSetInteger(0, bg_name, OBJPROP_BGCOLOR, C'40,40,40'); ObjectSetInteger(0, bg_name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, bg_name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, bg_name, OBJPROP_BACK, false); ObjectSetInteger(0, bg_name, OBJPROP_ZORDER, 1); m_components[m_component_count++] = bg_name; } //--- Risk bar string bar_name = name + "_BAR"; double bar_width = MathMin(risk_percent / 10.0 * width, width); //--- Color based on risk level color bar_color; if(risk_percent < 2) bar_color = m_config.profit_color; else if(risk_percent < 5) bar_color = clrYellow; else if(risk_percent < 8) bar_color = clrOrange; else bar_color = m_config.loss_color; if(ObjectFind(0, bar_name) < 0) { ObjectCreate(0, bar_name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, bar_name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, bar_name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, bar_name, OBJPROP_YSIZE, height); ObjectSetInteger(0, bar_name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, bar_name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, bar_name, OBJPROP_BACK, false); ObjectSetInteger(0, bar_name, OBJPROP_ZORDER, 2); m_components[m_component_count++] = bar_name; } ObjectSetInteger(0, bar_name, OBJPROP_XSIZE, (int)bar_width); ObjectSetInteger(0, bar_name, OBJPROP_BGCOLOR, bar_color); //--- Risk text string text_name = name + "_TEXT"; if(ObjectFind(0, text_name) < 0) { CreateLabel(text_name, x + width/2, y + 2, "", clrWhite, 8, "Arial Bold", ANCHOR_CENTER); } UpdateLabel(text_name, StringFormat("Risk: %.2f%%", risk_percent), clrWhite); } //+------------------------------------------------------------------+ //| Format currency value | //+------------------------------------------------------------------+ string CDashboardEnhanced::FormatCurrency(double value) { string sign = value >= 0 ? "" : "-"; value = MathAbs(value); if(value >= 1000000) return sign + "$" + DoubleToString(value/1000000, 2) + "M"; else if(value >= 1000) return sign + "$" + DoubleToString(value/1000, 2) + "K"; else return sign + "$" + DoubleToString(value, 2); } //+------------------------------------------------------------------+ //| Get color based on value | //+------------------------------------------------------------------+ color CDashboardEnhanced::GetColorForValue(double value, bool inverse) { if(inverse) value = -value; if(value > 0) return m_config.profit_color; else if(value < 0) return m_config.loss_color; else return m_config.text_color; } //+------------------------------------------------------------------+ //| Destroy dashboard | //+------------------------------------------------------------------+ void CDashboardEnhanced::Destroy() { for(int i = 0; i < m_component_count; i++) { ObjectDelete(0, m_components[i]); } m_component_count = 0; } //+------------------------------------------------------------------+ //| Show dashboard | //+------------------------------------------------------------------+ void CDashboardEnhanced::Show() { for(int i = 0; i < m_component_count; i++) { ObjectSetInteger(0, m_components[i], OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); } } //+------------------------------------------------------------------+ //| Hide dashboard | //+------------------------------------------------------------------+ void CDashboardEnhanced::Hide() { for(int i = 0; i < m_component_count; i++) { ObjectSetInteger(0, m_components[i], OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } } //+------------------------------------------------------------------+ //| Draw performance graph placeholder | //+------------------------------------------------------------------+ void CDashboardEnhanced::DrawPerformanceGraph(string name, int x, int y, int width, int height) { //--- This is a placeholder for a mini equity curve //--- In a full implementation, this would draw an actual graph string bg_name = name + "_BG"; ObjectCreate(0, bg_name, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, bg_name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, bg_name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, bg_name, OBJPROP_XSIZE, width); ObjectSetInteger(0, bg_name, OBJPROP_YSIZE, height); ObjectSetInteger(0, bg_name, OBJPROP_BGCOLOR, C'30,30,30'); ObjectSetInteger(0, bg_name, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, bg_name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, bg_name, OBJPROP_BACK, false); ObjectSetInteger(0, bg_name, OBJPROP_ZORDER, 1); m_components[m_component_count++] = bg_name; } //+------------------------------------------------------------------+ //| Create button | //+------------------------------------------------------------------+ void CDashboardEnhanced::CreateButton(string name, int x, int y, int width, int height, string text, color bg_color, color text_color) { ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); ObjectSetInteger(0, name, OBJPROP_XSIZE, width); ObjectSetInteger(0, name, OBJPROP_YSIZE, height); ObjectSetString(0, name, OBJPROP_TEXT, text); ObjectSetString(0, name, OBJPROP_FONT, m_config.font_name); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, m_config.font_size); ObjectSetInteger(0, name, OBJPROP_COLOR, text_color); ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg_color); ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, text_color); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_STATE, false); ObjectSetInteger(0, name, OBJPROP_ZORDER, 3); m_components[m_component_count++] = name; } //+------------------------------------------------------------------+ //| Format number with thousands separator | //+------------------------------------------------------------------+ string CDashboardEnhanced::FormatNumber(double value, int digits) { return DoubleToString(value, digits); } //+------------------------------------------------------------------+ //| Format percent value | //+------------------------------------------------------------------+ string CDashboardEnhanced::FormatPercent(double value, int digits) { return DoubleToString(value, digits) + "%"; } #endif // DASHBOARD_ENHANCED_MQH