Problem Description
Solution
To calculate the win rate for a specific symbol based on closed trades, you need to iterate through the account history using OrdersHistoryTotal(), select each order with OrderSelect() using MODE_HISTORY, and filter them by the symbol and order type.
Here is a complete MQL4 script that performs this task. You can drag and drop this script onto any chart, and it will print the statistics to the "Experts" tab in the terminal.
MQL4 Script: Calculate Win Rate
//+------------------------------------------------------------------+
//| CalculateWinRate.mq4 |
//| Copyright 2023, MetaQuotes |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property script_show_inputs
//--- Input Parameters
input string TargetSymbol = ""; // Symbol to calculate (Leave empty for current chart symbol)
input int MagicNumber = 0; // Magic Number filter (0 for manual trades/all)
input bool FilterByMagic = false; // Set to true to filter by the MagicNumber above
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
// Determine the symbol to use
string symbolToCheck = TargetSymbol;
if(symbolToCheck == "") symbolToCheck = Symbol();
int totalTrades = 0;
int winningTrades = 0;
int losingTrades = 0;
int breakEvenTrades = 0;
double totalNetProfit = 0.0;
// Get total number of orders in history
int historyTotal = OrdersHistoryTotal();
// Loop through history
for(int i = 0; i < historyTotal; i++)
{
// Select order from history
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
// 1. Filter by Symbol
if(OrderSymbol() != symbolToCheck) continue;
// 2. Filter by Magic Number (if enabled)
if(FilterByMagic && OrderMagicNumber() != MagicNumber) continue;
// 3. Filter by Order Type (We only want Buy and Sell, not Balance operations)
if(OrderType() > OP_SELL) continue;
// Increment total count
totalTrades++;
// Calculate Net Profit (Profit + Swap + Commission)
double netProfit = OrderProfit() + OrderSwap() + OrderCommission();
totalNetProfit += netProfit;
// Determine Win/Loss
if(netProfit > 0)
{
winningTrades++;
}
else if(netProfit < 0)
{
losingTrades++;
}
else
{
breakEvenTrades++;
}
}
}
// Output Results
if(totalTrades > 0)
{
double winRate = ((double)winningTrades / totalTrades) * 100.0;
Print("--------------------------------------------------");
Print("Stats for Symbol: ", symbolToCheck);
Print("Total Closed Trades: ", totalTrades);
Print("Winning Trades: ", winningTrades);
Print("Losing Trades: ", losingTrades);
Print("Break-Even Trades: ", breakEvenTrades);
Print("Total Net Profit: ", DoubleToString(totalNetProfit, 2));
Print("WIN RATE: ", DoubleToString(winRate, 2), "%");
Print("--------------------------------------------------");
}
else
{
Print("No closed trades found for symbol: ", symbolToCheck);
}
}
//+------------------------------------------------------------------+
How It Works
OrdersHistoryTotal(): This function retrieves the total number of records in the account history (including trades, balance adjustments, and cancelled pending orders).OrderSelect(i, SELECT_BY_POS, MODE_HISTORY): We loop through the history index.MODE_HISTORYis crucial here; otherwise, it would look at currently open trades.- Filters:
- Symbol: Checks if
OrderSymbol()matches your input. - Order Type:
OrderType() > OP_SELLexcludes pending orders (likeOP_BUYLIMIT) that were deleted and balance entries (deposits/withdrawals). We only wantOP_BUY(0) andOP_SELL(1). - Magic Number: Optional filter if you want to isolate a specific Expert Advisor.
- Symbol: Checks if
- Net Profit Calculation: The script sums
OrderProfit(),OrderSwap(), andOrderCommission()to determine if the trade was actually profitable in monetary terms. - Calculation: It performs standard division
(Wins / Total) * 100to get the percentage.
How to Use
- Open MetaEditor (F4).
- Create a new Script (File -> New -> Script).
- Name it
CalculateWinRate. - Paste the code above into the window.
- Compile (F7).
- Go back to the MT4 Terminal.
- Drag the script from the Navigator -> Scripts folder onto your chart.
- Check the Experts tab (at the bottom of the terminal) to see the results.
Q&A
Q: Why does the script include Swap and Commission in the profit calculation?
A: A trade might show a gross profit of $5.00, but if the commission was $7.00, the account actually lost money. To calculate a true "Win Rate" based on account growth, net profit is more accurate than gross profit.
Q: Does this include currently open trades?
A: No. The script uses MODE_HISTORY in the OrderSelect function, so it only calculates based on closed positions.
Q: Why do I see "No closed trades found" even though I have history?
A: Ensure your "Account History" tab in the terminal is set to "All History". If it is set to "Last 3 Months" or "Today", OrdersHistoryTotal() will only see those specific records. Right-click anywhere in the Account History tab and select All History.