Skip to content
← All posts
7 min readBy

Why the exchange CSV gets crypto CGT wrong

An exchange export records what the exchange's database did, not what happened for CGT. Where it misleads, and what a crypto schedule needs before review.

  • Crypto
  • CGT
  • Working papers
A laptop on a desk at night showing a long spreadsheet of rows, a phone with a trading app beside it and a mug, all text blurred.

The email arrives in the second week of October. No greeting to speak of, one attachment: transactions_export_all.csv, 4,112 rows. The body says it's all in there, the exchange does the tax stuff.

You open it. Columns for timestamp, type, asset, quantity, a price in US dollars, a fee in something else, and a notes field that says "Converted" on a few hundred rows. You filter on the sells, sum the proceeds, and get a number that would make the client the most successful amateur trader in the postcode. They are not. They mentioned in March that they were "down a bit".

The number is wrong, and the file is not lying. It is answering a different question.

An exchange export is a record of what the exchange's database did. A CGT schedule is a record of what the taxpayer did. Most of the time those line up well enough that nobody notices they are different things. On crypto files they come apart often enough that the CSV should be treated as evidence to be reconciled, never as a schedule that just needs summing.

What the ATO counts, and what the file counts

The ATO's page on how to work out and report CGT on crypto lists when a CGT event may happen for crypto held as an investment: trading, exchanging or swapping one crypto asset for another, converting it to Australian or foreign currency, and using it to buy goods or services. Its page on crypto-to-crypto swaps puts it more plainly: when you swap one crypto asset for another, you dispose of one CGT asset and acquire another.

So the question for every row is simple to state. Was something disposed of, when, for how much in Australian dollars, and what did it cost?

The CSV doesn't organise itself around that question. It organises itself around ledger entries — money in, money out, a balance moving on an internal account. Four places where the two drift apart are worth knowing by sight.

One conversion, two rows

Some exchange exports write a single conversion as two rows: one row where the old coin leaves, one where the new coin arrives. Each row carries a dollar value. Each row looks, on its own, like a trade.

Import that file naively and the conversion gets counted twice — once as a disposal, and again as a second transaction with proceeds of its own. The disposals come out overstated, sometimes by a lot, and nothing about the schedule looks broken. It totals. It even reconciles, if the thing you reconcile it against is the same file.

That last point is the one worth dwelling on. We found this one the unglamorous way, in our own crypto ledger, where our own tie-out checked the ledger against the export it had been built from and passed. Of course it passed. It was a file agreeing with itself — the problem we wrote about in why working papers come back from review, in a newer costume.

A coin rolling towards a navy archway, with two identical blank ledger cards standing on the far side, one outlined in coral.
One conversion, two rows. Each one looks like a trade on its own.

Coins that arrive with no history

A deposit from another platform or a private wallet lands on the exchange with a quantity and a date, and nothing else. The exchange never saw it bought. So when it is later sold, the export has a disposal and no cost base, and a lazy import fills that gap with zero.

A zero cost base doesn't look like a missing number. It looks like a very profitable trade.

The ATO's page on keeping crypto records is clear that each crypto asset is a separate CGT asset and that the records have to cover each one: receipts when you buy, transfer or dispose, the date, what the transaction was for and who the other party was, and the value in Australian dollars at the time. When the cost of a parcel lives on a different platform's history, that history is a document to chase. It is not a figure to assume.

The honest state for that line, until the record turns up, is outstanding — written on the schedule, in the cell, where a reviewer will see it. Not blank, and never zero.

Withdrawals that look like sales

Coins leaving an exchange for a wallet the client owns look, in the export, almost exactly like coins leaving for someone else. The row says "withdrawal", a quantity, an address. What it doesn't say is whose address.

This is a question for the client, and it is a better question than most, because they can usually answer it in a sentence. Asked, it costs one line in an email. Assumed either way, it quietly moves a figure — and the next time those coins turn up somewhere else, the schedule has already decided something about them that nobody actually decided.

Prices in the wrong currency

Most export files price a trade in the currency of the pair: US dollars, or another coin. The ATO wants the value in Australian dollars at the time of each transaction. That conversion is a step, it has a source, and the source belongs on the schedule — which rate, from where, for which moment. A column of AUD figures with no indication of how they got to be AUD is exactly the kind of figure a reviewer stops on, because it has been through a transformation that isn't visible.

Fees are the same problem in miniature. They are often a separate row in a separate asset, and whether they belong in the cost base, the proceeds, or neither is a treatment question that shouldn't be settled by which column the importer happened to read.

Two blank ledger cards joined by a curved navy arrow, with a small coral tag hanging from the middle of the arrow.
The conversion to Australian dollars is a step with a source. The source belongs on the schedule.

What a reviewer wants instead

A crypto schedule that survives review looks less like the export and more like a register:

  • One line per disposal, not one line per export row. A conversion is one event, whatever the file did with it.
  • Each line traceable to the rows it came from. Export row numbers or transaction ids, so anyone can go from the line back to the file without re-running the import in their head.
  • The parcel it came out of, and how that was decided. Which purchase the disposed units are matched against is a method, and a method should be stated once, on the face of the paper, not left implicit.
  • An AUD value with its source, for proceeds and cost.
  • Every gap named. An unknown cost base is written as outstanding, and the question that would close it is on the query list.

And one reconciliation that does not come from the same file: units in, units out, units held, tied to the platform's own statement of closing balances. If the schedule says the client should be holding a certain quantity of a coin at year end and the platform says something else, one of them is wrong, and the difference is the most useful line in the whole workbook. The count is independent of the prices, which is exactly why it catches the double row: a conversion counted twice can't also leave the balances right.

It is also worth remembering that the ATO is not relying on the client's file either. Its crypto asset data-matching program matches what is reported in returns against transaction and account data from designated service providers. The exchange's own view of the client's year will be seen by someone. It's better if that someone is you, first.

A set of balance scales with a small stack of coins on one side and a stack of ledger cards on the other, level with each other.
Units in, units out, units held. A count that doesn't depend on the prices catches what the prices hide.

Where we sit in this

Full disclosure: this is a problem we work on, so weigh the next paragraph accordingly.

BeforeMay reads an exchange export into a ledger of disposals before the working paper is built, with each line linked back to the file it came from. A cost base it can't find stays on the paper as outstanding, and the CGT figures that depend on it are marked provisional rather than quietly finished. The two-row conversion above is one of the things we found in that ledger, which is part of why this post exists. The layout of the CGT and investment schedules is on our working paper templates page, and what we do with client files is on the FAQ.

None of which changes the job. The export is evidence. The schedule is the argument. Someone still has to read the one to write the other.