I've provided you with a comprehensive solution for managing your commercial EA trades using the Risk Management Overlay EA, despite MT5's one-EA-per-chart limitation: 1. Complete Management Guide 4 different methods to run both EAs Detailed setup instructions for each method Configuration examples for different scenarios 2. Quick Setup Card 5-minute setup for the most common scenario Essential configuration templates Visual dashboard examples 3. EA Detection Utility Automatically detects all running EAs Shows magic numbers and trade counts Provides configuration suggestions 4. Method Selection Flowchart Simple decision tree to choose the best method Comparison of difficulty and resources Specific recommendations based on your needs Recommended Approach For your commercial EA on forex pairs, I recommend: Start with Method 1 (Different Timeframes): Put your commercial EA on H1 chart Put Risk Manager on M15 chart of same pair This is the simplest and most reli
579 lines
No EOL
43 KiB
MQL5
579 lines
No EOL
43 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| MultiTradeReporter.mqh |
|
|
//| Multi-Source Trade Reporting Module |
|
|
//| Fixed all compilation errors |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef MULTI_TRADE_REPORTER_MQH
|
|
#define MULTI_TRADE_REPORTER_MQH
|
|
|
|
#include "DataTypes.mqh"
|
|
#include <Files/FileTxt.mqh>
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Structure for correlation matrix |
|
|
//+------------------------------------------------------------------+
|
|
struct CorrelationPair
|
|
{
|
|
int index1;
|
|
int index2;
|
|
double correlation;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Multi-Trade Reporter Class |
|
|
//+------------------------------------------------------------------+
|
|
class CMultiTradeReporter
|
|
{
|
|
private:
|
|
//--- Configuration
|
|
string m_report_path;
|
|
bool m_csv_export;
|
|
bool m_html_export;
|
|
int m_report_frequency;
|
|
|
|
//--- Tracking
|
|
datetime m_last_report_time;
|
|
int m_report_count;
|
|
|
|
//--- Helper methods
|
|
void GenerateHTMLReport(const ManagedTrade &trades[], const PerformanceMetrics &performance);
|
|
void GenerateCSVReport(const ManagedTrade &trades[], const PerformanceMetrics &performance);
|
|
void AnalyzeTradesBySource(const ManagedTrade &trades[], string &output);
|
|
void AnalyzeCorrelations(const ManagedTrade &trades[], string &output);
|
|
double CalculateCorrelation(string symbol1, string symbol2, int period);
|
|
string GetSourceName(long magic); // Added declaration
|
|
|
|
public:
|
|
CMultiTradeReporter();
|
|
~CMultiTradeReporter();
|
|
|
|
//--- Initialization
|
|
bool Initialize(string report_path);
|
|
|
|
//--- Main reporting
|
|
void GenerateFullReport(const ManagedTrade &trades[], const PerformanceMetrics &performance);
|
|
void GenerateQuickSummary(const ManagedTrade &trades[]);
|
|
void ExportTradeHistory(const ManagedTrade &trades[]);
|
|
|
|
//--- Configuration
|
|
void SetExportFormats(bool csv, bool html) { m_csv_export = csv; m_html_export = html; }
|
|
void SetReportFrequency(int minutes) { m_report_frequency = minutes; }
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CMultiTradeReporter::CMultiTradeReporter()
|
|
{
|
|
m_report_path = "Reports\\";
|
|
m_csv_export = true;
|
|
m_html_export = true;
|
|
m_report_frequency = 60; // Hourly by default
|
|
m_last_report_time = 0;
|
|
m_report_count = 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CMultiTradeReporter::~CMultiTradeReporter()
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initialize reporter |
|
|
//+------------------------------------------------------------------+
|
|
bool CMultiTradeReporter::Initialize(string report_path)
|
|
{
|
|
m_report_path = report_path;
|
|
|
|
//--- Create directory if needed
|
|
if(!FileIsExist(m_report_path))
|
|
{
|
|
// Note: MQL5 cannot create directories, user must create manually
|
|
Print("MultiTradeReporter: Please create directory: ", m_report_path);
|
|
}
|
|
|
|
Print("MultiTradeReporter initialized: Path=", m_report_path);
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate full report |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::GenerateFullReport(const ManagedTrade &trades[], const PerformanceMetrics &performance)
|
|
{
|
|
//--- Check if it's time for report
|
|
if(TimeCurrent() - m_last_report_time < m_report_frequency * 60)
|
|
return;
|
|
|
|
m_report_count++;
|
|
string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES);
|
|
StringReplace(timestamp, ":", "_");
|
|
StringReplace(timestamp, " ", "_");
|
|
|
|
//--- Text report
|
|
string report = "=== MULTI-SOURCE TRADING REPORT ===\n";
|
|
report += "Generated: " + TimeToString(TimeCurrent()) + "\n";
|
|
report += "Report #" + IntegerToString(m_report_count) + "\n\n";
|
|
|
|
//--- Account overview
|
|
report += "ACCOUNT OVERVIEW\n";
|
|
report += "================\n";
|
|
report += "Balance: $" + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + "\n";
|
|
report += "Equity: $" + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2) + "\n";
|
|
report += "Free Margin: $" + DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE), 2) + "\n";
|
|
report += "Margin Level: " + DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL), 2) + "%\n\n";
|
|
|
|
//--- Performance summary
|
|
report += "PERFORMANCE SUMMARY\n";
|
|
report += "==================\n";
|
|
report += "Total Trades: " + IntegerToString(performance.total_trades) + "\n";
|
|
report += "Win Rate: " + DoubleToString(performance.win_rate, 2) + "%\n";
|
|
report += "Profit Factor: " + DoubleToString(performance.profit_factor, 2) + "\n";
|
|
report += "Net Profit: $" + DoubleToString(performance.net_profit, 2) + "\n";
|
|
report += "Max Drawdown: " + DoubleToString(performance.max_drawdown_percent, 2) + "%\n";
|
|
report += "Sharpe Ratio: " + DoubleToString(performance.sharpe_ratio, 2) + "\n\n";
|
|
|
|
//--- Active trades by source
|
|
string source_analysis;
|
|
AnalyzeTradesBySource(trades, source_analysis);
|
|
report += source_analysis;
|
|
|
|
//--- Correlation analysis
|
|
string correlation_analysis;
|
|
AnalyzeCorrelations(trades, correlation_analysis);
|
|
report += correlation_analysis;
|
|
|
|
//--- Risk analysis
|
|
report += "RISK ANALYSIS\n";
|
|
report += "=============\n";
|
|
double total_risk = 0;
|
|
double max_risk_trade = 0;
|
|
int high_risk_count = 0;
|
|
|
|
int trade_count = ArraySize(trades);
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
total_risk += trades[i].risk_percent;
|
|
if(trades[i].risk_percent > max_risk_trade)
|
|
max_risk_trade = trades[i].risk_percent;
|
|
if(trades[i].risk_percent > 2.0)
|
|
high_risk_count++;
|
|
}
|
|
|
|
report += "Total Portfolio Risk: " + DoubleToString(total_risk, 2) + "%\n";
|
|
report += "Maximum Single Trade Risk: " + DoubleToString(max_risk_trade, 2) + "%\n";
|
|
report += "High Risk Trades (>2%): " + IntegerToString(high_risk_count) + "\n";
|
|
report += "Average Risk per Trade: " + DoubleToString(total_risk / MathMax(trade_count, 1), 2) + "%\n\n";
|
|
|
|
//--- Save reports
|
|
string filename = "MultiSource_Report_" + timestamp;
|
|
|
|
//--- Text file
|
|
int handle = FileOpen(m_report_path + 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);
|
|
|
|
m_last_report_time = TimeCurrent();
|
|
Print("MultiTradeReporter: Generated report #", m_report_count);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Analyze trades by source |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::AnalyzeTradesBySource(const ManagedTrade &trades[], string &output)
|
|
{
|
|
output = "TRADES BY SOURCE\n";
|
|
output += "===============\n";
|
|
|
|
//--- Group trades by magic number
|
|
struct SourceGroup
|
|
{
|
|
long magic;
|
|
string name;
|
|
int count;
|
|
double volume;
|
|
double profit;
|
|
double risk;
|
|
};
|
|
|
|
SourceGroup groups[];
|
|
int group_count = 0;
|
|
int trade_count = ArraySize(trades);
|
|
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
long magic = (long)trades[i].magic;
|
|
bool found = false;
|
|
|
|
for(int j = 0; j < group_count; j++)
|
|
{
|
|
if(groups[j].magic == magic)
|
|
{
|
|
groups[j].count++;
|
|
groups[j].volume += trades[i].volume;
|
|
groups[j].profit += trades[i].profit;
|
|
groups[j].risk += trades[i].risk_percent;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!found)
|
|
{
|
|
ArrayResize(groups, group_count + 1);
|
|
groups[group_count].magic = magic;
|
|
groups[group_count].name = GetSourceName(magic);
|
|
groups[group_count].count = 1;
|
|
groups[group_count].volume = trades[i].volume;
|
|
groups[group_count].profit = trades[i].profit;
|
|
groups[group_count].risk = trades[i].risk_percent;
|
|
group_count++;
|
|
}
|
|
}
|
|
|
|
//--- Output grouped data
|
|
for(int i = 0; i < group_count; i++)
|
|
{
|
|
output += "\n" + groups[i].name + " (Magic: " + IntegerToString(groups[i].magic) + ")\n";
|
|
output += " Trades: " + IntegerToString(groups[i].count) + "\n";
|
|
output += " Volume: " + DoubleToString(groups[i].volume, 2) + " lots\n";
|
|
output += " P/L: $" + DoubleToString(groups[i].profit, 2) + "\n";
|
|
output += " Risk: " + DoubleToString(groups[i].risk, 2) + "%\n";
|
|
}
|
|
|
|
output += "\n";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get source name from magic number |
|
|
//+------------------------------------------------------------------+
|
|
string CMultiTradeReporter::GetSourceName(long magic)
|
|
{
|
|
switch((int)magic)
|
|
{
|
|
case 0: return "Manual Trading";
|
|
case 12345: return "Risk Manager EA";
|
|
default:
|
|
{
|
|
if(magic >= 10000 && magic < 20000)
|
|
return "External EA";
|
|
else if(magic >= 80000 && magic < 90000)
|
|
return "Copy Service";
|
|
else
|
|
return "Unknown Source";
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Analyze position correlations |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::AnalyzeCorrelations(const ManagedTrade &trades[], string &output)
|
|
{
|
|
output = "POSITION CORRELATIONS\n";
|
|
output += "===================\n";
|
|
|
|
//--- Get unique symbols
|
|
string symbols[];
|
|
int symbol_count = 0;
|
|
int trade_count = ArraySize(trades);
|
|
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
bool found = false;
|
|
for(int j = 0; j < symbol_count; j++)
|
|
{
|
|
if(symbols[j] == trades[i].symbol)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!found && symbol_count < 20) // Limit to 20 symbols
|
|
{
|
|
ArrayResize(symbols, symbol_count + 1);
|
|
symbols[symbol_count] = trades[i].symbol;
|
|
symbol_count++;
|
|
}
|
|
}
|
|
|
|
//--- Calculate correlations between pairs
|
|
if(symbol_count >= 2)
|
|
{
|
|
output += "\nHigh Correlations (>0.7):\n";
|
|
|
|
// Use a 1D array to simulate 2D array
|
|
double correlations[];
|
|
int corr_size = symbol_count * symbol_count;
|
|
ArrayResize(correlations, corr_size);
|
|
ArrayInitialize(correlations, 0.0);
|
|
|
|
// Helper function to access 2D array as 1D
|
|
#define CORR_INDEX(i,j) ((i)*symbol_count+(j))
|
|
|
|
for(int i = 0; i < symbol_count; i++)
|
|
{
|
|
for(int j = i + 1; j < symbol_count; j++)
|
|
{
|
|
double corr = CalculateCorrelation(symbols[i], symbols[j], 100);
|
|
correlations[CORR_INDEX(i,j)] = corr;
|
|
correlations[CORR_INDEX(j,i)] = corr; // Symmetric
|
|
|
|
if(MathAbs(corr) > 0.7)
|
|
{
|
|
output += symbols[i] + " vs " + symbols[j] + ": " +
|
|
DoubleToString(corr, 3) + "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
//--- Correlation risk warning
|
|
int high_corr_positions = 0;
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
for(int j = i + 1; j < trade_count; j++)
|
|
{
|
|
// Find symbol indices
|
|
int idx1 = -1, idx2 = -1;
|
|
for(int k = 0; k < symbol_count; k++)
|
|
{
|
|
if(symbols[k] == trades[i].symbol) idx1 = k;
|
|
if(symbols[k] == trades[j].symbol) idx2 = k;
|
|
}
|
|
|
|
if(idx1 >= 0 && idx2 >= 0 && idx1 != idx2)
|
|
{
|
|
double corr = correlations[CORR_INDEX(idx1,idx2)];
|
|
if(MathAbs(corr) > 0.8 && trades[i].type == trades[j].type)
|
|
{
|
|
high_corr_positions++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef CORR_INDEX
|
|
|
|
if(high_corr_positions > 0)
|
|
{
|
|
output += "\n⚠️ WARNING: " + IntegerToString(high_corr_positions) +
|
|
" position pairs with high correlation!\n";
|
|
}
|
|
}
|
|
|
|
output += "\n";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate correlation between two symbols |
|
|
//+------------------------------------------------------------------+
|
|
double CMultiTradeReporter::CalculateCorrelation(string symbol1, string symbol2, int period)
|
|
{
|
|
//--- Simplified correlation calculation
|
|
double prices1[], prices2[];
|
|
ArrayResize(prices1, period);
|
|
ArrayResize(prices2, period);
|
|
|
|
//--- Get price data
|
|
for(int i = 0; i < period; i++)
|
|
{
|
|
prices1[i] = iClose(symbol1, PERIOD_H1, i);
|
|
prices2[i] = iClose(symbol2, PERIOD_H1, i);
|
|
}
|
|
|
|
//--- Calculate returns
|
|
double returns1[], returns2[];
|
|
ArrayResize(returns1, period - 1);
|
|
ArrayResize(returns2, period - 1);
|
|
|
|
for(int i = 0; i < period - 1; i++)
|
|
{
|
|
returns1[i] = (prices1[i] - prices1[i + 1]) / prices1[i + 1];
|
|
returns2[i] = (prices2[i] - prices2[i + 1]) / prices2[i + 1];
|
|
}
|
|
|
|
//--- Calculate correlation
|
|
double sum1 = 0, sum2 = 0, sum12 = 0, sum1sq = 0, sum2sq = 0;
|
|
int n = period - 1;
|
|
|
|
for(int i = 0; i < n; i++)
|
|
{
|
|
sum1 += returns1[i];
|
|
sum2 += returns2[i];
|
|
sum12 += returns1[i] * returns2[i];
|
|
sum1sq += returns1[i] * returns1[i];
|
|
sum2sq += returns2[i] * returns2[i];
|
|
}
|
|
|
|
double numerator = n * sum12 - sum1 * sum2;
|
|
double denominator = MathSqrt((n * sum1sq - sum1 * sum1) * (n * sum2sq - sum2 * sum2));
|
|
|
|
if(denominator == 0) return 0;
|
|
|
|
return numerator / denominator;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate CSV report |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::GenerateCSVReport(const ManagedTrade &trades[], const PerformanceMetrics &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
|
|
FileWrite(handle, "Ticket", "Symbol", "Type", "Volume", "Entry", "Current",
|
|
"SL", "TP", "Profit", "Risk%", "RMultiple", "Magic", "Source", "EntryReason");
|
|
|
|
//--- Trade data
|
|
int trade_count = ArraySize(trades);
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
FileWrite(handle,
|
|
trades[i].ticket,
|
|
trades[i].symbol,
|
|
(trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL",
|
|
trades[i].volume,
|
|
trades[i].open_price,
|
|
SymbolInfoDouble(trades[i].symbol, SYMBOL_BID),
|
|
trades[i].sl,
|
|
trades[i].tp,
|
|
trades[i].profit,
|
|
trades[i].risk_percent,
|
|
trades[i].r_multiple,
|
|
trades[i].magic,
|
|
GetSourceName((long)trades[i].magic),
|
|
trades[i].entry_reason); // Changed from 'comment' to 'entry_reason'
|
|
}
|
|
|
|
FileClose(handle);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate HTML report |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::GenerateHTMLReport(const ManagedTrade &trades[], const PerformanceMetrics &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
|
|
string html = "<!DOCTYPE html>\n<html>\n<head>\n";
|
|
html += "<title>Multi-Source Trading Report</title>\n";
|
|
html += "<style>\n";
|
|
html += "body { font-family: Arial, sans-serif; margin: 20px; }\n";
|
|
html += "table { border-collapse: collapse; width: 100%; margin: 20px 0; }\n";
|
|
html += "th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }\n";
|
|
html += "th { background-color: #4CAF50; color: white; }\n";
|
|
html += "tr:nth-child(even) { background-color: #f2f2f2; }\n";
|
|
html += ".profit { color: green; font-weight: bold; }\n";
|
|
html += ".loss { color: red; font-weight: bold; }\n";
|
|
html += ".warning { background-color: #fff3cd; padding: 10px; margin: 10px 0; }\n";
|
|
html += "</style>\n</head>\n<body>\n";
|
|
|
|
//--- Report header
|
|
html += "<h1>Multi-Source Trading Report</h1>\n";
|
|
html += "<p>Generated: " + TimeToString(TimeCurrent()) + "</p>\n";
|
|
|
|
//--- Account summary
|
|
html += "<h2>Account Summary</h2>\n";
|
|
html += "<table>\n";
|
|
html += "<tr><td>Balance</td><td>$" + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + "</td></tr>\n";
|
|
html += "<tr><td>Equity</td><td>$" + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2) + "</td></tr>\n";
|
|
html += "<tr><td>Free Margin</td><td>$" + DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE), 2) + "</td></tr>\n";
|
|
html += "</table>\n";
|
|
|
|
//--- Active trades table
|
|
html += "<h2>Active Trades</h2>\n";
|
|
html += "<table>\n";
|
|
html += "<tr><th>Ticket</th><th>Symbol</th><th>Type</th><th>Volume</th>";
|
|
html += "<th>Entry</th><th>Current</th><th>P/L</th><th>Risk</th><th>Source</th></tr>\n";
|
|
|
|
int trade_count = ArraySize(trades);
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
string pl_class = trades[i].profit >= 0 ? "profit" : "loss";
|
|
html += "<tr>";
|
|
html += "<td>" + IntegerToString(trades[i].ticket) + "</td>";
|
|
html += "<td>" + trades[i].symbol + "</td>";
|
|
html += "<td>" + ((trades[i].type == POSITION_TYPE_BUY) ? "BUY" : "SELL") + "</td>";
|
|
html += "<td>" + DoubleToString(trades[i].volume, 2) + "</td>";
|
|
html += "<td>" + DoubleToString(trades[i].open_price, 5) + "</td>";
|
|
html += "<td>" + DoubleToString(SymbolInfoDouble(trades[i].symbol, SYMBOL_BID), 5) + "</td>";
|
|
html += "<td class='" + pl_class + "'>$" + DoubleToString(trades[i].profit, 2) + "</td>";
|
|
html += "<td>" + DoubleToString(trades[i].risk_percent, 2) + "%</td>";
|
|
html += "<td>" + GetSourceName((long)trades[i].magic) + "</td>";
|
|
html += "</tr>\n";
|
|
}
|
|
|
|
html += "</table>\n";
|
|
|
|
//--- Footer
|
|
html += "</body>\n</html>";
|
|
|
|
FileWrite(handle, html);
|
|
FileClose(handle);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate quick summary |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::GenerateQuickSummary(const ManagedTrade &trades[])
|
|
{
|
|
int trade_count = ArraySize(trades);
|
|
double total_profit = 0;
|
|
double total_risk = 0;
|
|
|
|
for(int i = 0; i < trade_count; i++)
|
|
{
|
|
total_profit += trades[i].profit;
|
|
total_risk += trades[i].risk_percent;
|
|
}
|
|
|
|
string summary = StringFormat("\n=== QUICK SUMMARY ===\n" +
|
|
"Active Trades: %d\n" +
|
|
"Total P/L: $%.2f\n" +
|
|
"Total Risk: %.2f%%\n" +
|
|
"==================\n",
|
|
trade_count, total_profit, total_risk);
|
|
|
|
Print(summary);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Export trade history - additional method |
|
|
//+------------------------------------------------------------------+
|
|
void CMultiTradeReporter::ExportTradeHistory(const ManagedTrade &trades[])
|
|
{
|
|
// This method can be used for exporting closed trade history
|
|
// Implementation depends on your specific needs
|
|
GenerateCSVReport(trades, PerformanceMetrics());
|
|
}
|
|
|
|
#endif // MULTI_TRADE_REPORTER_MQH
|
|
//+------------------------------------------------------------------+ |