Skip to content

Run it from source

There is no release yet: the first version, v0.1, is underway (see the roadmap). Its source can already read your exports and write the returns, so you can try it on your own computer. Treat what it writes as a draft to check, not a return to file.

  • Trading 212: the CSV export of your account history.
  • Interactive Brokers (IBKR): an Activity Flex Query in XML (see below for its sections).
  • Trade Republic: the transaction export (CSV), with all transactions. Its dividends are not read yet: a file with one stops both returns and says why.

Export your whole history, from the day you opened the account: each sale is matched against your earliest purchases of the same security first.

In the Client Portal, open Performance & Reports → Flex Queries and add an Activity Flex Query, delivered as XML, with these sections:

Section What to tick
Account Information Account ID and IB Entity
Trades Executions, all fields (not Orders or Symbol Summary)
Corporate Actions All fields
Cash Transactions Dividends, Payment in Lieu of Dividends, Withholding Tax
Financial Instrument Information All fields
Transfers All fields

Keep the general settings at their defaults (date yyyyMMdd). Select every account, closed and migrated ones included, and run the query once per calendar year since you opened the account: IBKR returns at most 365 days at a time.

  • Node.js 24 or newer.
  • pnpm 10: run corepack enable once, and Node provides it.
  • Git, to fetch the source.
Terminal window
git clone https://github.com/jaxtothemax/broker-to-edavki.git
cd broker-to-edavki
pnpm install --frozen-lockfile
pnpm run build
Terminal window
pnpm --dir apps/web build
pnpm --dir apps/web preview

Open the address it prints (usually http://localhost:4173). The build carries the app’s security policy, under which the files you add are read in a background worker whose network and storage functions are removed and which may load only the app’s own files. Nothing is uploaded, and closing the tab forgets them.

pnpm --dir apps/web dev runs the same app for development, without that policy.

Terminal window
node apps/cli/dist/bin.js my-exports/*.csv my-exports/*.xml \
--year 2026 --tax-number 12345678 --out returns/ --payers payers.json

It prints what it read, the estimated tax and every finding, and writes Doh_KDVP_2026.xml and Doh_Div_2026.xml into returns/ when nothing blocks them; a return with nothing on it is not written. The exit code is 0 when nothing blocks, 1 when something does, and 2 for a mistake in the command. Add --json for a report other tools can read.

The JSON report says what became of each return, under returns: written; withheld, when the return is needed but not written (a finding blocks it, a file was refused, or the write failed); or nothingToFile. While any file is refused, both returns are withheld, because a file that was not read may hold the year’s sales or payments; refused says which. The estimates are given in every case, but for a withheld return the figure may change once what stops it is fixed. The plain text says the same on each return’s line.

The JSON report also lists the shares you still hold, under holdings, in two views:

  • accounts: each account’s own position per security, which you can compare with what the broker shows, and the day it is as of: the last day that account’s files cover. An account is named by its broker and a number (ibkr-1), never by its account number.
  • securities: the lots still open across all your accounts, matched first in, first out. These are the lots your next sale will be taxed against. Each lot shows its purchase date, its cost in euro at the Banka Slovenije rate of that day, and nextBucket: the lower tax rate it moves to next and the date it applies from, or null once a lot is exempt. That date is the day after the anniversary, because FURS has not said whether the anniversary itself counts. A security’s asOf is the earliest last day among the accounts that hold it, since after that day one of them may have traded it in a file you did not add.

Market prices are never fetched, so holdings show what you paid, not what the shares are worth. If earlier exports are missing, holdings come out too low. An account’s day can be past the end of the exchange rates the app ships with only as far as its own trades reach, so a cash row dated years ahead does not make every lot look old. Three flags say where a figure may be wrong:

  • transferred: the account’s files move shares in or out, which are not read yet.
  • refusedRows: a row of the account’s files was refused, so its position may be missing it.
  • incomplete: your files sell more of the security than they buy.

If the holdings cannot be worked out, holdings is null and the returns are written as usual.

Brokers do not export a dividend payer’s address, which Doh-Div needs, so give it in a small JSON file, one entry per security (by ISIN):

{
"US1912161007": {
"name": "The Coca-Cola Company",
"address": "One Coca-Cola Plaza, Atlanta, GA 30313, United States",
"country": "US"
}
}

A Slovenian payer also takes "taxNumber", and a foreign one may take its "identificationNumber".

Compare every figure with your broker’s own statements, and read every finding. TaxReporter prepares a return for you to check; it does not file it, and it is not tax advice. If a number looks wrong, please open an issue, without attaching your files.