Overview To fully integrate the enhanced external trade management system, updates are required to 5 out of 7 existing modules. The updates maintain backward compatibility while adding new functionality for external trade handling. Module Update Requirements 🟢 No Updates Required (2 modules) TechnicalAnalysis.mqh - Already provides necessary calculations EntrySystem.mqh - Only handles EA's own entry signals 🟡 Minor Updates (2 modules) DataTypes.mqh - Add external trade structures and fields Utilities.mqh - Enhanced logging for external trades 🟠 Moderate Updates (3 modules) RiskManager.mqh - Enhanced risk enforcement methods TradeManager.mqh - Improved stop management for externals Dashboard.mqh - Display external trade information Integration Steps Phase 1: Data Structures (DataTypes.mqh) Add ENUM_EXTERNAL_STATUS enumeration Extend ManagedTrade structure with external-specific fields Add ExternalTradeStats structure for metrics Update DashboardConfig with show_external flag Key additions: external_status - Track state of external trade source_name - Identify where trade came from stops_modified - Track if we modified the trade original_sl/tp - Store original values for comparison Phase 2: Risk Management (RiskManager.mqh) Add EnforceRiskRulesEnhanced() method Implement GetExternalExposure() for risk aggregation Add UpdateExternalStats() for tracking Enhance ValidateAndAdjustRiskExternal() method Key features: Separate risk calculation for external trades Cache mechanism for performance Statistical tracking of external positions Smart risk adjustment without closing trades Phase 3: Trade Management (TradeManager.mqh) Add ApplyDefaultStopsEnhanced() with better logic Implement OverrideExternalStops() with smart override Create ManageExternalTrade() with different rules Add ApplyBreakevenExternal() with wider triggers Key features: Smart stop override (only improve, never worsen) Different management rules for external trades Respect minimum broker distances Track modification success/failure rates Phase 4: User Interface (Dashboard.mqh) Add CreateExternalSection() for display area Implement UpdateExternalSection() for real-time updates Add SetCustomText() for flexible display Create ShowExternalTrades() toggle method Key features: Real-time external trade count and risk Color-coded risk warnings List of active external positions Modification statistics display Phase 5: Logging (Utilities.mqh) Add LogExternalTrade() for detailed event logging Create separate CSV log for external trades Enhance GenerateReportEnhanced() with external section Add IdentifyTradeSource() for magic number interpretation Key features: Separate CSV log for external trade events Detailed tracking of all modifications Source identification from magic numbers Enhanced reporting with external statistics
770 lines
No EOL
31 KiB
MQL5
770 lines
No EOL
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 |