Discover expert developed MetaTrader tools that can complement professional solutions.
Why I wrote it
My scalper trades two setups. A bullish order block and the bearish mirror of it. The Strategy Tester gave me one profit factor for both of them. I spent two weeks tuning inputs that applied to each setup equally.
Then I split the trades by setup type. On USDCAD M1 the bullish side had caused 88 percent of the loss. The bearish side was close to flat. The number I needed had been sitting in my own trade history the whole time. I just had no way to read it.
This class reads it.
Recover from drawdowns intelligently with the Auto Recovery Expert Advisor for MT4/MT5. Perfect for hedging strategies. Learn more.
What it gives you
You register your setup types once at startup. Each one gets an id back. That id is added to your magic number base so every order carries its own setup tag from the moment it is sent.
After that the ledger answers three questions for each setup. How many wins and losses. What the net result was after swap and commission. And whether the win rate has earned any trust yet.
That last question is the one I built this for. Three wins from three trades is a 100 percent win rate. It is also what a coin that lands heads 44 percent of the time manages about once in twelve attempts. So the class prints a Wilson score lower bound beside the raw rate and checks it against the breakeven win rate your reward ratio demands. At 1:2 that bar sits at 33.3 percent. A setup only reads as trusted when even its pessimistic rate clears the bar. Early on everything reads "not yet trusted". That is the honest answer when you have twenty trades.
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 goes out.
trade.SetExpertMagicNumber((ulong)ledger.MagicFor(SETUP_BULL));
Fold the position in once it closes.
double net = 0.0; if(ledger.ProcessClosedPosition(posId, setupId, net)) Print(ledger.Report(2.0));
Report()
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
The same report passed to
The counts are wins over losses. So that is 764 trades on the bullish setup and 584 on the bearish one. Both nets add back to the tester's own net loss to the cent. Run that reconciliation on your own output before you trust any ledger including this one. If the per-setup trades do not sum to the tester's trade count then positions are being miscounted and every percentage above that line is worthless.
Three traps it handles for you
Hand written versions of this usually get these wrong. I got two of them wrong myself before this class existed.
Deals are not trades. MT5 history is a list of deals. A position closed in three parts produces three OUT deals. Loop over deals and count each profitable one as a win and a single winning trade becomes three wins. The ledger aggregates by
DEAL_PROFIT
POSITION_TICKET
The one rule you must not break
Registration order is a data format. The setup id lives nowhere except inside the magic numbers of trades that have already closed. Insert a new setup in the middle of the list next month and every historical trade of the setup that used to hold that id silently becomes a trade of the new one. Nothing throws an error. The numbers are simply wrong from then on.
New setups go at the end of the list. If you retire a setup then leave its
What it will not do
It keeps one record per position. An EA that stacks a second entry into the same netting position will credit the whole thing to the first setup. If yours does that it needs a per-deal model instead.
Sixteen setups is the ceiling. Raise
A net result of exactly zero counts as a loss. Scratch trades are rare and treating them as wins is the more flattering error.
ProcessClosedPosition()
And it measures your exits rather than your idea. A setup that reads direction correctly but places its stop badly scores as a bad setup. For deciding what to trade tomorrow that is arguably the right answer. It is not the same as judging whether the idea was sound.
Requirements
MetaTrader 5. No dependencies beyond the standard library. Drop the file in
One last thing. A ledger built on a single in sample backtest measures that backtest. It does not validate a strategy. Out of sample testing on a period you never tuned on is a separate job and this class does not replace it.
— Ali Rajput
Build better strategies with RobotFX professional tools – check them out.
77531