770 lines
31 KiB
MQL5
770 lines
31 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| Dashboard_v71.mqh |
|
||
|
//| Institutional Grade Dashboard Module v7.1 |
|
||
|
//| Real-time Analytics, Risk Metrics, Performance |
|
||
|
//+------------------------------------------------------------------+
|
||
|
#ifndef DASHBOARD_V71_MQH
|
||
|
#define DASHBOARD_V71_MQH
|
||
|
|
||
|
#include "DataTypes_v71.mqh"
|
||
|
#include <ChartObjects/ChartObjectsTxtControls.mqh>
|
||
|
#include <ChartObjects/ChartObjectsShapes.mqh>
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Dashboard Layout |
|
||
|
//+------------------------------------------------------------------+
|
||
|
struct DashboardLayout
|
||
|
{
|
||
|
int x_start;
|
||
|
int y_start;
|
||
|
int width;
|
||
|
int height;
|
||
|
int panel_width;
|
||
|
int panel_height;
|
||
|
int row_height;
|
||
|
int column_width;
|
||
|
color bg_color;
|
||
|
color text_color;
|
||
|
color profit_color;
|
||
|
color loss_color;
|
||
|
color warning_color;
|
||
|
string font_name;
|
||
|
int font_size;
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Dashboard Panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
struct DashboardPanel
|
||
|
{
|
||
|
string name;
|
||
|
int x;
|
||
|
int y;
|
||
|
int width;
|
||
|
int height;
|
||
|
bool is_visible;
|
||
|
string objects[];
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Dashboard Class - Institutional Grade |
|
||
|
//+------------------------------------------------------------------+
|
||
|
class CDashboardV71
|
||
|
{
|
||
|
private:
|
||
|
//--- Layout configuration
|
||
|
DashboardLayout m_layout;
|
||
|
|
||
|
//--- Panels
|
||
|
DashboardPanel m_panel_account;
|
||
|
DashboardPanel m_panel_performance;
|
||
|
DashboardPanel m_panel_risk;
|
||
|
DashboardPanel m_panel_positions;
|
||
|
DashboardPanel m_panel_execution;
|
||
|
DashboardPanel m_panel_correlation;
|
||
|
|
||
|
//--- Object prefix
|
||
|
string m_prefix;
|
||
|
|
||
|
//--- Update tracking
|
||
|
datetime m_last_update;
|
||
|
int m_update_counter;
|
||
|
|
||
|
//--- Visualization options
|
||
|
bool m_show_var_metrics;
|
||
|
bool m_show_greek_letters;
|
||
|
bool m_show_execution_stats;
|
||
|
bool m_show_ml_confidence;
|
||
|
bool m_show_correlation_map;
|
||
|
|
||
|
//--- Helper methods
|
||
|
void CreatePanel(DashboardPanel &panel, string title);
|
||
|
void CreateLabel(string name, int x, int y, string text,
|
||
|
color clr = clrWhite, int size = 0);
|
||
|
void CreateValue(string name, int x, int y, string text,
|
||
|
color clr = clrWhite, int size = 0);
|
||
|
void CreateRectangle(string name, int x, int y, int width,
|
||
|
int height, color clr);
|
||
|
void CreateProgressBar(string name, int x, int y, int width,
|
||
|
double value, double max_value);
|
||
|
void CreateHeatMap(string name, int x, int y, double &matrix[][]);
|
||
|
color GetGradientColor(double value, double min_val, double max_val);
|
||
|
string FormatLargeNumber(double value);
|
||
|
void UpdateObject(string name, string text, color clr = WRONG_VALUE);
|
||
|
void DeletePanel(DashboardPanel &panel);
|
||
|
|
||
|
public:
|
||
|
CDashboardV71();
|
||
|
~CDashboardV71();
|
||
|
|
||
|
//--- Initialization
|
||
|
bool Create(int x, int y, color bg_color = C'20,20,20',
|
||
|
color profit_color = clrLime, color loss_color = clrRed);
|
||
|
bool CreateInstitutional(int x, int y);
|
||
|
void Destroy();
|
||
|
|
||
|
//--- Updates
|
||
|
void Update(PerformanceMetrics &performance, ManagedTrade &trades[],
|
||
|
MarketConditions &conditions);
|
||
|
void UpdateInstitutional(PerformanceMetricsV71 &performance,
|
||
|
SystemStateV71 &state, ExecutionMetrics &execution);
|
||
|
|
||
|
//--- Panel updates
|
||
|
void UpdateAccountPanel(double balance, double equity, double margin_level);
|
||
|
void UpdatePerformancePanel(PerformanceMetricsV71 &performance);
|
||
|
void UpdateRiskPanel(SystemStateV71 &state);
|
||
|
void UpdatePositionsPanel(ManagedTradeV71 &trades[]);
|
||
|
void UpdateExecutionPanel(ExecutionMetrics &execution);
|
||
|
void UpdateCorrelationPanel(CorrelationMatrix &correlations);
|
||
|
|
||
|
//--- Real-time metrics
|
||
|
void UpdateVaRMetrics(double var, double cvar, double stress_var);
|
||
|
void UpdateGreeks(double delta, double gamma, double vega, double theta);
|
||
|
void UpdateMLConfidence(double confidence, string model_status);
|
||
|
void UpdateOrderFlow(double imbalance, double vpin, double liquidity);
|
||
|
|
||
|
//--- Alerts and warnings
|
||
|
void ShowAlert(string message, color alert_color = clrYellow);
|
||
|
void ShowRiskWarning(string risk_type, double level);
|
||
|
void ClearAlerts();
|
||
|
|
||
|
//--- Configuration
|
||
|
void SetVisualizationOptions(bool show_var, bool show_greeks,
|
||
|
bool show_exec, bool show_ml, bool show_corr);
|
||
|
void SetUpdateFrequency(int milliseconds);
|
||
|
void TogglePanel(string panel_name);
|
||
|
|
||
|
//--- Export
|
||
|
void Screenshot(string filename);
|
||
|
void ExportMetrics(string filename);
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Constructor |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDashboardV71::CDashboardV71()
|
||
|
{
|
||
|
m_prefix = "DASHBOARD_V71_";
|
||
|
m_last_update = 0;
|
||
|
m_update_counter = 0;
|
||
|
m_show_var_metrics = true;
|
||
|
m_show_greek_letters = false;
|
||
|
m_show_execution_stats = true;
|
||
|
m_show_ml_confidence = true;
|
||
|
m_show_correlation_map = false;
|
||
|
|
||
|
//--- Default layout
|
||
|
m_layout.width = 400;
|
||
|
m_layout.height = 800;
|
||
|
m_layout.panel_width = 380;
|
||
|
m_layout.panel_height = 150;
|
||
|
m_layout.row_height = 20;
|
||
|
m_layout.column_width = 100;
|
||
|
m_layout.bg_color = C'20,20,20';
|
||
|
m_layout.text_color = clrWhite;
|
||
|
m_layout.profit_color = clrLime;
|
||
|
m_layout.loss_color = clrRed;
|
||
|
m_layout.warning_color = clrYellow;
|
||
|
m_layout.font_name = "Consolas";
|
||
|
m_layout.font_size = 9;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Destructor |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDashboardV71::~CDashboardV71()
|
||
|
{
|
||
|
Destroy();
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create institutional dashboard |
|
||
|
//+------------------------------------------------------------------+
|
||
|
bool CDashboardV71::CreateInstitutional(int x, int y)
|
||
|
{
|
||
|
m_layout.x_start = x;
|
||
|
m_layout.y_start = y;
|
||
|
|
||
|
//--- Create main background
|
||
|
CreateRectangle(m_prefix + "MAIN_BG", x, y, m_layout.width, m_layout.height, m_layout.bg_color);
|
||
|
|
||
|
//--- Create title
|
||
|
CreateLabel(m_prefix + "TITLE", x + 10, y + 10, "ERMT 7.1 - INSTITUTIONAL DASHBOARD",
|
||
|
m_layout.text_color, 12);
|
||
|
|
||
|
int current_y = y + 40;
|
||
|
|
||
|
//--- Account panel
|
||
|
m_panel_account.name = "ACCOUNT";
|
||
|
m_panel_account.x = x + 10;
|
||
|
m_panel_account.y = current_y;
|
||
|
m_panel_account.width = m_layout.panel_width;
|
||
|
m_panel_account.height = 80;
|
||
|
CreatePanel(m_panel_account, "ACCOUNT METRICS");
|
||
|
current_y += 90;
|
||
|
|
||
|
//--- Performance panel
|
||
|
m_panel_performance.name = "PERFORMANCE";
|
||
|
m_panel_performance.x = x + 10;
|
||
|
m_panel_performance.y = current_y;
|
||
|
m_panel_performance.width = m_layout.panel_width;
|
||
|
m_panel_performance.height = 120;
|
||
|
CreatePanel(m_panel_performance, "PERFORMANCE ANALYTICS");
|
||
|
current_y += 130;
|
||
|
|
||
|
//--- Risk panel
|
||
|
m_panel_risk.name = "RISK";
|
||
|
m_panel_risk.x = x + 10;
|
||
|
m_panel_risk.y = current_y;
|
||
|
m_panel_risk.width = m_layout.panel_width;
|
||
|
m_panel_risk.height = 140;
|
||
|
CreatePanel(m_panel_risk, "RISK METRICS");
|
||
|
current_y += 150;
|
||
|
|
||
|
//--- Positions panel
|
||
|
m_panel_positions.name = "POSITIONS";
|
||
|
m_panel_positions.x = x + 10;
|
||
|
m_panel_positions.y = current_y;
|
||
|
m_panel_positions.width = m_layout.panel_width;
|
||
|
m_panel_positions.height = 160;
|
||
|
CreatePanel(m_panel_positions, "ACTIVE POSITIONS");
|
||
|
current_y += 170;
|
||
|
|
||
|
//--- Execution panel
|
||
|
if(m_show_execution_stats)
|
||
|
{
|
||
|
m_panel_execution.name = "EXECUTION";
|
||
|
m_panel_execution.x = x + 10;
|
||
|
m_panel_execution.y = current_y;
|
||
|
m_panel_execution.width = m_layout.panel_width;
|
||
|
m_panel_execution.height = 100;
|
||
|
CreatePanel(m_panel_execution, "EXECUTION QUALITY");
|
||
|
current_y += 110;
|
||
|
}
|
||
|
|
||
|
//--- Update timestamp
|
||
|
CreateLabel(m_prefix + "TIMESTAMP", x + 10, m_layout.y_start + m_layout.height - 20,
|
||
|
"Last Update: " + TimeToString(TimeCurrent()), clrGray, 8);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::CreatePanel(DashboardPanel &panel, string title)
|
||
|
{
|
||
|
string base_name = m_prefix + panel.name + "_";
|
||
|
|
||
|
//--- Panel background
|
||
|
CreateRectangle(base_name + "BG", panel.x, panel.y, panel.width, panel.height, C'30,30,30');
|
||
|
|
||
|
//--- Panel border
|
||
|
CreateRectangle(base_name + "BORDER", panel.x, panel.y, panel.width, 2, C'50,50,50');
|
||
|
|
||
|
//--- Panel title
|
||
|
CreateLabel(base_name + "TITLE", panel.x + 5, panel.y + 5, title, clrCyan, 10);
|
||
|
|
||
|
panel.is_visible = true;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update institutional dashboard |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateInstitutional(PerformanceMetricsV71 &performance,
|
||
|
SystemStateV71 &state, ExecutionMetrics &execution)
|
||
|
{
|
||
|
//--- Update account panel
|
||
|
UpdateAccountPanel(AccountInfoDouble(ACCOUNT_BALANCE),
|
||
|
AccountInfoDouble(ACCOUNT_EQUITY),
|
||
|
AccountInfoDouble(ACCOUNT_MARGIN_LEVEL));
|
||
|
|
||
|
//--- Update performance panel
|
||
|
UpdatePerformancePanel(performance);
|
||
|
|
||
|
//--- Update risk panel
|
||
|
UpdateRiskPanel(state);
|
||
|
|
||
|
//--- Update execution panel
|
||
|
if(m_show_execution_stats)
|
||
|
UpdateExecutionPanel(execution);
|
||
|
|
||
|
//--- Update timestamp
|
||
|
UpdateObject(m_prefix + "TIMESTAMP",
|
||
|
"Updated: " + TimeToString(TimeCurrent(), TIME_SECONDS), clrGray);
|
||
|
|
||
|
m_last_update = TimeCurrent();
|
||
|
m_update_counter++;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update account panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateAccountPanel(double balance, double equity, double margin_level)
|
||
|
{
|
||
|
string base = m_prefix + "ACCOUNT_";
|
||
|
int x = m_panel_account.x + 10;
|
||
|
int y = m_panel_account.y + 25;
|
||
|
|
||
|
//--- Balance
|
||
|
CreateLabel(base + "BAL_LBL", x, y, "Balance:", m_layout.text_color);
|
||
|
CreateValue(base + "BAL_VAL", x + 100, y, FormatLargeNumber(balance), m_layout.text_color);
|
||
|
|
||
|
//--- Equity
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "EQ_LBL", x, y, "Equity:", m_layout.text_color);
|
||
|
color eq_color = (equity >= balance) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateValue(base + "EQ_VAL", x + 100, y, FormatLargeNumber(equity), eq_color);
|
||
|
|
||
|
//--- Margin Level
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "ML_LBL", x, y, "Margin Lvl:", m_layout.text_color);
|
||
|
color ml_color = (margin_level > 200) ? m_layout.profit_color :
|
||
|
(margin_level > 100) ? m_layout.warning_color : m_layout.loss_color;
|
||
|
string ml_text = (margin_level > 0) ? DoubleToString(margin_level, 1) + "%" : "N/A";
|
||
|
CreateValue(base + "ML_VAL", x + 100, y, ml_text, ml_color);
|
||
|
|
||
|
//--- Floating P/L
|
||
|
double floating_pl = equity - balance;
|
||
|
CreateLabel(base + "PL_LBL", x + 200, y - m_layout.row_height * 2, "Float P/L:", m_layout.text_color);
|
||
|
color pl_color = (floating_pl >= 0) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateValue(base + "PL_VAL", x + 280, y - m_layout.row_height * 2,
|
||
|
FormatLargeNumber(floating_pl), pl_color);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update performance panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdatePerformancePanel(PerformanceMetricsV71 &performance)
|
||
|
{
|
||
|
string base = m_prefix + "PERFORMANCE_";
|
||
|
int x = m_panel_performance.x + 10;
|
||
|
int y = m_panel_performance.y + 25;
|
||
|
|
||
|
//--- Row 1: Win Rate & Profit Factor
|
||
|
CreateLabel(base + "WR_LBL", x, y, "Win Rate:", m_layout.text_color);
|
||
|
color wr_color = (performance.win_rate > 50) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateValue(base + "WR_VAL", x + 80, y, DoubleToString(performance.win_rate, 1) + "%", wr_color);
|
||
|
|
||
|
CreateLabel(base + "PF_LBL", x + 190, y, "Prof Factor:", m_layout.text_color);
|
||
|
color pf_color = (performance.profit_factor > 1.0) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateValue(base + "PF_VAL", x + 280, y, DoubleToString(performance.profit_factor, 2), pf_color);
|
||
|
|
||
|
//--- Row 2: Sharpe & Sortino
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "SR_LBL", x, y, "Sharpe:", m_layout.text_color);
|
||
|
color sr_color = (performance.sharpe_ratio > 1.0) ? m_layout.profit_color :
|
||
|
(performance.sharpe_ratio > 0) ? m_layout.text_color : m_layout.loss_color;
|
||
|
CreateValue(base + "SR_VAL", x + 80, y, DoubleToString(performance.sharpe_ratio, 2), sr_color);
|
||
|
|
||
|
CreateLabel(base + "SO_LBL", x + 190, y, "Sortino:", m_layout.text_color);
|
||
|
CreateValue(base + "SO_VAL", x + 280, y, DoubleToString(performance.sortino_ratio, 2), sr_color);
|
||
|
|
||
|
//--- Row 3: Information Ratio & Hit Rate
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "IR_LBL", x, y, "Info Ratio:", m_layout.text_color);
|
||
|
CreateValue(base + "IR_VAL", x + 80, y, DoubleToString(performance.information_ratio, 2), m_layout.text_color);
|
||
|
|
||
|
CreateLabel(base + "HR_LBL", x + 190, y, "Hit Rate:", m_layout.text_color);
|
||
|
CreateValue(base + "HR_VAL", x + 280, y, DoubleToString(performance.hit_rate, 1) + "%", m_layout.text_color);
|
||
|
|
||
|
//--- Row 4: Max DD & Recovery
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "DD_LBL", x, y, "Max DD:", m_layout.text_color);
|
||
|
CreateValue(base + "DD_VAL", x + 80, y, DoubleToString(performance.max_drawdown_percent, 1) + "%", m_layout.loss_color);
|
||
|
|
||
|
CreateLabel(base + "RF_LBL", x + 190, y, "Recovery:", m_layout.text_color);
|
||
|
CreateValue(base + "RF_VAL", x + 280, y, DoubleToString(performance.recovery_factor, 2), m_layout.text_color);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update risk panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateRiskPanel(SystemStateV71 &state)
|
||
|
{
|
||
|
string base = m_prefix + "RISK_";
|
||
|
int x = m_panel_risk.x + 10;
|
||
|
int y = m_panel_risk.y + 25;
|
||
|
|
||
|
//--- VaR Metrics
|
||
|
if(m_show_var_metrics)
|
||
|
{
|
||
|
CreateLabel(base + "VAR_LBL", x, y, "VaR (95%):", m_layout.text_color);
|
||
|
color var_color = (state.current_var < 2.0) ? m_layout.profit_color :
|
||
|
(state.current_var < 3.0) ? m_layout.warning_color : m_layout.loss_color;
|
||
|
CreateValue(base + "VAR_VAL", x + 80, y, DoubleToString(state.current_var, 2) + "%", var_color);
|
||
|
|
||
|
CreateLabel(base + "CVAR_LBL", x + 190, y, "CVaR:", m_layout.text_color);
|
||
|
CreateValue(base + "CVAR_VAL", x + 280, y, DoubleToString(state.current_cvar, 2) + "%", var_color);
|
||
|
|
||
|
y += m_layout.row_height;
|
||
|
}
|
||
|
|
||
|
//--- Portfolio Beta
|
||
|
CreateLabel(base + "BETA_LBL", x, y, "Beta:", m_layout.text_color);
|
||
|
color beta_color = (MathAbs(state.portfolio_beta) < 1.0) ? m_layout.text_color : m_layout.warning_color;
|
||
|
CreateValue(base + "BETA_VAL", x + 80, y, DoubleToString(state.portfolio_beta, 2), beta_color);
|
||
|
|
||
|
//--- Real-time Sharpe
|
||
|
CreateLabel(base + "RTS_LBL", x + 190, y, "RT Sharpe:", m_layout.text_color);
|
||
|
CreateValue(base + "RTS_VAL", x + 280, y, DoubleToString(state.sharpe_real_time, 2), m_layout.text_color);
|
||
|
|
||
|
//--- Risk Score
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "RISK_SCORE_LBL", x, y, "Risk Score:", m_layout.text_color);
|
||
|
color risk_color = RiskScoreToColor(state.risk_score);
|
||
|
CreateValue(base + "RISK_SCORE_VAL", x + 80, y, IntegerToString(state.risk_score) + "/100", risk_color);
|
||
|
|
||
|
//--- Risk Score Bar
|
||
|
CreateProgressBar(base + "RISK_BAR", x, y + 20, 350, state.risk_score, 100);
|
||
|
|
||
|
//--- Max Correlation
|
||
|
y += m_layout.row_height + 25;
|
||
|
CreateLabel(base + "CORR_LBL", x, y, "Max Correlation:", m_layout.text_color);
|
||
|
color corr_color = (state.max_position_correlation < 0.7) ? m_layout.text_color : m_layout.warning_color;
|
||
|
CreateValue(base + "CORR_VAL", x + 120, y, DoubleToString(state.max_position_correlation, 2), corr_color);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update positions panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdatePositionsPanel(ManagedTradeV71 &trades[])
|
||
|
{
|
||
|
string base = m_prefix + "POSITIONS_";
|
||
|
int x = m_panel_positions.x + 10;
|
||
|
int y = m_panel_positions.y + 25;
|
||
|
|
||
|
int trade_count = ArraySize(trades);
|
||
|
int display_count = MathMin(trade_count, 6); // Show max 6 positions
|
||
|
|
||
|
//--- Header
|
||
|
CreateLabel(base + "HDR", x, y,
|
||
|
"Symbol Dir Vol P/L Risk R-Mult", clrCyan, 8);
|
||
|
y += 15;
|
||
|
|
||
|
//--- Position details
|
||
|
for(int i = 0; i < display_count; i++)
|
||
|
{
|
||
|
string row_base = base + "ROW_" + IntegerToString(i) + "_";
|
||
|
|
||
|
//--- Symbol
|
||
|
CreateLabel(row_base + "SYM", x, y, trades[i].symbol, m_layout.text_color, 8);
|
||
|
|
||
|
//--- Direction
|
||
|
string dir = (trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL";
|
||
|
color dir_color = (trades[i].type == POSITION_TYPE_BUY) ? clrDodgerBlue : clrOrangeRed;
|
||
|
CreateLabel(row_base + "DIR", x + 60, y, dir, dir_color, 8);
|
||
|
|
||
|
//--- Volume
|
||
|
CreateLabel(row_base + "VOL", x + 100, y, DoubleToString(trades[i].volume, 2), m_layout.text_color, 8);
|
||
|
|
||
|
//--- P/L
|
||
|
color pl_color = (trades[i].profit >= 0) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateLabel(row_base + "PL", x + 150, y, DoubleToString(trades[i].profit, 0), pl_color, 8);
|
||
|
|
||
|
//--- Risk
|
||
|
CreateLabel(row_base + "RISK", x + 220, y, DoubleToString(trades[i].risk_percent, 1) + "%", m_layout.text_color, 8);
|
||
|
|
||
|
//--- R-Multiple
|
||
|
color r_color = (trades[i].r_multiple >= 0) ? m_layout.profit_color : m_layout.loss_color;
|
||
|
CreateLabel(row_base + "R", x + 280, y, DoubleToString(trades[i].r_multiple, 1) + "R", r_color, 8);
|
||
|
|
||
|
y += 15;
|
||
|
}
|
||
|
|
||
|
//--- Summary
|
||
|
if(trade_count > 0)
|
||
|
{
|
||
|
y += 5;
|
||
|
double total_risk = 0;
|
||
|
double total_profit = 0;
|
||
|
|
||
|
for(int i = 0; i < trade_count; i++)
|
||
|
{
|
||
|
total_risk += trades[i].risk_percent;
|
||
|
total_profit += trades[i].profit;
|
||
|
}
|
||
|
|
||
|
CreateLabel(base + "SUMM", x, y,
|
||
|
"Total: " + IntegerToString(trade_count) + " positions, " +
|
||
|
"Risk: " + DoubleToString(total_risk, 1) + "%, " +
|
||
|
"P/L: " + DoubleToString(total_profit, 0),
|
||
|
m_layout.text_color, 9);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CreateLabel(base + "EMPTY", x, y, "No active positions", clrGray);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update execution panel |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateExecutionPanel(ExecutionMetrics &execution)
|
||
|
{
|
||
|
string base = m_prefix + "EXECUTION_";
|
||
|
int x = m_panel_execution.x + 10;
|
||
|
int y = m_panel_execution.y + 25;
|
||
|
|
||
|
//--- Average Slippage
|
||
|
CreateLabel(base + "SLIP_LBL", x, y, "Avg Slippage:", m_layout.text_color);
|
||
|
color slip_color = (execution.avg_slippage < 0) ? m_layout.profit_color : // Negative = price improvement
|
||
|
(execution.avg_slippage < 1) ? m_layout.text_color : m_layout.loss_color;
|
||
|
CreateValue(base + "SLIP_VAL", x + 100, y, DoubleToString(execution.avg_slippage, 2) + " pips", slip_color);
|
||
|
|
||
|
//--- Fill Rate
|
||
|
CreateLabel(base + "FILL_LBL", x + 200, y, "Fill Rate:", m_layout.text_color);
|
||
|
double fill_rate = (execution.fills_count > 0) ?
|
||
|
(double)(execution.fills_count - execution.rejected_orders) / execution.fills_count * 100 : 0;
|
||
|
CreateValue(base + "FILL_VAL", x + 280, y, DoubleToString(fill_rate, 1) + "%", m_layout.text_color);
|
||
|
|
||
|
//--- Positive Slippage Rate
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "POS_LBL", x, y, "Pos Slip Rate:", m_layout.text_color);
|
||
|
CreateValue(base + "POS_VAL", x + 100, y, DoubleToString(execution.positive_slippage_rate * 100, 1) + "%", m_layout.text_color);
|
||
|
|
||
|
//--- Average Fill Time
|
||
|
CreateLabel(base + "TIME_LBL", x + 200, y, "Fill Time:", m_layout.text_color);
|
||
|
CreateValue(base + "TIME_VAL", x + 280, y, DoubleToString(execution.avg_fill_time_ms, 0) + " ms", m_layout.text_color);
|
||
|
|
||
|
//--- VWAP Tracking Error
|
||
|
if(execution.vwap_tracking_error != 0)
|
||
|
{
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "VWAP_LBL", x, y, "VWAP Error:", m_layout.text_color);
|
||
|
CreateValue(base + "VWAP_VAL", x + 100, y, DoubleToString(execution.vwap_tracking_error, 3), m_layout.text_color);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create label object |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::CreateLabel(string name, int x, int y, string text, color clr, int size)
|
||
|
{
|
||
|
if(ObjectFind(0, name) >= 0)
|
||
|
{
|
||
|
ObjectSetString(0, name, OBJPROP_TEXT, text);
|
||
|
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
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);
|
||
|
ObjectSetString(0, name, OBJPROP_TEXT, text);
|
||
|
ObjectSetString(0, name, OBJPROP_FONT, m_layout.font_name);
|
||
|
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, (size > 0) ? size : m_layout.font_size);
|
||
|
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
|
||
|
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create value object (right-aligned) |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::CreateValue(string name, int x, int y, string text, color clr, int size)
|
||
|
{
|
||
|
CreateLabel(name, x, y, text, clr, size);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create rectangle object |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::CreateRectangle(string name, int x, int y, int width, int height, color clr)
|
||
|
{
|
||
|
if(ObjectFind(0, name) < 0)
|
||
|
{
|
||
|
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 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);
|
||
|
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
|
||
|
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||
|
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||
|
ObjectSetInteger(0, name, OBJPROP_WIDTH, 0);
|
||
|
ObjectSetInteger(0, name, OBJPROP_BACK, true);
|
||
|
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create progress bar |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::CreateProgressBar(string name, int x, int y, int width, double value, double max_value)
|
||
|
{
|
||
|
//--- Background
|
||
|
CreateRectangle(name + "_BG", x, y, width, 10, C'40,40,40');
|
||
|
|
||
|
//--- Fill
|
||
|
int fill_width = (int)(width * value / max_value);
|
||
|
color fill_color = GetGradientColor(value, 0, max_value);
|
||
|
CreateRectangle(name + "_FILL", x, y, fill_width, 10, fill_color);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Get gradient color based on value |
|
||
|
//+------------------------------------------------------------------+
|
||
|
color CDashboardV71::GetGradientColor(double value, double min_val, double max_val)
|
||
|
{
|
||
|
double ratio = (value - min_val) / (max_val - min_val);
|
||
|
ratio = MathMax(0, MathMin(1, ratio));
|
||
|
|
||
|
//--- Green to Red gradient
|
||
|
int r = (int)(255 * ratio);
|
||
|
int g = (int)(255 * (1 - ratio));
|
||
|
int b = 0;
|
||
|
|
||
|
return StringToColor(StringFormat("%d,%d,%d", r, g, b));
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Format large numbers |
|
||
|
//+------------------------------------------------------------------+
|
||
|
string CDashboardV71::FormatLargeNumber(double value)
|
||
|
{
|
||
|
if(MathAbs(value) >= 1000000)
|
||
|
return DoubleToString(value / 1000000, 2) + "M";
|
||
|
else if(MathAbs(value) >= 1000)
|
||
|
return DoubleToString(value / 1000, 2) + "K";
|
||
|
else
|
||
|
return DoubleToString(value, 2);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update object text and color |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateObject(string name, string text, color clr)
|
||
|
{
|
||
|
if(ObjectFind(0, name) >= 0)
|
||
|
{
|
||
|
ObjectSetString(0, name, OBJPROP_TEXT, text);
|
||
|
if(clr != WRONG_VALUE)
|
||
|
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update VaR metrics display |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::UpdateVaRMetrics(double var, double cvar, double stress_var)
|
||
|
{
|
||
|
string base = m_prefix + "VAR_METRICS_";
|
||
|
int x = m_panel_risk.x + 10;
|
||
|
int y = m_panel_risk.y + 100;
|
||
|
|
||
|
CreateLabel(base + "TITLE", x, y, "Value at Risk Analysis", clrCyan, 10);
|
||
|
y += 20;
|
||
|
|
||
|
//--- VaR
|
||
|
CreateLabel(base + "VAR_LBL", x, y, "VaR (95%):", m_layout.text_color);
|
||
|
color var_color = (var < 2.0) ? m_layout.profit_color :
|
||
|
(var < 3.0) ? m_layout.warning_color : m_layout.loss_color;
|
||
|
CreateValue(base + "VAR_VAL", x + 100, y, DoubleToString(var, 2) + "%", var_color);
|
||
|
|
||
|
//--- CVaR
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "CVAR_LBL", x, y, "CVaR (95%):", m_layout.text_color);
|
||
|
CreateValue(base + "CVAR_VAL", x + 100, y, DoubleToString(cvar, 2) + "%", var_color);
|
||
|
|
||
|
//--- Stressed VaR
|
||
|
y += m_layout.row_height;
|
||
|
CreateLabel(base + "SVAR_LBL", x, y, "Stressed VaR:", m_layout.text_color);
|
||
|
color svar_color = (stress_var < 5.0) ? m_layout.warning_color : m_layout.loss_color;
|
||
|
CreateValue(base + "SVAR_VAL", x + 100, y, DoubleToString(stress_var, 2) + "%", svar_color);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Show alert message |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::ShowAlert(string message, color alert_color)
|
||
|
{
|
||
|
string name = m_prefix + "ALERT";
|
||
|
int x = m_layout.x_start + 10;
|
||
|
int y = m_layout.y_start + m_layout.height - 50;
|
||
|
|
||
|
//--- Alert background
|
||
|
CreateRectangle(name + "_BG", x, y, m_layout.panel_width, 30, C'50,20,20');
|
||
|
|
||
|
//--- Alert text
|
||
|
CreateLabel(name + "_TEXT", x + 5, y + 5, "⚠ " + message, alert_color, 10);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Clear all alerts |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::ClearAlerts()
|
||
|
{
|
||
|
ObjectDelete(0, m_prefix + "ALERT_BG");
|
||
|
ObjectDelete(0, m_prefix + "ALERT_TEXT");
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Destroy dashboard |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::Destroy()
|
||
|
{
|
||
|
//--- Delete all objects with prefix
|
||
|
int total = ObjectsTotal(0);
|
||
|
for(int i = total - 1; i >= 0; i--)
|
||
|
{
|
||
|
string obj_name = ObjectName(0, i);
|
||
|
if(StringFind(obj_name, m_prefix) == 0)
|
||
|
ObjectDelete(0, obj_name);
|
||
|
}
|
||
|
|
||
|
ChartRedraw();
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create standard dashboard (compatibility) |
|
||
|
//+------------------------------------------------------------------+
|
||
|
bool CDashboardV71::Create(int x, int y, color bg_color, color profit_color, color loss_color)
|
||
|
{
|
||
|
m_layout.bg_color = bg_color;
|
||
|
m_layout.profit_color = profit_color;
|
||
|
m_layout.loss_color = loss_color;
|
||
|
|
||
|
return CreateInstitutional(x, y);
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Update standard dashboard (compatibility) |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDashboardV71::Update(PerformanceMetrics &performance, ManagedTrade &trades[],
|
||
|
MarketConditions &conditions)
|
||
|
{
|
||
|
//--- Convert to V71 structures and update
|
||
|
PerformanceMetricsV71 perf_v71;
|
||
|
|
||
|
//--- Copy basic metrics
|
||
|
perf_v71.total_trades = performance.total_trades;
|
||
|
perf_v71.winning_trades = performance.winning_trades;
|
||
|
perf_v71.losing_trades = performance.losing_trades;
|
||
|
perf_v71.gross_profit = performance.gross_profit;
|
||
|
perf_v71.gross_loss = performance.gross_loss;
|
||
|
perf_v71.net_profit = performance.net_profit;
|
||
|
perf_v71.profit_factor = performance.profit_factor;
|
||
|
perf_v71.win_rate = performance.win_rate;
|
||
|
perf_v71.sharpe_ratio = performance.sharpe_ratio;
|
||
|
perf_v71.max_drawdown_percent = performance.max_drawdown_percent;
|
||
|
|
||
|
SystemStateV71 state;
|
||
|
state.current_var = 0;
|
||
|
state.current_cvar = 0;
|
||
|
state.portfolio_beta = 0;
|
||
|
state.sharpe_real_time = performance.sharpe_ratio;
|
||
|
state.risk_score = 50;
|
||
|
|
||
|
ExecutionMetrics exec;
|
||
|
exec.avg_slippage = 0;
|
||
|
exec.positive_slippage_rate = 0;
|
||
|
exec.avg_fill_time_ms = 10;
|
||
|
exec.fills_count = performance.total_trades;
|
||
|
exec.rejected_orders = 0;
|
||
|
|
||
|
UpdateInstitutional(perf_v71, state, exec);
|
||
|
}
|
||
|
|
||
|
#endif // DASHBOARD_V71_MQH
|