Vanguard¶
cgt-calc reads a CSV copy of a Vanguard UK Client Transactions Listing. Use the worksheet for a taxable General Account only. Do not include a Stocks and Shares ISA, Junior ISA or Personal Pension: the CSV does not give cgt-calc an account type it can use to exclude tax-advantaged activity.
The importer does not read the Excel workbook directly. Keep that original workbook for your records, but save the complete General Account worksheet as a CSV for cgt-calc.
Export the complete history¶
Export enough history to establish the cost of every investment owned or sold during the tax year. The safest range starts with the account's first transaction and ends today, or at least 30 days after the end of the tax year you are calculating, because later acquisitions can affect UK share matching. See Before you start.
- Sign in to Vanguard UK and open Documents, then the Report Generator.
- Request a Client Transactions Listing for the required period.
- Download the completed workbook. If it contains several account worksheets, select only the taxable General Account.
- Save the entire worksheet as a comma-separated, UTF-8 CSV. Keep both the Cash Transactions and Investment Transactions tables, including their original headings.
Do not substitute an annual statement or Consolidated Tax Certificate. Vanguard says its Consolidated Tax Certificate summarises dividends and tax deducted at source, but does not provide a Capital Gains Tax calculation.
You can compare the expected worksheet structure with the sanitised example. The filename does not matter. Use commas: tab-separated full worksheets are not reliably detected.
Why both tables matter¶
The Cash Transactions table is the primary record when both tables are present. Its Amount is the
cash movement used by the balance check. Ordinary Bought and Sold cash rows already state their
quantities. The important exception is wording such as:
Selling of account investments for payment of Account Fee for the period ...
That cash row omits the investment and quantity, while the matching Investment Transactions row
contains them. The importer joins the rows only when Details and TransactionDetails contain
exactly the same text. Where several investment rows share that text, it picks the one nearest the
cash row's own date and skips the join entirely if none qualifies. It copies the quantity and
derives a unit price from the cash amount, but it does not copy the investment symbol and still
classifies the result as a cash movement rather than a disposal.
Keep the complete, unchanged worksheet so that enrichment is not lost and ticker-renaming events remain available. See Automatic sales to pay fees.
Generate the report¶
For the 2025/26 tax year, run:
cgt-calc --year 2025 --vanguard-file vanguard.csv
--year 2025 means 6 April 2025 to 5 April 2026. Pass the CSV, not the original Excel workbook.
Follow Generate Your First Report to find and check the output.
Run with the balance check enabled. Do not add --no-balance-check merely to bypass an error; first
reconcile the file and any unsupported activity as described under
Troubleshooting.
Supported activity¶
The importer recognises these forms in the Details or TransactionDetails column:
| Exported text or pattern | How cgt-calc handles it |
|---|---|
Bought <quantity> <investment> (<ticker>) |
A GBP purchase |
Sold <quantity> <investment> (<ticker>) |
A GBP disposal |
DIV: <ticker>.<market>... @ <currency> <rate> |
Dividend income using the GBP cash amount |
Reversal of DIV: ... |
A reversing dividend using the exported negative amount |
Cash Account Interest |
GBP interest income |
| Supported deposit, transfer and payment phrases | GBP cash movements used by the balance check |
Text containing Account fee, Account Fee or ETF dealing fee |
GBP cash movements only |
NameChange: <OLD> replaced with <NEW> in Investment Transactions |
A rename between uppercase ticker codes |
For ordinary buys and sells in a full worksheet, the cash table supplies the total amount and the
exported text supplies the quantity and symbol. cgt-calc treats the final text in parentheses as the
symbol; if there is no text in parentheses, it uses the complete investment name. This is a simple
text rule, not validation that the value is an exchange ticker. The importer records Vanguard
account amounts in GBP and does not expose a separate dealing-fee field. For a cash-table trade, it
derives the unit price from the total cash amount and quantity, so any dealing charge already
included in that trade's Amount is folded into the derived price.
Deposit and withdrawal wording is recognised through phrases such as Regular Deposit,
Cash transfer, Deposit via, Deposit for and Payment by. Capitalisation and punctuation can
matter. Most other text stops the import with Unknown action, but Reversal of is stripped before
classification. Only dividend reversals have been validated; a reversed buy or sell can be imported
incorrectly instead of stopping.
By contrast, a separate account-fee or ETF-dealing-fee row only changes the tracked cash balance. cgt-calc does not assign that row to a purchase or disposal as an allowable cost.
Tax information outside the transaction listing¶
The transaction listing is not a complete tax certificate. In particular, it does not supply Excess Reportable Income (ERI). See the Vanguard section of the custom ERI data guide for Vanguard's published reports and the distinction between its traditional funds and ETFs.
Follow the cgt-calc offshore funds guide and check that the bundled ERI data covers the fund and reporting period you need. Vanguard rows do not contain an ISIN, so cgt-calc can attach ERI only when the parsed symbol maps to an ISIN. The bundled translations contain exchange tickers, but not Vanguard's complete fund names.
For a holding whose parsed symbol is a fund name, create an ISIN translation CSV. The symbol must
match the parsed holding name shown in the cgt-calc report, not the complete Details cell. For
example, after confirming that the share class really is the
Vanguard Emerging Markets Stock Index Fund GBP Accumulation share class,
the mapping would be:
ISIN,symbol
IE00B50MZ724,VANEMPA,Emerging Markets Stock Index Fund - Accumulation
The bundled translations already associate that ISIN with VANEMPA. A row in the user file for an
existing ISIN replaces its bundled symbol set, so retain every verified alias on the same row. Do
not copy that ISIN for another share class. Pass your verified mapping when generating the report:
cgt-calc --year 2025 --vanguard-file vanguard.csv \
--isin-translation-file vanguard-isins.csv
This option selects a read/write cache, not a read-only input. cgt-calc may create or rewrite the file when it learns a mapping from a transaction or a successful Open FIGI lookup. Keep a separate copy of manually curated data if you need an immutable record; see Configuration files.
A missing mapping currently produces no warning: ERI for that holding is simply absent. Check the report rather than assuming that bundled ERI data was matched. Some bond-fund distributions are taxed as interest rather than dividends; see Interest fund tickers.
Known limitations¶
- When a file contains both tables, ordinary transactions come from Cash Transactions. An unmatched Investment Transactions row is not imported as an additional transaction; ticker renames are the exception. Compare both tables for missing activity.
- Automatic sales of investments to cover an account fee are currently classified as cash movements, not disposals. They do not reduce the calculated holding or generate a gain or loss.
- Account fees and ETF dealing fees are not assigned to a purchase or disposal as allowable costs.
- Corporate actions other than the supported
NameChangepair are not mapped. A split, merger, conversion, transfer of investments or other unfamiliar row can stop the import or be absent from the cash table. NameChangesupports uppercase ticker-style codes, with an optional dot suffix, rather than fund names. A row such asNameChange: U.S. Equity Index Fund replaced with ...stops withUnknown action.- The dividend reader expects Vanguard's
DIV: ... @ ...text layout. Changed dividend wording or another income type is not mapped merely because it appears in the workbook. Reversal ofis removed from every details string before classification. Only reversing dividends have been validated; a reversal of a buy, sell or another activity can be silently misclassified.- The importer treats every transaction amount as GBP. Foreign-currency dividend text has not been validated and is not converted.
- The final text in parentheses is always treated as the ticker. For example, an investment ending
in
(Accumulation)is assigned the symbolAccumulation, which can silently combine different funds in one holding. - Rows whose number of fields differs from their table header are silently skipped. A malformed or ragged CSV can therefore omit transactions without an error.
- A legacy cash-only table can be calculated, but an investment-only table cannot. Although its rows
parse, the unsigned
Costof a purchase fails the calculator's amount check. Use the complete worksheet with its Cash Transactions table.
Troubleshooting¶
Vanguard CSV file is empty, a header error or UnicodeDecodeError¶
Pass the CSV saved from the General Account worksheet, not the .xlsx workbook, a PDF statement or
the Consolidated Tax Certificate. An .xlsx file is binary and can produce a raw
UnicodeDecodeError rather than a friendly file-type message. Keep the headings unchanged. A usable
export must contain the Date,Details,Amount,Balance Cash Transactions header; retain the
Date,InvestmentName,TransactionDetails,Quantity,Price,Cost Investment Transactions table as well.
The current parser requires a comma-separated UTF-8 file. A tab-separated full worksheet can fail
because cgt-calc chooses the delimiter from the first line only. A byte order mark is harmless in a
full worksheet, where it lands on the title cell, but breaks a legacy cash-only export whose first
line is the header: if an error says that column 1 should be Date but found what appears to be the
same Date, save that file again as UTF-8 without a BOM. Do not manually concatenate rows from
different account worksheets.
Unknown action¶
The error names the unrecognised Details or TransactionDetails text. Compare it with the
original workbook and determine whether it is a trade, income, transfer, fee or corporate action
before changing anything.
Keep the original export unchanged. A name-based NameChange row is unsupported even though a
ticker-based rename is recognised. If the row is another real transaction not listed under
Supported activity, first upgrade cgt-calc using the same method you used to
install it. If it still fails, open a
GitHub issue with your cgt-calc
version, the complete error and a sanitised copy of the row.
Do not assume that every unsupported row raises this error. A row beginning Reversal of can be
misclassified, and a row with the wrong number of fields is skipped; check the source workbook as
described below.
Automatic sales to pay fees¶
If Vanguard sold units to pay an account fee, compare the Cash Transactions row with the matching Investment Transactions row and your statement. Exact matching text enriches the cash movement with the Investment Transactions quantity and a derived price, but the symbol remains empty and no disposal of those units is recorded. Editing either text cell can prevent that enrichment.
Do not rely on the calculated gain or closing quantity until you have added the verified disposal through another supported export or the RAW format, or calculated that event separately. Make sure the disposal appears exactly once and retain the original workbook as evidence.
Transactions are missing without an error¶
Compare the activity and row counts in both CSV tables with the original workbook. cgt-calc silently skips a row whose number of fields differs from its table header, including a short or overlong row created by an incomplete spreadsheet conversion.
Also inspect every Reversal of row. Only dividend reversals have been validated; a reversed buy or
sell can be imported with the wrong action, quantity or amount instead of being rejected. Keep the
original export unchanged and report an unchanged Vanguard row that behaves this way in a
GitHub issue.
Reached a negative balance or Tried to sell not owned symbol¶
Check that the CSV is from the General Account and covers the complete required history, including the deposits that funded purchases and the earlier purchase behind every sale. Also compare the Cash and Investment Transactions tables for transfers, name changes and automatic fee sales.
Use --no-balance-check only after establishing why the cash history cannot reconcile and checking
its completeness another way.
A quantity, ticker, fee or dividend looks wrong¶
Use the complete, unchanged worksheet CSV. Compare the terminal section headed “Portfolio at the end of … tax year” with the Vanguard statement for 5 April. Check each disposal quantity and total against both transaction tables, and reconcile dividends with the Consolidated Tax Certificate and any required ERI. If an investment name ends in parentheses, confirm that the text is a real ticker; cgt-calc otherwise uses it as the symbol and can combine unrelated funds.
Do not upload an unredacted workbook or CSV to GitHub: it can contain account names, holdings, balances and other sensitive financial information.