//+------------------------------------------------------------------+
//| EA_FileReporting_Template |
//| Template for MCP file-based reporting |
//+------------------------------------------------------------------+
#property copyright "MCP MT4 Integration"
#property version "1.00"
// File paths for reporting
string StatusFilePath = "mt4_reports\\backtest_status.json";
string ResultsFilePath = "mt4_reports\\backtest_results.json";
// Backtest tracking variables
datetime BacktestStartTime;
int TotalTrades = 0;
double InitialBalance = 0;
double MaxDrawdown = 0;
double CurrentDrawdown = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize tracking variables
BacktestStartTime = TimeCurrent();
InitialBalance = AccountBalance();
// Create reports directory if it doesn't exist
CreateDirectory("mt4_reports");
// Write initial status
WriteBacktestStatus("starting", 0, "Backtest initialization complete");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Write final status and results
WriteBacktestStatus("completed", 100, "Backtest completed successfully");
WriteBacktestResults();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Your trading logic here...
// Update status periodically (every 100 ticks for example)
static int tickCount = 0;
tickCount++;
if(tickCount % 100 == 0)
{
double progress = CalculateBacktestProgress();
WriteBacktestStatus("running", progress, "Processing market data");
}
// Track drawdown
double currentBalance = AccountBalance();
CurrentDrawdown = InitialBalance - currentBalance;
if(CurrentDrawdown > MaxDrawdown)
MaxDrawdown = CurrentDrawdown;
}
//+------------------------------------------------------------------+
//| Calculate backtest progress percentage |
//+------------------------------------------------------------------+
double CalculateBacktestProgress()
{
if(!IsTesting()) return 100.0;
// Estimate progress based on time elapsed
datetime currentTime = TimeCurrent();
datetime testEndTime = StrToTime("2024.01.31 23:59:59"); // Adjust as needed
double totalDuration = testEndTime - BacktestStartTime;
double elapsed = currentTime - BacktestStartTime;
if(totalDuration <= 0) return 0.0;
double progress = (elapsed / totalDuration) * 100.0;
return MathMin(progress, 100.0);
}
//+------------------------------------------------------------------+
//| Write backtest status to JSON file |
//+------------------------------------------------------------------+
void WriteBacktestStatus(string status, double progress, string message)
{
int fileHandle = FileOpen(StatusFilePath, FILE_WRITE|FILE_TXT);
if(fileHandle != INVALID_HANDLE)
{
string jsonStatus = StringFormat(
"{\n"
" \"status\": \"%s\",\n"
" \"expert\": \"%s\",\n"
" \"symbol\": \"%s\",\n"
" \"timeframe\": \"%s\",\n"
" \"progress\": %.2f,\n"
" \"start_time\": \"%s\",\n"
" \"current_time\": \"%s\",\n"
" \"trades_executed\": %d,\n"
" \"current_balance\": %.2f,\n"
" \"current_drawdown\": %.2f,\n"
" \"message\": \"%s\"\n"
"}",
status,
WindowExpertName(),
Symbol(),
PeriodToString(Period()),
progress,
TimeToString(BacktestStartTime, TIME_DATE|TIME_SECONDS),
TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS),
TotalTrades,
AccountBalance(),
CurrentDrawdown,
message
);
FileWrite(fileHandle, jsonStatus);
FileClose(fileHandle);
}
}
//+------------------------------------------------------------------+
//| Write final backtest results to JSON file |
//+------------------------------------------------------------------+
void WriteBacktestResults()
{
int fileHandle = FileOpen(ResultsFilePath, FILE_WRITE|FILE_TXT);
if(fileHandle != INVALID_HANDLE)
{
// Calculate statistics
double totalProfit = AccountProfit();
double profitFactor = 0;
int totalTrades = OrdersHistoryTotal();
int profitTrades = 0;
int lossTrades = 0;
double largestProfit = 0;
double largestLoss = 0;
// Analyze historical orders
for(int i = 0; i < totalTrades; i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
double orderProfit = OrderProfit() + OrderSwap() + OrderCommission();
if(orderProfit > 0)
{
profitTrades++;
if(orderProfit > largestProfit) largestProfit = orderProfit;
}
else if(orderProfit < 0)
{
lossTrades++;
if(orderProfit < largestLoss) largestLoss = orderProfit;
}
}
}
double winRate = totalTrades > 0 ? (profitTrades * 100.0 / totalTrades) : 0;
string jsonResults = StringFormat(
"{\n"
" \"summary\": {\n"
" \"expert\": \"%s\",\n"
" \"symbol\": \"%s\",\n"
" \"timeframe\": \"%s\",\n"
" \"period\": \"%s to %s\",\n"
" \"initial_deposit\": %.2f,\n"
" \"final_balance\": %.2f,\n"
" \"total_net_profit\": %.2f,\n"
" \"absolute_drawdown\": %.2f,\n"
" \"maximal_drawdown\": %.2f,\n"
" \"total_trades\": %d,\n"
" \"profit_trades\": %d,\n"
" \"loss_trades\": %d,\n"
" \"largest_profit_trade\": %.2f,\n"
" \"largest_loss_trade\": %.2f,\n"
" \"win_rate\": %.2f\n"
" },\n"
" \"status\": \"completed\",\n"
" \"completion_time\": \"%s\"\n"
"}",
WindowExpertName(),
Symbol(),
PeriodToString(Period()),
TimeToString(BacktestStartTime, TIME_DATE),
TimeToString(TimeCurrent(), TIME_DATE),
InitialBalance,
AccountBalance(),
totalProfit,
CurrentDrawdown,
MaxDrawdown,
totalTrades,
profitTrades,
lossTrades,
largestProfit,
largestLoss,
winRate,
TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS)
);
FileWrite(fileHandle, jsonResults);
FileClose(fileHandle);
}
}
//+------------------------------------------------------------------+
//| Convert period to string |
//+------------------------------------------------------------------+
string PeriodToString(int period)
{
switch(period)
{
case PERIOD_M1: return "M1";
case PERIOD_M5: return "M5";
case PERIOD_M15: return "M15";
case PERIOD_M30: return "M30";
case PERIOD_H1: return "H1";
case PERIOD_H4: return "H4";
case PERIOD_D1: return "D1";
case PERIOD_W1: return "W1";
case PERIOD_MN1: return "MN1";
default: return "UNKNOWN";
}
}
//+------------------------------------------------------------------+
//| Create directory if it doesn't exist |
//+------------------------------------------------------------------+
void CreateDirectory(string path)
{
// Note: MT4 automatically creates directories when writing files
// This is a placeholder for directory creation logic
}