mql5/Shared Projects/ERMT-ML/Modules-ML8x/MultiTradeReporter_v71.mqh

956 lines
40 KiB
MQL5
Raw Permalink Normal View History

Module Integration Summary for External Trade Management 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
2025-08-27 14:21:02 +01:00
//+------------------------------------------------------------------+
//| MultiTradeReporter_v71.mqh |
//| Institutional Grade Multi-Source Reporting |
//| Performance Attribution, Risk Analytics, Compliance |
//+------------------------------------------------------------------+
#ifndef MULTI_TRADE_REPORTER_V71_MQH
#define MULTI_TRADE_REPORTER_V71_MQH
#include "DataTypes_v71.mqh"
#include <Files/FileTxt.mqh>
#include <Files/FileBin.mqh>
//+------------------------------------------------------------------+
//| Report Types |
//+------------------------------------------------------------------+
enum ENUM_REPORT_TYPE
{
REPORT_DAILY = 0,
REPORT_WEEKLY = 1,
REPORT_MONTHLY = 2,
REPORT_QUARTERLY = 3,
REPORT_ANNUAL = 4,
REPORT_CUSTOM = 5
};
//+------------------------------------------------------------------+
//| Performance Attribution |
//+------------------------------------------------------------------+
struct PerformanceAttribution
{
double strategy_contribution;
double timing_contribution;
double selection_contribution;
double allocation_effect;
double interaction_effect;
double currency_effect;
double total_attribution;
};
//+------------------------------------------------------------------+
//| Risk Attribution |
//+------------------------------------------------------------------+
struct RiskAttribution
{
double systematic_risk;
double specific_risk;
double concentration_risk;
double correlation_risk;
double liquidity_risk;
double operational_risk;
double model_risk;
};
//+------------------------------------------------------------------+
//| Compliance Metrics |
//+------------------------------------------------------------------+
struct ComplianceMetrics
{
int violations_count;
double max_position_breach;
double max_drawdown_breach;
double max_var_breach;
int unauthorized_trades;
datetime last_violation_time;
string violation_details[];
};
//+------------------------------------------------------------------+
//| Multi-Trade Reporter Class - Institutional |
//+------------------------------------------------------------------+
class CMultiTradeReporterV71
{
private:
//--- Configuration
string m_report_path;
ENUM_REPORT_TYPE m_report_type;
bool m_csv_export;
bool m_html_export;
bool m_json_export;
bool m_fix_export;
int m_report_frequency;
//--- Tracking
datetime m_last_report_time;
int m_report_count;
//--- Performance attribution
PerformanceAttribution m_attribution;
RiskAttribution m_risk_attribution;
ComplianceMetrics m_compliance;
//--- Report templates
string m_daily_template;
string m_institutional_template;
string m_regulatory_template;
//--- Helper methods
void GenerateHTMLReport(ManagedTradeV71 &trades[], PerformanceMetricsV71 &performance);
void GenerateJSONReport(ManagedTradeV71 &trades[], PerformanceMetricsV71 &performance);
void GenerateFIXReport(ManagedTradeV71 &trades[], PerformanceMetricsV71 &performance);
void GenerateComplianceReport(ComplianceMetrics &compliance);
//--- Analysis methods
void CalculatePerformanceAttribution(ManagedTradeV71 &trades[]);
void CalculateRiskAttribution(ManagedTradeV71 &trades[]);
void AnalyzeTradesByStrategy(ManagedTradeV71 &trades[], string &output);
void AnalyzeTradesByTimeframe(ManagedTradeV71 &trades[], string &output);
void AnalyzeExecutionQuality(ManagedTradeV71 &trades[], string &output);
//--- Statistical analysis
double CalculateInformationRatio(double returns[], double benchmark[]);
double CalculateMaximumLikelihoodEstimate(double data[]);
void CalculateRegressionAnalysis(double x[], double y[], double &alpha, double &beta);
public:
CMultiTradeReporterV71();
~CMultiTradeReporterV71();
//--- Initialization
bool Initialize(string report_path, ENUM_REPORT_TYPE type = REPORT_DAILY);
void SetExportFormats(bool csv, bool html, bool json, bool fix);
void SetReportFrequency(int minutes) { m_report_frequency = minutes; }
//--- Main reporting
void GenerateInstitutionalReport(PerformanceMetricsV71 &performance,
ManagedTradeV71 &trades[],
ExecutionMetrics &execution);
void GenerateRegulatoryReport(ManagedTradeV71 &trades[],
ComplianceMetrics &compliance);
void GenerateRiskReport(ManagedTradeV71 &trades[],
SystemStateV71 &state);
//--- Performance attribution
void UpdatePerformanceAttribution(ManagedTradeV71 &trades[],
PerformanceMetricsV71 &performance);
PerformanceAttribution GetAttribution() { return m_attribution; }
//--- Specialized reports
void GenerateVaRReport(ManagedTradeV71 &trades[], double var, double cvar);
void GenerateStressTestReport(ManagedTradeV71 &trades[], double scenarios[]);
void GenerateCorrelationReport(CorrelationMatrix &correlations);
void GenerateLiquidityReport(ManagedTradeV71 &trades[]);
//--- Trade analysis
void GenerateTradeAnalysis(ManagedTradeV71 &trades[]);
void GenerateMLPerformanceReport(ManagedTradeV71 &trades[]);
void GenerateOrderFlowReport(OrderFlowData &flow_data[]);
//--- Compliance and audit
void CheckCompliance(ManagedTradeV71 &trades[], ComplianceMetrics &metrics);
void GenerateAuditTrail(ManagedTradeV71 &trades[]);
void LogComplianceViolation(string violation_type, string details);
//--- Export methods
void ExportToBloomberg(ManagedTradeV71 &trades[]);
void ExportToFIX(ManagedTradeV71 &trades[]);
void ExportToREDI(ManagedTradeV71 &trades[]);
//--- Real-time updates
void SendRealtimeUpdate(string metric, double value);
void BroadcastPerformance(PerformanceMetricsV71 &performance);
//--- Getters
datetime GetLastReportTime() { return m_last_report_time; }
int GetReportCount() { return m_report_count; }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CMultiTradeReporterV71::CMultiTradeReporterV71()
{
m_report_path = "InstitutionalReports\\";
m_report_type = REPORT_DAILY;
m_csv_export = true;
m_html_export = true;
m_json_export = true;
m_fix_export = false;
m_report_frequency = 3600; // Hourly
m_last_report_time = 0;
m_report_count = 0;
//--- Initialize attribution
ZeroMemory(m_attribution);
ZeroMemory(m_risk_attribution);
ZeroMemory(m_compliance);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CMultiTradeReporterV71::~CMultiTradeReporterV71()
{
}
//+------------------------------------------------------------------+
//| Initialize reporter |
//+------------------------------------------------------------------+
bool CMultiTradeReporterV71::Initialize(string report_path, ENUM_REPORT_TYPE type)
{
m_report_path = report_path;
m_report_type = type;
//--- Create directory structure
if(!FileIsExist(m_report_path))
{
Print("Please create directory: ", m_report_path);
}
//--- Load report templates
m_daily_template = "Daily Institutional Report";
m_institutional_template = "Institutional Trading Report";
m_regulatory_template = "Regulatory Compliance Report";
Print("MultiTradeReporterV71 initialized: Path=", m_report_path,
", Type=", EnumToString(m_report_type));
return true;
}
//+------------------------------------------------------------------+
//| Generate institutional report |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::GenerateInstitutionalReport(PerformanceMetricsV71 &performance,
ManagedTradeV71 &trades[],
ExecutionMetrics &execution)
{
//--- Check report frequency
if(TimeCurrent() - m_last_report_time < m_report_frequency && m_report_frequency > 0)
return;
m_report_count++;
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
StringReplace(timestamp, ":", "_");
StringReplace(timestamp, " ", "_");
//--- Main report content
string report = "";
report += "╔══════════════════════════════════════════════════════════════╗\n";
report += "║ INSTITUTIONAL TRADING REPORT - ERMT 7.1 ║\n";
report += "╚══════════════════════════════════════════════════════════════╝\n\n";
report += "Report Date: " + TimeToString(TimeCurrent()) + "\n";
report += "Report Number: " + IntegerToString(m_report_count) + "\n";
report += "Reporting Period: " + EnumToString(m_report_type) + "\n\n";
//--- Executive Summary
report += "┌─────────────────────────────────────────────────────────────┐\n";
report += "│ EXECUTIVE SUMMARY │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
double starting_balance = AccountInfoDouble(ACCOUNT_BALANCE) - performance.net_profit;
double roi = (starting_balance > 0) ? (performance.net_profit / starting_balance * 100) : 0;
report += "Starting Capital: $" + DoubleToString(starting_balance, 2) + "\n";
report += "Current Capital: $" + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + "\n";
report += "Net P&L: $" + DoubleToString(performance.net_profit, 2) + "\n";
report += "Return on Investment: " + DoubleToString(roi, 2) + "%\n";
report += "Sharpe Ratio: " + DoubleToString(performance.sharpe_ratio, 3) + "\n";
report += "Information Ratio: " + DoubleToString(performance.information_ratio, 3) + "\n\n";
//--- Risk Analytics
report += "┌─────────────────────────────────────────────────────────────┐\n";
report += "│ RISK ANALYTICS │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
report += "Value at Risk (95%): " + DoubleToString(performance.var_95, 2) + "%\n";
report += "Conditional VaR (95%): " + DoubleToString(performance.cvar_95, 2) + "%\n";
report += "Maximum Drawdown: " + DoubleToString(performance.max_drawdown_percent, 2) + "%\n";
report += "Beta: " + DoubleToString(performance.beta, 3) + "\n";
report += "Tracking Error: " + DoubleToString(performance.tracking_error, 3) + "%\n\n";
//--- Performance Attribution
if(m_attribution.total_attribution != 0)
{
report += "┌─────────────────────────────────────────────────────────────┐\n";
report += "│ PERFORMANCE ATTRIBUTION │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
report += "Strategy Selection: " + DoubleToString(m_attribution.selection_contribution * 100, 2) + "%\n";
report += "Market Timing: " + DoubleToString(m_attribution.timing_contribution * 100, 2) + "%\n";
report += "Asset Allocation: " + DoubleToString(m_attribution.allocation_effect * 100, 2) + "%\n";
report += "Currency Effect: " + DoubleToString(m_attribution.currency_effect * 100, 2) + "%\n";
report += "Total Attribution: " + DoubleToString(m_attribution.total_attribution * 100, 2) + "%\n\n";
}
//--- Execution Quality
report += "┌─────────────────────────────────────────────────────────────┐\n";
report += "│ EXECUTION QUALITY │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
report += "Total Executions: " + IntegerToString(execution.fills_count) + "\n";
report += "Average Slippage: " + DoubleToString(execution.avg_slippage, 2) + " pips\n";
report += "Positive Slippage Rate: " + DoubleToString(execution.positive_slippage_rate * 100, 1) + "%\n";
report += "Average Fill Time: " + DoubleToString(execution.avg_fill_time_ms, 0) + " ms\n";
report += "VWAP Tracking Error: " + DoubleToString(execution.vwap_tracking_error, 3) + "\n";
report += "Price Improvement: $" + DoubleToString(execution.improvement_amount, 2) + "\n\n";
//--- Position Analysis
report += "┌─────────────────────────────────────────────────────────────┐\n";
report += "│ POSITION ANALYSIS │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
int trade_count = ArraySize(trades);
report += "Active Positions: " + IntegerToString(trade_count) + "\n";
if(trade_count > 0)
{
//--- Group by symbol
string symbols[];
double exposures[];
int symbol_count = 0;
for(int i = 0; i < trade_count; i++)
{
int idx = -1;
for(int j = 0; j < symbol_count; j++)
{
if(symbols[j] == trades[i].symbol)
{
idx = j;
break;
}
}
if(idx < 0)
{
ArrayResize(symbols, symbol_count + 1);
ArrayResize(exposures, symbol_count + 1);
symbols[symbol_count] = trades[i].symbol;
exposures[symbol_count] = trades[i].risk_percent;
symbol_count++;
}
else
{
exposures[idx] += trades[i].risk_percent;
}
}
report += "\nExposure by Symbol:\n";
for(int i = 0; i < symbol_count; i++)
{
report += " " + symbols[i] + ": " + DoubleToString(exposures[i], 2) + "%\n";
}
}
//--- Trade Analysis
string trade_analysis;
AnalyzeTradesByStrategy(trades, trade_analysis);
report += "\n" + trade_analysis;
//--- Compliance Check
if(m_compliance.violations_count > 0)
{
report += "\n┌─────────────────────────────────────────────────────────────┐\n";
report += "│ COMPLIANCE ALERTS │\n";
report += "└─────────────────────────────────────────────────────────────┘\n";
report += "Total Violations: " + IntegerToString(m_compliance.violations_count) + "\n";
for(int i = 0; i < ArraySize(m_compliance.violation_details); i++)
{
report += " - " + m_compliance.violation_details[i] + "\n";
}
}
//--- Save report
string filename = m_report_path + "Institutional_" + timestamp;
//--- Text format
int handle = FileOpen(filename + ".txt", FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle != INVALID_HANDLE)
{
FileWrite(handle, report);
FileClose(handle);
}
//--- Additional formats
if(m_csv_export)
GenerateCSVReport(trades, performance);
if(m_html_export)
GenerateHTMLReport(trades, performance);
if(m_json_export)
GenerateJSONReport(trades, performance);
if(m_fix_export)
GenerateFIXReport(trades, performance);
m_last_report_time = TimeCurrent();
Print("Institutional report generated: ", filename);
}
//+------------------------------------------------------------------+
//| Generate CSV report |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::GenerateCSVReport(ManagedTradeV71 &trades[],
PerformanceMetricsV71 &performance)
{
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
StringReplace(timestamp, ":", "_");
StringReplace(timestamp, " ", "_");
string filename = m_report_path + "Trades_" + timestamp + ".csv";
int handle = FileOpen(filename, FILE_WRITE|FILE_CSV|FILE_ANSI, ',');
if(handle == INVALID_HANDLE) return;
//--- Header with extended fields
FileWrite(handle, "Ticket", "Symbol", "Type", "Volume", "Entry", "Current",
"SL", "TP", "Profit", "Commission", "Swap", "Risk%", "RMultiple",
"MAE", "MFE", "ExpectedReturn", "PredictedVol", "MLConfidence",
"VaRContribution", "CorrelationRisk", "LiquidityScore",
"ExecutionQuality", "EntryAlgo", "Magic", "OpenTime", "BarsHeld", "Comment");
//--- Trade data
int trade_count = ArraySize(trades);
for(int i = 0; i < trade_count; i++)
{
double current_price = (trades[i].type == POSITION_TYPE_BUY) ?
SymbolInfoDouble(trades[i].symbol, SYMBOL_BID) :
SymbolInfoDouble(trades[i].symbol, SYMBOL_ASK);
FileWrite(handle,
trades[i].ticket,
trades[i].symbol,
(trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL",
trades[i].volume,
trades[i].open_price,
current_price,
trades[i].sl,
trades[i].tp,
trades[i].profit,
trades[i].commission,
trades[i].swap,
trades[i].risk_percent,
trades[i].r_multiple,
trades[i].mae,
trades[i].mfe,
trades[i].expected_return,
trades[i].predicted_volatility,
trades[i].ml_confidence,
trades[i].var_contribution,
trades[i].correlation_risk,
trades[i].liquidity_score,
trades[i].execution_quality,
trades[i].entry_algo,
trades[i].magic,
TimeToString(trades[i].open_time),
trades[i].bars_in_trade,
trades[i].comment);
}
FileClose(handle);
}
//+------------------------------------------------------------------+
//| Calculate performance attribution |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::CalculatePerformanceAttribution(ManagedTradeV71 &trades[])
{
int trade_count = ArraySize(trades);
if(trade_count == 0) return;
//--- Group trades by strategy
double strategy_returns[];
double benchmark_returns[];
//--- Calculate selection effect (simplified)
double total_return = 0;
double strategy_weighted_return = 0;
for(int i = 0; i < trade_count; i++)
{
double trade_return = trades[i].profit / (trades[i].volume * trades[i].open_price);
total_return += trade_return;
//--- Weight by ML confidence
if(trades[i].ml_enhanced)
{
strategy_weighted_return += trade_return * trades[i].ml_confidence;
}
}
m_attribution.selection_contribution = strategy_weighted_return - total_return / trade_count;
//--- Timing contribution (simplified)
double entry_timing_score = 0;
double exit_timing_score = 0;
for(int i = 0; i < trade_count; i++)
{
//--- Entry timing: compare to average price in next few bars
double avg_price_after = trades[i].open_price; // Simplified
if(trades[i].type == POSITION_TYPE_BUY)
{
entry_timing_score += (avg_price_after - trades[i].open_price) / trades[i].open_price;
}
else
{
entry_timing_score += (trades[i].open_price - avg_price_after) / trades[i].open_price;
}
}
m_attribution.timing_contribution = entry_timing_score / trade_count;
//--- Allocation effect (position sizing)
double equal_weight_return = total_return / trade_count;
double actual_weighted_return = 0;
double total_risk = 0;
for(int i = 0; i < trade_count; i++)
{
total_risk += trades[i].risk_percent;
}
for(int i = 0; i < trade_count; i++)
{
double weight = trades[i].risk_percent / total_risk;
double trade_return = trades[i].profit / (trades[i].volume * trades[i].open_price);
actual_weighted_return += trade_return * weight;
}
m_attribution.allocation_effect = actual_weighted_return - equal_weight_return;
//--- Currency effect (for non-base currency pairs)
m_attribution.currency_effect = 0; // Simplified
//--- Interaction effect
m_attribution.interaction_effect = 0; // Simplified
//--- Total attribution
m_attribution.total_attribution = m_attribution.selection_contribution +
m_attribution.timing_contribution +
m_attribution.allocation_effect +
m_attribution.currency_effect +
m_attribution.interaction_effect;
}
//+------------------------------------------------------------------+
//| Update performance attribution |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::UpdatePerformanceAttribution(ManagedTradeV71 &trades[],
PerformanceMetricsV71 &performance)
{
//--- Calculate attribution
CalculatePerformanceAttribution(trades);
//--- Calculate risk attribution
CalculateRiskAttribution(trades);
//--- Store for reporting
m_attribution.strategy_contribution = performance.alpha; // Simplified mapping
}
//+------------------------------------------------------------------+
//| Calculate risk attribution |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::CalculateRiskAttribution(ManagedTradeV71 &trades[])
{
int trade_count = ArraySize(trades);
if(trade_count == 0) return;
//--- Systematic risk (market beta exposure)
double total_beta_exposure = 0;
for(int i = 0; i < trade_count; i++)
{
total_beta_exposure += trades[i].risk_percent * 0.8; // Assume 0.8 beta
}
m_risk_attribution.systematic_risk = total_beta_exposure / trade_count;
//--- Specific risk (idiosyncratic)
m_risk_attribution.specific_risk = 100 - m_risk_attribution.systematic_risk;
//--- Concentration risk
double max_single_risk = 0;
for(int i = 0; i < trade_count; i++)
{
if(trades[i].risk_percent > max_single_risk)
max_single_risk = trades[i].risk_percent;
}
m_risk_attribution.concentration_risk = max_single_risk;
//--- Correlation risk
double total_correlation_risk = 0;
for(int i = 0; i < trade_count; i++)
{
total_correlation_risk += trades[i].correlation_risk;
}
m_risk_attribution.correlation_risk = total_correlation_risk / trade_count;
//--- Liquidity risk
double avg_liquidity_score = 0;
for(int i = 0; i < trade_count; i++)
{
avg_liquidity_score += trades[i].liquidity_score;
}
avg_liquidity_score /= trade_count;
m_risk_attribution.liquidity_risk = (1.0 - avg_liquidity_score) * 100;
//--- Model risk (based on ML confidence)
double avg_ml_confidence = 0;
int ml_trades = 0;
for(int i = 0; i < trade_count; i++)
{
if(trades[i].ml_enhanced)
{
avg_ml_confidence += trades[i].ml_confidence;
ml_trades++;
}
}
if(ml_trades > 0)
{
avg_ml_confidence /= ml_trades;
m_risk_attribution.model_risk = (1.0 - avg_ml_confidence) * 100;
}
}
//+------------------------------------------------------------------+
//| Analyze trades by strategy |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::AnalyzeTradesByStrategy(ManagedTradeV71 &trades[], string &output)
{
output = "STRATEGY BREAKDOWN\n";
output += "─────────────────\n";
//--- Group by entry algorithm
struct StrategyGroup
{
string name;
int count;
double profit;
double win_rate;
double avg_r_multiple;
};
StrategyGroup strategies[];
int strategy_count = 0;
int trade_count = ArraySize(trades);
for(int i = 0; i < trade_count; i++)
{
//--- Find or create strategy group
int idx = -1;
for(int j = 0; j < strategy_count; j++)
{
if(strategies[j].name == trades[i].entry_algo)
{
idx = j;
break;
}
}
if(idx < 0)
{
ArrayResize(strategies, strategy_count + 1);
strategies[strategy_count].name = trades[i].entry_algo;
strategies[strategy_count].count = 0;
strategies[strategy_count].profit = 0;
strategies[strategy_count].win_rate = 0;
strategies[strategy_count].avg_r_multiple = 0;
idx = strategy_count;
strategy_count++;
}
//--- Update metrics
strategies[idx].count++;
strategies[idx].profit += trades[i].profit;
strategies[idx].avg_r_multiple += trades[i].r_multiple;
if(trades[i].profit > 0)
strategies[idx].win_rate++;
}
//--- Calculate averages and format output
for(int i = 0; i < strategy_count; i++)
{
strategies[i].win_rate = (strategies[i].count > 0) ?
strategies[i].win_rate / strategies[i].count * 100 : 0;
strategies[i].avg_r_multiple = (strategies[i].count > 0) ?
strategies[i].avg_r_multiple / strategies[i].count : 0;
output += "\n" + strategies[i].name + ":\n";
output += " Trades: " + IntegerToString(strategies[i].count) + "\n";
output += " P&L: $" + DoubleToString(strategies[i].profit, 2) + "\n";
output += " Win Rate: " + DoubleToString(strategies[i].win_rate, 1) + "%\n";
output += " Avg R-Multiple: " + DoubleToString(strategies[i].avg_r_multiple, 2) + "\n";
}
}
//+------------------------------------------------------------------+
//| Generate JSON report |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::GenerateJSONReport(ManagedTradeV71 &trades[],
PerformanceMetricsV71 &performance)
{
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
StringReplace(timestamp, ":", "_");
StringReplace(timestamp, " ", "_");
string filename = m_report_path + "Report_" + timestamp + ".json";
int handle = FileOpen(filename, FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle == INVALID_HANDLE) return;
//--- Start JSON
FileWrite(handle, "{");
FileWrite(handle, " \"report_info\": {");
FileWrite(handle, " \"timestamp\": \"" + TimeToString(TimeCurrent()) + "\",");
FileWrite(handle, " \"report_type\": \"" + EnumToString(m_report_type) + "\",");
FileWrite(handle, " \"version\": \"7.1\"");
FileWrite(handle, " },");
//--- Performance metrics
FileWrite(handle, " \"performance\": {");
FileWrite(handle, " \"net_profit\": " + DoubleToString(performance.net_profit, 2) + ",");
FileWrite(handle, " \"total_trades\": " + IntegerToString(performance.total_trades) + ",");
FileWrite(handle, " \"win_rate\": " + DoubleToString(performance.win_rate, 2) + ",");
FileWrite(handle, " \"sharpe_ratio\": " + DoubleToString(performance.sharpe_ratio, 3) + ",");
FileWrite(handle, " \"sortino_ratio\": " + DoubleToString(performance.sortino_ratio, 3) + ",");
FileWrite(handle, " \"information_ratio\": " + DoubleToString(performance.information_ratio, 3) + ",");
FileWrite(handle, " \"max_drawdown\": " + DoubleToString(performance.max_drawdown_percent, 2) + ",");
FileWrite(handle, " \"var_95\": " + DoubleToString(performance.var_95, 2) + ",");
FileWrite(handle, " \"cvar_95\": " + DoubleToString(performance.cvar_95, 2));
FileWrite(handle, " },");
//--- Trades array
FileWrite(handle, " \"trades\": [");
int trade_count = ArraySize(trades);
for(int i = 0; i < trade_count; i++)
{
FileWrite(handle, " {");
FileWrite(handle, " \"ticket\": " + IntegerToString(trades[i].ticket) + ",");
FileWrite(handle, " \"symbol\": \"" + trades[i].symbol + "\",");
FileWrite(handle, " \"type\": \"" + ((trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL") + "\",");
FileWrite(handle, " \"volume\": " + DoubleToString(trades[i].volume, 2) + ",");
FileWrite(handle, " \"profit\": " + DoubleToString(trades[i].profit, 2) + ",");
FileWrite(handle, " \"risk_percent\": " + DoubleToString(trades[i].risk_percent, 2) + ",");
FileWrite(handle, " \"r_multiple\": " + DoubleToString(trades[i].r_multiple, 2) + ",");
FileWrite(handle, " \"ml_confidence\": " + DoubleToString(trades[i].ml_confidence, 3));
FileWrite(handle, " }" + ((i < trade_count - 1) ? "," : ""));
}
FileWrite(handle, " ]");
FileWrite(handle, "}");
FileClose(handle);
}
//+------------------------------------------------------------------+
//| Generate HTML report |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::GenerateHTMLReport(ManagedTradeV71 &trades[],
PerformanceMetricsV71 &performance)
{
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
StringReplace(timestamp, ":", "_");
StringReplace(timestamp, " ", "_");
string filename = m_report_path + "Report_" + timestamp + ".html";
int handle = FileOpen(filename, FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle == INVALID_HANDLE) return;
//--- HTML header
FileWrite(handle, "<!DOCTYPE html>");
FileWrite(handle, "<html>");
FileWrite(handle, "<head>");
FileWrite(handle, "<title>ERMT 7.1 Institutional Report</title>");
FileWrite(handle, "<style>");
FileWrite(handle, "body { font-family: Arial, sans-serif; background-color: #1e1e1e; color: #e0e0e0; }");
FileWrite(handle, "h1, h2 { color: #00bcd4; }");
FileWrite(handle, "table { border-collapse: collapse; width: 100%; margin: 20px 0; }");
FileWrite(handle, "th, td { border: 1px solid #333; padding: 8px; text-align: left; }");
FileWrite(handle, "th { background-color: #2c2c2c; color: #00bcd4; }");
FileWrite(handle, "tr:nth-child(even) { background-color: #252525; }");
FileWrite(handle, ".profit { color: #4caf50; }");
FileWrite(handle, ".loss { color: #f44336; }");
FileWrite(handle, ".metric-card { background-color: #2c2c2c; padding: 15px; margin: 10px; border-radius: 5px; display: inline-block; }");
FileWrite(handle, "</style>");
FileWrite(handle, "</head>");
FileWrite(handle, "<body>");
//--- Title
FileWrite(handle, "<h1>ERMT 7.1 Institutional Trading Report</h1>");
FileWrite(handle, "<p>Generated: " + TimeToString(TimeCurrent()) + "</p>");
//--- Key metrics cards
FileWrite(handle, "<div>");
FileWrite(handle, "<div class='metric-card'>");
FileWrite(handle, "<h3>Net P&L</h3>");
FileWrite(handle, "<p class='" + ((performance.net_profit >= 0) ? "profit" : "loss") + "'>$" +
DoubleToString(performance.net_profit, 2) + "</p>");
FileWrite(handle, "</div>");
FileWrite(handle, "<div class='metric-card'>");
FileWrite(handle, "<h3>Sharpe Ratio</h3>");
FileWrite(handle, "<p>" + DoubleToString(performance.sharpe_ratio, 3) + "</p>");
FileWrite(handle, "</div>");
FileWrite(handle, "<div class='metric-card'>");
FileWrite(handle, "<h3>Win Rate</h3>");
FileWrite(handle, "<p>" + DoubleToString(performance.win_rate, 1) + "%</p>");
FileWrite(handle, "</div>");
FileWrite(handle, "<div class='metric-card'>");
FileWrite(handle, "<h3>Max Drawdown</h3>");
FileWrite(handle, "<p class='loss'>" + DoubleToString(performance.max_drawdown_percent, 2) + "%</p>");
FileWrite(handle, "</div>");
FileWrite(handle, "</div>");
//--- Trades table
FileWrite(handle, "<h2>Active Positions</h2>");
FileWrite(handle, "<table>");
FileWrite(handle, "<tr><th>Symbol</th><th>Type</th><th>Volume</th><th>Entry</th><th>P&L</th><th>Risk%</th><th>R-Multiple</th></tr>");
int trade_count = ArraySize(trades);
for(int i = 0; i < trade_count; i++)
{
string pl_class = (trades[i].profit >= 0) ? "profit" : "loss";
FileWrite(handle, "<tr>");
FileWrite(handle, "<td>" + trades[i].symbol + "</td>");
FileWrite(handle, "<td>" + ((trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL") + "</td>");
FileWrite(handle, "<td>" + DoubleToString(trades[i].volume, 2) + "</td>");
FileWrite(handle, "<td>" + DoubleToString(trades[i].open_price, 5) + "</td>");
FileWrite(handle, "<td class='" + pl_class + "'>$" + DoubleToString(trades[i].profit, 2) + "</td>");
FileWrite(handle, "<td>" + DoubleToString(trades[i].risk_percent, 2) + "%</td>");
FileWrite(handle, "<td class='" + pl_class + "'>" + DoubleToString(trades[i].r_multiple, 2) + "</td>");
FileWrite(handle, "</tr>");
}
FileWrite(handle, "</table>");
//--- Footer
FileWrite(handle, "<p style='text-align: center; color: #666; margin-top: 50px;'>ERMT 7.1 - Institutional Risk Management System</p>");
FileWrite(handle, "</body>");
FileWrite(handle, "</html>");
FileClose(handle);
}
//+------------------------------------------------------------------+
//| Check compliance |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::CheckCompliance(ManagedTradeV71 &trades[],
ComplianceMetrics &metrics)
{
//--- Reset metrics
metrics.violations_count = 0;
metrics.max_position_breach = 0;
metrics.max_drawdown_breach = 0;
metrics.max_var_breach = 0;
metrics.unauthorized_trades = 0;
ArrayResize(metrics.violation_details, 0);
//--- Check position limits
double total_exposure = 0;
int trade_count = ArraySize(trades);
for(int i = 0; i < trade_count; i++)
{
total_exposure += trades[i].risk_percent;
//--- Check individual position limit (example: 2% max)
if(trades[i].risk_percent > 2.0)
{
metrics.violations_count++;
metrics.max_position_breach = MathMax(metrics.max_position_breach,
trades[i].risk_percent - 2.0);
int size = ArraySize(metrics.violation_details);
ArrayResize(metrics.violation_details, size + 1);
metrics.violation_details[size] = "Position limit breach: " +
trades[i].symbol + " at " +
DoubleToString(trades[i].risk_percent, 2) + "%";
}
//--- Check authorized magic numbers
if(trades[i].magic < 10000 || trades[i].magic > 99999)
{
metrics.unauthorized_trades++;
}
}
//--- Check total exposure limit (example: 6% max)
if(total_exposure > 6.0)
{
metrics.violations_count++;
int size = ArraySize(metrics.violation_details);
ArrayResize(metrics.violation_details, size + 1);
metrics.violation_details[size] = "Total exposure limit breach: " +
DoubleToString(total_exposure, 2) + "%";
}
//--- Update compliance tracking
m_compliance = metrics;
}
//+------------------------------------------------------------------+
//| Generate VaR report |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::GenerateVaRReport(ManagedTradeV71 &trades[],
double var, double cvar)
{
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
StringReplace(timestamp, ":", "_");
StringReplace(timestamp, " ", "_");
string filename = m_report_path + "VaR_Report_" + timestamp + ".txt";
int handle = FileOpen(filename, FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle == INVALID_HANDLE) return;
FileWrite(handle, "VALUE AT RISK REPORT");
FileWrite(handle, "===================");
FileWrite(handle, "");
FileWrite(handle, "Report Date: " + TimeToString(TimeCurrent()));
FileWrite(handle, "");
FileWrite(handle, "Portfolio VaR (95%): " + DoubleToString(var, 3) + "%");
FileWrite(handle, "Portfolio CVaR (95%): " + DoubleToString(cvar, 3) + "%");
FileWrite(handle, "");
FileWrite(handle, "VaR BY POSITION:");
FileWrite(handle, "----------------");
int trade_count = ArraySize(trades);
double total_var = 0;
for(int i = 0; i < trade_count; i++)
{
FileWrite(handle, trades[i].symbol + ": " +
DoubleToString(trades[i].var_contribution, 3) + "%");
total_var += trades[i].var_contribution;
}
FileWrite(handle, "");
FileWrite(handle, "Total VaR Contribution: " + DoubleToString(total_var, 3) + "%");
FileWrite(handle, "Diversification Benefit: " + DoubleToString(total_var - var, 3) + "%");
FileClose(handle);
}
//+------------------------------------------------------------------+
//| Set export formats |
//+------------------------------------------------------------------+
void CMultiTradeReporterV71::SetExportFormats(bool csv, bool html, bool json, bool fix)
{
m_csv_export = csv;
m_html_export = html;
m_json_export = json;
m_fix_export = fix;
}
#endif // MULTI_TRADE_REPORTER_V71_MQH