JurgestBalla
AboutServicesWorkBlogContact
JurgestBalla

Senior Full-Stack Engineer

ERP Integrations & Legacy Modernization

Tirana, Albania

Navigation

AboutServicesWorkBlogContact

Connect

LinkedInGitHubinfo@jurgest.comB2B projects via Klartech

Legal

Privacy policyImprint

© 2026 Jurgest Balla. All rights reserved.

Built by me ·

Back to blog
Published 19 March 20246 min read

Importing broker CSVs without trusting them

Lessons from building trade imports for a trading journal: detecting the broker, validating every row, and making re-imports safe.

ReactCSVData importFintech

Every broker exports differently

In a trading journal, users import their trades from the broker's CSV export. Every broker has its own columns, date formats, decimal separators and ideas about what a "trade" is. Some split one fill into several rows; some include cancelled orders.

Detect, don't ask

Asking users to pick their broker from a list works badly; they pick the wrong one. Instead, the importer looks at the header row and a few sample rows and scores each known format. Only when no format is confident does it ask.

Validate every row, show every problem

Each format maps rows into one internal shape, validated with a schema. Invalid rows are not silently skipped; the preview shows them with the reason, and the user decides.

const Trade = z.object({
  symbol: z.string().min(1),
  side: z.enum(["buy", "sell"]),
  quantity: z.number().positive(),
  price: z.number().positive(),
  executedAt: z.coerce.date(),
});

Make re-imports safe

Users import the same file twice, or overlapping date ranges. Each trade gets a stable key built from the broker's own identifiers (or a hash of the row when there is none), so a second import updates instead of duplicating.

Preview before commit

Nothing is written until the user has seen the summary: how many trades, which date range, which rows were rejected. Imports that can be undone are imports people trust.