mql5/Experts/Advisors/Modules_optimised/Dashboard_Enhanced (2).mqh

922 lines
No EOL
34 KiB
MQL5

//+------------------------------------------------------------------+
//| 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