mql5/Shared Projects/ERMT-ML/Modules-ML8x/MultiTradeReporter_v71.mqh
darashikoh 0fb1bd1b0a 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

956 lines
No EOL
40 KiB
MQL5

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