Back to the collection
Selected work / Tax software live

BrokerTax

Turn an IBKR or DEGIRO export into a reviewable Swiss tax statement—without hiding the warnings.

BrokerTax local import screen with the annual IBKR Activity Flex XML upload and three-step workflow

01 — The brief

Start with the useful tension.

The problem

Private Swiss investors have broker exports but still need to reconcile year-end holdings, cash, income, currency conversion, unsupported events and source evidence before using a tax application. BrokerTax prepares a reviewable eSteuerauszug and keeps tax advice and filing submission outside the product.

The audience

Private individuals in Switzerland preparing one tax-year output from one Interactive Brokers account or one DEGIRO account; Interactive Brokers is the supported path and DEGIRO is explicitly beta.

My contribution

Independently built the owner-approved BrokerTax product: the shared import, reference-data, warning/reconciliation, lifecycle, filing-artifact and multilingual web implementation powering both the retained local tool and the launched hosted MVP.

02 — Capability ledger

What exists, what is next.

A plain-language status check, so a polished surface never implies more than the work supports.

Implemented

08
  • IBKR Activity Flex XML import

    Accepts one structurally valid annual Interactive Brokers Activity Flex XML report, parses account information, cash, trades, positions, fees, transfers, option lifecycle rows and corporate actions, and preserves unsupported source rows for review.

  • DEGIRO paired CSV import

    Parses a matching DEGIRO Account.csv activity export and year-end Portfolio.csv snapshot for one declared tax year, normalizes supported English, German, French and Italian descriptions, and fails rather than guessing unknown activity.

  • Warning-first review cases

    Builds a server-owned review case with totals, filing identity, compatibility status, warnings, controlled correction targets, explicit source-row dispositions and a final readiness summary. Ordinary tax and reference warnings remain reviewable; explicit filing blockers produce review-only output.

  • Official reference data and CHF provenance

    Resolves public ESTV/ICTax currency, security and BTC/ETH reference values, caches immutable content-addressed snapshots, and records fallback provenance for direct CHF conversion, IBKR triangulation, broker marks, manual values or unresolved zero values.

  • Options, bonds and lifecycle evidence

    Normalizes supported listed equity, ETF and index options plus ordinary bonds, preserving signed source-order events, linkage, valuation evidence and eligibility. Supported option lifecycle events, bond income/redemptions/maturities and the narrow foreign pure-difference IUP subset are fail-safe; unresolved or unsupported holding changes remain visible and can block filing.

  • Filing and review artifact package

    Generates a provider-specific eSteuerauszug PDF with embedded eCH-0196 XML and eCH-0270 barcode carrier, alongside a separate review PDF, reconciliation CSV/JSON and reproducibility manifest. Content or technical blockers return a review-only ZIP rather than an invalid filing artifact.

  • Independent browser and filing-PDF languages

    The browser review UI and filing PDF support English, German, French and Italian independently; a new local case defaults its filing language to German while review and reconciliation artifacts retain canonical English/structured data.

  • Local privacy boundary and hosted guest flow

    The local tool binds to loopback, injects a per-launch session token, keeps cases in process memory and exposes redacted support bundles. The hosted MVP adds guest ownership, temporary case handling, intake controls, server-owned Checkout and verified fulfillment while reusing the same browser and filing engine.

Planned

00

Nothing recorded here yet.

Unverified

00

Nothing recorded here yet.

03 — Design decisions

The reasoning stays in the room.

01One provider and one account per output

Keeping IBKR and DEGIRO cases separate avoids silently combining heterogeneous broker semantics and preserves a direct comparison between each generated statement and its source export.

02Share one normalized engine across local and hosted surfaces

The retained local tool and hosted MVP use the same import, review and filing pipeline while the hosted adapter adds guest ownership, capacity and payment boundaries at the HTTP edge.

03Warnings remain visible instead of silently blocking or disappearing

Tax-year mismatches, missing reference matches, unsupported assets, reconciliation differences and ambiguous classifications remain in the review artifacts, while only explicit filing-eligibility blockers suppress the filing PDF/XML.

04Keep the filing document clean and diagnostics separate

The user-facing filing PDF carries supported filing content, while fees, warnings, exclusions, mutation provenance, reconciliation commentary and source detail stay in review and reconciliation artifacts.

05Pin reference snapshots and retain mechanical provenance

A case stays tied to the values used for its review until the user explicitly refreshes; every conversion can identify the ESTV/ICTax, broker, manual or unresolved source without asserting tax-authority applicability.

06Fail closed on unresolved lifecycle evidence

Signed position effects, multipliers, linked option/underlying legs, bond/IUP evidence and holding-changing corporate actions are retained for review; the engine does not invent a liability or infer semantics from free text when the evidence is incomplete.

07Make the local privacy boundary explicit

Loopback binding, a per-launch browser token, Host/Origin checks, in-memory cases and redacted support diagnostics keep the local workflow inspectable without broker credentials, cloud accounts or financial-data request logs.

05 — A short walk-through

See the shape of the interaction.

Capture storyboard

Review an anonymized IBKR export and generate a local filing package

0:30
Storyboard · recording not supplied
  1. Start at the local BrokerTax import screen on loopback with the anonymized IBKR Activity Flex XML staged and the isolated offline cache enabled.
  2. Upload the XML and enter the capture-only identity Sample Investor; start the free review without using production or a hosted session.
  3. Show the totals, compatibility badge, warning-first review, controlled correction detail, option lifecycle ledger and reconciliation dispositions; do not apply a tax override.
  4. Check the end-user-responsibility confirmation, select the filing language if desired, and generate the local ZIP; do not open hosted Checkout or send an email.
  5. End on the local package-download state, with the generated eSteuerauszug and separate review/reconciliation artifacts available for inspection.

The materials

Built with care.

Stack
  • Python 3.11+
  • Python standard-library HTTP server
  • Vanilla HTML/CSS/JavaScript browser frontend
  • lxml
  • ReportLab
  • pypdf
  • Pillow
  • zxing-cpp
  • Java 17+ Macro PDF417 helper
  • eCH-0196 v2.2.0
  • eCH-0270 v1.0.0
  • Caddy hosted edge