C Setup Ledger: Per-Setup Win Rate Analysis for Expert Advisors
Info
The C Setup Ledger: Per-Setup Win Rate Analysis for Expert Advisors is a Expert Advisor for MetaTrader 5 that why i wrote itmy scalper trades two setups: a bullish order block and its bearish mirror. The Strategy Tester initially provided a single profit factor for both, leading to two weeks of tuning inputs that applied to each setup equally.
Usage
This tool is typically used for automated trading on major forex pairs and gold.
Platform
This Expert Advisor works exclusively on MetaTrader 5 (both build 600+ and newer versions).
Setup
Place the downloaded file in MQL5/Experts folder via File ? Open Data Folder in MetaTrader 5.
How to Install and Use C Setup Ledger: Per-Setup Win Rate Analysis for Expert Advisors
1. Installation: Open the "File" menu, select "Open Data Folder," navigate to MQL/Experts, paste your file, and restart the terminal.
2. Activation: Drag the EA from the Navigator onto a chart, ensure "Allow live trading" is checked in the Common tab, and verify the AutoTrading button is green.
3. Optimization: Right-click your chart, choose "Expert List," click "Properties" to adjust inputs, and save your preferred setup as a set file for future use.
4. Maintenance: Regularly check the "Experts" tab in the terminal window to monitor trade logs and potential execution errors.
Frequently Asked Questions
Q: Why is my EA not opening trades? A: Check the "AutoTrading" button, ensure "Allow live trading" is enabled, and verify your broker allows automated trading on your account type.
Q: Can I run multiple EAs on one chart? A: No, each chart can only host one active EA; however, you can open multiple charts for different currency pairs to run several EAs.
Q: What does the "smiley face" icon mean? A: A smiley face in the top-right corner of the chart indicates the EA is successfully running; a frowny face means it is disabled.
What this tool does
Why I wrote itMy scalper trades two setups: a bullish order block and its bearish mirror.
Typical Use Case
This Expert Advisor excels in automated trading and technical analysis on MetaTrader 5.
Compatible Platform & Setup
This Expert Advisor works on MetaTrader 5. Place the file in the MQL5/Experts folder and restart the terminal.
Description & Settings
Related: testinator for testing massive combinations of trade setups - another powerful expert for MetaTrader 5 traders.
Why I wrote itAlso recommended: EXP SMI Correct - similar expert with strong performance on MetaTrader 5.
My scalper trades two setups: a bullish order block and its bearish mirror. The Strategy Tester initially provided a single profit factor for both, leading to two weeks of tuning inputs that applied to each setup equally.
After separating trades by setup type, I discovered that on USDCAD M1, the bullish side accounted for 88 percent of the losses, while the bearish side was nearly flat. The crucial data I needed was already in my trade history; I just lacked a way to access and interpret it.
This class provides that capability.
What it gives you
You register your setup types once at startup, and each is assigned a unique ID. This ID is incorporated into your magic number base, ensuring every order carries its setup tag from initiation.
Subsequently, the ledger answers three key questions for each setup: the number of wins and losses, the net result after swap and commission, and whether the win rate has achieved a level of statistical trust.
The trust assessment is a primary feature. A 100 percent win rate from three trades, for instance, is statistically similar to a coin landing heads 44 percent of the time about once in twelve attempts. Therefore, the class prints a Wilson score lower bound alongside the raw win rate and compares it against the breakeven win rate required by your reward ratio. At a 1:2 reward-to-risk ratio, this threshold is 33.3 percent. A setup is only considered trusted when its pessimistic win rate (the Wilson lower bound) clears this bar. Initially, most setups will read as 'not yet trusted,' which is an accurate reflection when you have only a limited number of trades, such as twenty.
Using it
#include
<CSetupLedger.mqh>
CSetupLedger ledger;
int
SETUP_BULL, SETUP_BEAR;
int
OnInit()
{
ledger.Init(552001); // your magic base
SETUP_BULL = ledger.Register("Bullish OB"); // id 0 -> magic 552001
SETUP_BEAR = ledger.Register("Bearish OB"); // id 1 -> magic 552002
ledger.RebuildFromHistory(); // read the record off the account
Print(ledger.Report(2.0)); // 2.0 = reward-to-risk ratio
return INIT_SUCCEEDED;
}
Stamp the setup onto the trade before the order is sent.
trade.SetExpertMagicNumber((ulong)ledger.MagicFor(SETUP_BULL));
Record the position's closure.
double
net = 0.0;
if(ledger.ProcessClosedPosition(posId, setupId, net))
Print(ledger.Report(2.0));
The Report() function returns a single block of text, usable with both Print() and Comment(). Here is a sample report from my USDCAD M1 trading:
Per-setup ledger (breakeven win rate at 1:2.0 = 33.3%)
---------------------------------------------------------------------
Bullish OB 235/529 raw 30.8% wilson 27.6% net -5819.94 not yet trusted
Bearish OB 191/393 raw 32.7% wilson 29.0% net -811.42 not yet trusted
Displaying the same report using Comment() places it in the chart corner during EA operation. The box on the bar indicates the entry label, showing the setup's record before the trade was initiated. In this example, the panel shows 4 wins and 6 losses, a raw rate of 40 percent, and a Wilson lower bound of 16.8 percent. With ten trades, the verdict remains 'not yet trusted,' which is the intended behavior.
The win/loss counts represent wins over losses. This amounts to 764 trades for the bullish setup and 584 for the bearish setup. The net results for both setups precisely reconcile with the Strategy Tester's overall net loss. It is crucial to perform this reconciliation on your own output to ensure accurate trade counting; any discrepancy may render the calculated percentages invalid.
Three common pitfalls it addresses
Manual implementations often err in these areas. I encountered two of these issues myself before developing this class.
Deals versus trades: MT5 history logs deals, not trades. A position closed in three parts generates three OUT deals. Iterating through deals and counting each profitable one as a win can inflate the win count for a single trade. This ledger aggregates by DEAL_POSITION_ID, ensuring a partial close is counted only once.
Profit calculation: DEAL_PROFIT alone does not represent the net result, as swap and commission are in separate fields. While the impact might be cosmetic for a swing EA, for a scalper, these charges can determine profitability. A trade with a 3 USD price movement gain but a 4 USD commission is a net loss. The ledger correctly sums profit, swap, and commission.
Position identifiers: POSITION_TICKET is not always the same as POSITION_IDENTIFIER. HistorySelectByPosition() requires the identifier. While they often hold the same value in a netting account, this can cause issues in hedging accounts or during partial closes, leading to empty selections and no error messages.
The one rule you must not break
The registration order defines the data format. The setup ID exists only within the magic numbers of closed trades. If you insert a new setup in the middle of the list in the future, all historical trades previously associated with that ID will silently be reassigned to the new setup, resulting in incorrect data without any error.
Always add new setups to the end of the list. If you retire a setup, leave its Register() call in place to maintain the ID's integrity. A brief comment above the registration block indicating its retirement is recommended.
What it will not do
It maintains one record per position. An EA that adds a second entry to an existing netting position will attribute the entire position to the first setup. Such EAs would require a per-deal model instead.
The class supports a maximum of sixteen setups. You can increase this limit by modifying SETUP_LEDGER_MAX if needed. However, sixteen setups on a single account may lead to numerous small samples, which the Wilson column will reflect.
A net result of exactly zero is counted as a loss. Scratch trades are infrequent, and classifying them as wins is a more optimistic, and potentially misleading, error.
ProcessClosedPosition() replaces the global history selection as it internally calls HistorySelectByPosition(). Avoid calling it within your own history loop without reselecting the history afterward.
The class measures exits rather than the initial trading idea. A setup that correctly identifies market direction but has a poorly placed stop loss will be penalized as a bad setup. While this may be the right metric for deciding future trades, it does not assess the soundness of the original trading idea.
Requirements
MetaTrader 5. No dependencies beyond the standard library. Place the file in the MQL5/Include/ directory and include it. Written and tested on build 6190 (as of 2026).
One final note: A ledger built on a single in-sample backtest reflects that specific backtest's performance. It does not validate a strategy's overall robustness. Out-of-sample testing on data not used for tuning is a separate, essential process that this class does not replace.
You may also like: MQL5 Wizard: Trading Signals with Meeting Lines and RSI Confirmation - excellent alternative for expert users on MetaTrader 5.
Source Code
#ifndef __CSETUP_LEDGER_MQH__
#define __CSETUP_LEDGER_MQH__
#define SETUP_LEDGER_MAX 16
struct SetupStat
{
string name;
int wins;
int losses;
double netProfit;
};
.......
⚠ Limitations & Risk Warning
- This tool is provided for educational and testing purposes only.
- Past performance does not guarantee future results.
- Trading involves substantial risk of loss. Use on a demo account first.
- Results may vary depending on market conditions, broker, and settings.
- We recommend thorough backtesting and forward testing before using with real funds.