How many trades is a file of fills?
A broker export is a list of fills. A row appears every time some quantity was matched — a partial entry, a partial exit, a stop that filled in two pieces because the book was thin. A trade is a different object: the span between the moment a position leaves flat and the moment it comes back. One trade is often four rows. One row is sometimes two trades.
The definition that resolves it needs no judgement and no timestamp. Take one symbol at a time and track the net position. When it leaves zero a trade opens; when it returns to zero that trade closes; everything in between belongs to it. Three ordinary situations break any reading that skips this step:
- ReversalA single row sells more than the position held. It closes the trade that was open and opens the opposite one. The row belongs to both, and its money belongs only to the first.
- Two at oncePositions in two instruments overlap in the file. They are two ledgers, and their interleaving is not a flat crossing — a grouper watching one combined position invents a trade boundary that never happened.
- Still openThe file ends with a position on. It has no result yet, and averaging it in as a zero is an assertion about a trade that has not finished.
The fill log in this article is constructed, not collected: figures.data.js lays out 34 trades across 2 invented instruments at seed 7314, rounds every price to the tick and then recomputes what those rounded rows are worth. It ships beside this page and prints what it emits when run.
No real contract, broker or firm is described. What one point of a symbol is worth is knowledge the file does not contain.
| 13 | rows in this excerpt |
| 6 | of them reduce the position, so a row-by-row reading calls each one a trade |
| 5 | trades, counting flat to flat |
| 91 | rows in the whole sample, which is 47 results by rows and 34 by trades |
The consequence is arithmetic rather than opinion. Reading the sample flat to flat gives 34 trades, a win rate of 51.5%, an average win of $173.85 and an average loss of $146.88. Reading the same rows one at a time gives 47 results, a win rate of 65.2% — 13.7 percentage points higher — and an average win of $103.53, barely more than half as large.
Neither reading is a mistake in arithmetic. Both add up to the same realised money: $605.50, to the cent, because every closing row's result belongs to exactly one trade whichever way they are grouped. What changes is the denominator, and the three numbers are all quotients.
A file has one total and two of everything else. The win rate is not a property of your trading; it is a property of your trading and your definition of a trade, and the second one is a choice you make in a spreadsheet.
The inflation has a direction, and it is not random. Scaling out of a position banks the piece that is furthest in your favour first, so partial exits manufacture small winners; the remainder carries whatever is left, which on a losing trade is the whole loss and more. A file where every position is taken off in one piece shows no gap at all. A file where the good ones are trimmed and the bad ones are held shows a large one.
What do your own rows say?
Below is the grouper, the matcher and the arithmetic, running in this page. The box holds a sample so that the readouts mean something before anyone types; clear it and paste your own rows over the top. Reduce your export to four fields in file order — symbol, side, quantity, price — and add a line for what one point of each symbol is worth, since the file does not know.
The parser refuses anything that is not exactly four fields, and says how many rows it refused and what the first one was. That strictness is the point. A parser that guesses which column is the price will succeed on a file it has misunderstood, and hand back three numbers with no indication that anything went wrong.
The multiplier, because a symbol is not a contract specification. The stop, because a fills export does not carry the risk you intended, only the money you made. The account balance, because it is not in the file either — which is why every number here is money per trade and none of them is a percentage of anything.
The three numbers, from rows you supply
Replace the sample with your own rows. Nothing is uploaded: this document contains no network call of any kind, and the build refuses to ship one.
To the right, the largest winners come out — the outlier test. To the left, the worst losers do, which is the edit that makes a record look like the system you meant to trade.
Share of the wins dropped from each end before the trimmed average is taken.
%Charged on every contract in and every contract out, so a round turn is two of these. Leave it at nothing if your prices are already net of cost.
Reading the sample.
Readouts are in whatever currency the multipliers are denominated in; the file itself carries prices, not money.
Nothing you paste leaves the browser, and that is a structural claim rather than a promise: this document contains no script, style, font or image loaded from anywhere else, and no code path that can open a network connection. A build gate refuses to publish the page if one appears.
The four controls are the four decisions the rest of this article is about. The first is what a trade is. The second removes results from the extremes, in either direction. The third replaces the average win with a trimmed one. The fourth charges cost per contract per side, which matters here more than it looks: cost is levied on fills, and a scaled entry with two partial exits pays it four times while producing one trade.
Which single trade is your average win?
An average is a claim about a set. When one member of the set is several times larger than any other, the average is mostly a claim about that member, and the usual way to find out is to take it away and look again.
The identity in this section is arithmetic, not simulation, and is reproducible by hand from any list of results. It is asserted on every build against the shipped sample, together with the fact that the median and trimmed substitutions break it — a check that would pass vacuously if they happened to agree.
| $173.85 | average win, whole file |
| $131.59 | with the largest win removed, a fall of 24.3% |
| 28.8% | of gross profit sits in that one trade |
In the sample, 28.8% of all gross profit sits in one trade. Remove it and the average win falls from $173.85 to $131.59, a drop of 24.3%; expectancy per decided trade goes from $18.35 to -$7.64, which is to say the sign of the edge is carried by one row out of 34. Every other removal moves the average by a few dollars.
The instinct at this point is to reach for a robust centre — the median, or a trimmed mean — and there is a real reason not to.
| $605.50 | the file's realised total |
| $605.50 | rebuilt from the mean-based three numbers |
| -$164.33 | rebuilt from the median-based ones |
The drawing makes the arithmetic visible. The median of the wins is $133.75 and the mean of the wins is $173.85, a gap of $40.10 that looks like a fact about the distribution. Take the largest win out and the mean lands at $131.59 — within $2.16 of the median. The gap between the two centres was never a property of the shape. It was one trade.
Expectancy is defined on this site's expectancy page as the win rate times the average win, less the loss rate times the average loss. With arithmetic means in those two slots the expression is not a model of anything: it is the file's own realised total divided by its decided trades, exactly, by cancellation. Multiply it back out and you get $605.50, which is what the file made.
Substitute the medians and the same multiplication returns -$164.33 — a file that lost money, described by the same trades that made $605.50. The trimmed pair returns -$36.67. Neither substitution is a computation error; the median is a perfectly good statistic. It is simply not the input this particular machine takes, because a simulator handed an average win multiplies it by a trade count, and only the arithmetic mean survives that multiplication.
The median is not a better average win. It is a measurement of how much of your record lives in a few trades — and the distance between the two expectancies, $18.35 against -$4.98, is more informative than either number on its own.
That distance is the honest reading of this file: an edge that survives its own arithmetic and does not survive the removal of one trade. A record whose mean and median expectancies nearly agree is telling you something quite different from one where they disagree in sign, and no single summary number can carry that difference.
Are you averaging money, points, or risk?
A fills export contains prices. Prices are not money, and the step between them is a number the file does not carry. In the sample one instrument is worth $2 a point and the other $5, so the same price move is worth two and a half times as much in one as the other. Averaging the price differences as though a point were a unit of money gives an average win of $67.47 against a true $173.85 — and the error is not a constant factor you could correct for later, because it depends on which instruments you happened to trade and in what size.
Can R be recovered from the file?
Not from fills alone. An R-multiple is a result divided by the risk that was actually taken, and the risk taken is the stop distance at entry times the size times the multiplier. An export records what filled, not what you intended; the stop that never filled leaves no row. Any R computed from this file is therefore reconstructed from an assumption, and the assumption is usually that the average loss is one R.
That assumption is worse than it sounds, because it is self-confirming. Define R as the average loss and the average loss becomes exactly one R by construction, whatever the losses actually did. In the sample they run from $68.50 to $203 — the largest is nearly three times the smallest — and a simulator handed one average loss draws every loss at that size. That is not a guess about simulators in general: the engine behind this site sets out in its own FAQ that it draws each trade from a win rate, an average win in R, an average loss in R and a trading cost in R, and states plainly that it uses those averages rather than the full distribution. The spread is discarded at the input, before any simulation has run, and no amount of simulation puts it back. If you want R, the place to record it is at entry, in a journal, not afterwards from a statement.
And percentages?
Averaging percentages of different balances is a different operation from averaging money, and it is not a matter of units. A gain of 2% on one balance and a loss of 2% on a balance twice as large average to nothing as percentages, while costing 2% of the smaller balance as money. The mean of ratios is not the ratio of sums, and an export does not carry the balance at the time of each trade, so whichever you use is a declaration rather than a measurement.
Gross or net?
One last unit question decides whether a cost is charged once or twice. If your export's prices are raw, the results here are gross and a cost term belongs somewhere. If your platform already reports each fill net of commission, the results are net, and handing them to a model that subtracts a cost per trade charges you the same money again. The cost is a separate input precisely so that it can be set; numbers derived by this method from an already-net export belong in it at zero.
Simulated pages on this site carry a trading cost among the trader's statistics, as the engine's FAQ sets out. That is the right default for a hypothetical trader and the wrong one for a reader arriving with a statement whose prices are already net, who would be charged for the same round turn twice. The cost control in the instrument above starts at nothing for that reason.
Which trades did the file never contain?
Everything so far assumes the file is the record. It usually is not. The account that was funded and closed, the two weeks on a demo, the month excluded because it was a different market — each of those is a decision about which trades count, taken before any arithmetic begins, and it moves the answer further than any of the choices above.
The instrument measures it, because removing results from the bottom is the same operation as removing them from the top with the sign reversed. Take the three worst results out of the sample and expectancy per decided trade rises from $18.35 to $40.24, a gain of 119%, with the win rate moving from 51.5% to 56.7%. Take the three best out instead and it falls to -$24.10. Neither edit is visible in the file that results; both are visible in the slider.
Two smaller categories have the same character. A trade that closed exactly where it opened is neither a win nor a loss, and the three-number interface has no slot for it: put it in the wins and the win rate rises, put it in the losses and it falls, exclude it and the trade count no longer matches the file. The sample contains one, and the readouts report it rather than absorbing it. A position still open at the end has the same problem in a stronger form, since its result does not exist yet; one row of the sample is in that state and is excluded and named.
What do three correct numbers still not tell you?
This page makes three numbers correct. It does not make them stable, and those are different properties: a correctly computed average win from 34 trades is still an estimate with a wide interval around it, and a companion draft in this set, on the error bars around a simulated pass rate, is about exactly that. Nothing here says how many trades are enough, because the honest answer depends on the dispersion this article has spent its length measuring.
It also assumes your export is complete and correctly ordered, which for a file assembled by hand from several statements is worth checking before anything else. Rows out of chronological order will match against the wrong lots and produce results that are individually wrong while still summing to the right total — the same invariant that makes the matching convention harmless makes an ordering error hard to see.
And it says nothing about whether the numbers it produces describe your future. That is a question about variance and about the rule set they will meet, and neither of those is in your export. What a win rate and a pair of averages decide once a floor and a daily limit are set beside them is the subject of which rule actually ends an evaluation and of why a profitable trader still blows up. This page has one job before either of those can mean anything, which is to make sure the three numbers you hand them are yours.
Why the win rate is the wrong number defines the expectancy this page computes from your rows. Which rule actually ends an evaluation begins from the three numbers, and inherits whatever went wrong on the way to them.
Which choices in the export still change the three numbers?
Does it matter whether my broker matches first-in-first-out or against the average price?
Not for a completed trade's total, and that is provable rather than conventional. Between leaving flat and returning to flat, the money paid out and taken in is fixed by the fills themselves; no matching rule appears in that sum. What the convention changes is how the total is split across partial exits, which is exactly the number a row-by-row reading uses. So the matching rule is irrelevant to the trade-by-trade reading and decisive for the other one. This page's two independent implementations agree on both, and a build gate asserts the invariant on every trade in the sample.
Is the median the better number to hand a simulator?
No, and the reason is mechanical rather than a matter of taste. A simulator takes an average win and multiplies it by a count of winning trades. Only the arithmetic mean has the property that this multiplication returns the money the trades actually made; substituting the median of the sample's wins turns a realised $605.50 into a predicted -$164.33. The median is worth computing and worth looking at, as a measure of how concentrated the record is. It is not an input to this particular machine.
My export already has a realised profit column. Can I skip the matching?
Yes, for the money — a realised column has already done the lot matching for you. The grouping question is untouched by it, because that column is populated on closing fills, which is precisely the row-by-row reading. You still have to decide which rows belong to one trade. It is also worth establishing whether the column is gross or net of commission before handing the result to anything that subtracts a cost.
How many trades do I need before these three numbers mean something?
This page does not answer that, and the answer is not a fixed number. What it can say is where to look: the wider the spread of your wins and losses, the longer it takes for their means to settle, and this article's own sample is an example of a record whose average win is dominated by a single trade. Correctness and stability are separate problems, and the companion piece on error bars is about the second one.
The fill log on this page is illustrative and constructed by figures.data.js at seed 7314, which ships beside the page and prints every value it emits when run directly. Every number in the prose comes from that generator; every number the instrument shows is computed in the page from the rows in the box and checked on each build against model.js, an implementation that reaches the same results by cash flow and unit expansion rather than by a lot queue. The grouping rule is additionally checked against hand-worked fill sequences in cases.js. No firm, broker or contract is described, and no page on this site publishes a per-firm pass rate.
- Expectancy and the break-even win rate: Why the win rate is the wrong number. Cited, not re-derived — this page computes the inputs that definition takes.
- What the simulator does with those inputs, including that it draws from average values rather than from the full distribution: how the engine works and what it will not claim.
- Terms used here without redefining them, R-multiple among them: the glossary.
- Where the three numbers go next: which rule actually ends an evaluation and why a profitable trader still blows up.
- No source outside this site is cited, because no claim on this page is empirical. The grouping rule, the cash-flow invariant, the expectancy identity and the percentage-base result are each derived in full above, over a file that ships with the page. No broker's export format, no contract specification and no published result is asserted anywhere on it.