Export trade history from MT4, IBKR and Binance
11 min read
You have a year or two of trades sitting inside your broker's platform and no way to learn anything from them. So you find the export button, and what comes out is a list of fills: timestamps, sizes, prices, fees and, on most platforms, a column of profit in account currency. No planned stop. No risk. No setup name. Nothing you can group, average or compare.
That file is not a trade log. It is the raw material for one, and the distance between the two is about twenty minutes of work done once.
What a broker export actually is
Your broker keeps records for accounting, not for review. Every row is a transaction it had to settle, which means the file has three properties that will quietly ruin your averages if you import it as-is.
Fills are not decisions. If you scaled into a position in three clips and out in two, the export has five rows. Your journal should have one trade. Import it raw and one decision counts as five trades: your sample size is inflated, your win rate counts pieces instead of decisions, and every per-trade average is computed over fragments, without placing a single extra trade.
The only performance column is the one you cannot compare. Profit in account currency is the number most exports give you, and it is the number that tells you least: a 180-unit win on a trade where you risked 600 is a worse outcome than a 90-unit win on a trade where you risked 30. Currency amounts hide the only variable you controlled, which is why R-multiple exists as a unit at all.
Costs sit in their own rows. Commission, swap and financing are usually separate lines or separate columns. If you ignore them your results are flattering; if you double-count them against an already net profit figure, they are pessimistic. Decide which convention you are using, write it down, and apply it to every trade.
Where the file lives
Menu paths change between platform versions, so treat these as the neighbourhood rather than the address. What matters is the shape of the file you end up with: one row per fill or per closed trade, with timestamp, instrument, direction, size and price.
MetaTrader 4. Open the Terminal panel (Ctrl+T) and go to the Account History tab. Right-click inside it, set the period to All History (the default shows only recent days), then right-click again and choose Save as Detailed Report. You get an HTML statement with one row per closed trade.
MetaTrader 5. The history lives in the Toolbox (Ctrl+T), on the History tab. Right-click to set the period and the view: Deals gives one row per fill, Positions one row per position. Then choose Report and save it as HTML or as Open XML for Excel.
On both platforms you are converting the saved file to CSV afterwards, and the statement holds several sections besides your closed trades: open trades, working orders, balance operations and a summary. Keep only the one section you want (Closed Transactions in MT4; Deals or Positions in MT5, never both) and delete the rest, or you will import rows that are not trades and count the same activity twice.
Interactive Brokers. Two routes. An Activity Statement in CSV covers a one-off pull. For anything you intend to repeat, build a Flex Query with the Trades section selected: you choose the fields, the date range and the format once, and every later run returns the same columns in the same order. That repeatability is worth the extra ten minutes, because a file whose columns move is a file you have to re-map every time.
Binance. Use Trade History, not Order History: under Orders, then Spot Order, the Trade History tab lists what actually executed, while Order History also lists orders that never filled. Recent ranges export straight away; longer ones are generated as a job you download once it is ready. Each request covers at most a year, and Binance caps how many of those statements you can generate a month, so a long history takes several files and some planning. The spot file has no profit column at all, only price, amount and fee per row; profit comes from matching buys against sells. Spot, margin and futures history are separate exports. If you trade more than one of them, label every row with its product before merging, because the same symbol exists in all three and an instrument column alone cannot tell them apart.
The five columns no export contains
Here is the whole problem in one table. The left column is what your broker knows. The right column is what the questions you actually want answered require.
| In the export | Not in the export | Why the answer needs it |
|---|---|---|
| Entry price, exit price, size, timestamps | Planned stop at entry | Without it there is no risk distance, so no R-multiple |
| Profit in account currency | Risk as % of account | The only way two trades from different account sizes compare |
| Instrument | Setup or strategy name | Any "which of my setups pays" question is unanswerable without it |
| Order type | Exit reason (target, stop, manual, time) | Separates a plan working from you overriding it |
| — | Timeframe or session | The grouping that most often turns out to matter |
MetaTrader reports do include an S/L column, but it holds the stop as it stood when the trade closed. If you moved it to breakeven or trailed it, that column shows where the stop ended up, not the risk you took at entry.
Four of those five you can reconstruct for past trades if you kept charts or notes. The fifth, exit reason, is usually gone forever, because nobody remembers in March why they closed a trade early in November. That asymmetry is the argument for recording forward rather than archaeologically — the fields worth recording cost seconds at the time and cannot be recovered later.
Reconstructing R when the file has no risk column
This is the one piece of arithmetic that makes an imported history readable, and it needs nothing but prices.
Take a row from the export: EURUSD short, entry 1.0850, exit 1.0730. Your chart notes say the stop sat at 1.0890.
risk distance = 1.0890 - 1.0850 = 0.0040 (40 pips)
reward distance = 1.0850 - 1.0730 = 0.0120 (120 pips)
R-multiple = 0.0120 / 0.0040 = +3.0R
Now the next row: GBPUSD long, entry 1.2600, stop 1.2580, exit 1.2660.
risk distance = 1.2600 - 1.2580 = 0.0020 (20 pips)
reward distance = 1.2660 - 1.2600 = 0.0060 (60 pips)
R-multiple = 0.0060 / 0.0020 = +3.0R
Both trades are +3.0R. In the export's profit column they look nothing alike — different pip counts, different position sizes, different currencies underneath. In R they are the same trade twice, which is exactly the point: R strips out size and instrument and leaves the only thing that repeats.
Then the second half, which most reconstructions skip. If you risked a fixed 1% of the account on both, each one moved the account about 3%, and the two are comparable end to end. If you risked 1% on the first and 4% on the second, both are still +3.0R — but the second moved the account roughly 12% and carried four times the exposure. The R column is honest per trade; the equity path behind it is not comparable unless risk per trade was consistent.
So when you reconstruct, add two columns, not one: r_multiple and risk_pct. If you have to back out the risk percentage from stop distance and position size, the position sizing calculator runs that arithmetic in the forward direction and is quicker to check against than a spreadsheet formula you wrote at midnight.
My imported history says I averaged 3.85% risk per trade before June 2026, with some trades far above that. Not all of those were typos. I used to revenge trade after losing streaks, or even after a single losing day, and sometimes I risked more than was reasonable. The fix was not a better spreadsheet. It was a rule: 1% per trade, no exceptions. Every month since then averages exactly 1% per trade.
Merging, deduplicating and the stuff that silently corrupts the average
Four failure modes, in the order they usually bite:
- Partial fills counted as trades. Group rows by instrument and a short time window, then collapse each group into one trade with a size-weighted average entry and exit. This is the single largest distortion in a raw import.
- Overlapping date ranges. Two exports pulled on different days almost always share a week. Deduplicate on the broker's fill-level ID (deal, trade or execution ID) if the file has one. An order ID is not enough on raw rows, because one order can fill in several pieces and each piece is a real row. If you merged files from several accounts or products, pair the ID with the account and product, because brokers only promise it is unique within one of them. If the file has no such ID, matching on timestamp, instrument and size is only a guess: two genuine fills can share all three, so flag those matches for review instead of deleting them automatically.
- Demo and test accounts in the same pile. A month of demo trades sized at 10% will dominate every average you compute. Keep them out or tag them so you can exclude them, and never let them into a strategy comparison.
- Account currency changes and conversions. If the account currency changed, or the instrument settles in something else, the profit column is not one unit. This is another reason to work in R and percentages rather than currency.
If you are importing into a tool rather than a spreadsheet, the only features worth caring about here are a preview before the write and the ability to roll the import back — a bad mapping discovered after 1,900 rows have landed is a far worse afternoon than one discovered on the preview screen. Tradexy's CSV import ships with broker templates for MT4, IBKR and Binance plus both of those safeguards, and a direct Notion import if your old log lived there. There is no live broker connection: the export is the hand-off, by design.
Notion held every trade I took and still could not tell me whether I had an edge. Once the history was in a form I could query, the first thing it showed me was not about setups at all. It was volume. From February 2025 to May 2026 I took about 1,900 trades, roughly 120 a month. Since June I have taken 33 in over four months. Seasoned traders all tell you quality beats quantity; I had to learn it the hard way. That was far too many trades for all of them to be real setups. A lot of them were revenge trades. Many others came from a blind urge to trade, without waiting for the setup to be clear.
What a clean import still will not tell you
An imported history is a record of what happened, not a verdict on whether it should have. Four limits worth being honest about before you draw conclusions from a freshly imported file.
Sample size does not improve by importing. Two thousand rows of fills can still be a few hundred decisions, and if you changed how you trade partway through, only the trades after the change describe how you trade now. The arithmetic for how many that needs to be is in how many trades before you know a strategy works.
A regime split invalidates the average. If you moved timeframes, changed risk, or learned a method properly at some point, the combined average is a blend of two different traders and describes neither.
The export has no counterfactual. It cannot show you the trades you did not take, the ones you exited early out of fear, or the setups you talked yourself into. Those are the expensive ones, and they only exist in a record you write at the time.
No amount of history makes a small sample conclusive. It makes it legible, which is different and still worth having.
My 33 trades since June look profitable: +11.7R in total, +0.35R on average. Take July out and the same window is −2.3R. At a 24% win rate that is about eight winners, and two or three of them carry the whole result. The mistake I'd expect, because I'm tempted to make it myself, is to call +0.35R my edge. I take it as a sign, not a verdict. I've built the habit of checking my results and the running total every month, so I know whether I'm still on the right track.
Doing it once, properly
The sequence that saves the second afternoon:
- Pull the export with the widest date range the platform allows, in CSV, with trade-level rather than summary rows.
- Open it and read ten rows before mapping anything. Confirm whether a row is a fill or a trade, and where costs sit.
- Collapse partial fills into decisions.
- Add
stop_price,r_multiple,risk_pct,setupandtimeframeas columns, even if you can only fill them for the recent trades. - Import with a preview, check twenty rows against the platform, and only then compute anything.
- From that point, record the five missing fields at the time of the trade, because this is the last import where they are reconstructable.
The file your broker hands you is an accounting record that happens to contain your decisions. Turning it into something you can learn from is mostly a matter of adding the risk you took, which is the one thing the broker never knew and the only thing you fully controlled.
Weekly Insights
One email a week on measuring trading performance. No account required.