922 lines
No EOL
35 KiB
MQL5
922 lines
No EOL
35 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_Optimised.mqh"
|
|
#include "Symbol_Manager.mqh"
|
|
#include "Performance_Tracker.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 |