Visualize your Interactive Brokers realized PnL from a Flex CSV. Zero backend, all in your browser.
- Open
index.html(from a built package) or run with Vite (npm run dev/build) - First load shows demo data so you can poke around immediately
- Click "Upload CSV" to visualize your own IBKR Flex CSV
- Deployed on Railway: ibkr-visualizer.up.railway.app
- Smooth cumulative Realized PnL chart with hover tooltips
- Time ranges: 24h, 1w, 1m, all (auto weekly bucketing for long spans)
- Completed Trades view that groups fills within ~15 min sessions
- Orders view for raw fills (chronological)
- Client‑side only: your CSV stays in the browser
Side effect: spreadsheet‑related stress drops by 97%.*
*n=1, caffeinated developer study.
Important: Use "Closed Lots" (or include the Realized P/L fields). This guarantees correct realized PnL.
- Open the IBKR Client Portal and go to Performance & Reports → Flex Queries
- Create a new Activity Flex Query (the plus button)
- In Sections, choose Trades
- Under Options, set Execution to Closed Lots and select these columns:
- Date/Time (DateTime)
- Symbol
- Asset Class
- Currency
- Quantity
- Proceeds
- IB Commission
- Cost Basis
- Realized P/L (or FifoPnlRealized)
- Buy/Sell
- In Delivery Configuration, choose CSV and keep column headers enabled
- At the bottom, set the Date/Time format so the app can parse your CSV correctly:
- Date Format:
yyyy-MM-dd - Time Format:
HH:mm:ss - Date/Time Separator:
, (comma)
- Date Format:
- Save the query and run it (arrow button) → download the CSV → click "Upload CSV" in the app
- ESLint enforces no semicolons per project style
- Demo data is generated on-the-fly for a pleasant first impression
- Privacy: All processing happens locally in your browser. Files are never uploaded to a server.
This is a React + Vite app. Opening index.html from the file system won’t work (blank page) because the modules are served by the dev server. Use Vite:
- Requirements: Node 18+ and npm
- Install deps
npm ci- Start dev server
npm run devOpen the printed URL (default http://localhost:5174).
- Build static files (for hosting on any static host)
npm run build
npm run preview # optional local preview- Static hosting (recommended): Deploy the
dist/folder to any static host (GitHub Pages, Cloudflare Pages, Netlify, Vercel static, NGINX). No backend required. - Railway: either use a Static Site (publish dir
dist) or a Node service withnpm run preview -- --host 0.0.0.0 --port $PORT.
- Use Flex Query → Activity Flex Query → choose Closed Lots (recommended).
- Include: DateTime, Symbol, Currency, Quantity, Proceeds, Commission, Cost Basis, Realized P/L, Buy/Sell.
- Output: CSV → Run → download → Upload in the app.
The app is open source — contributions welcome! → smyth64/ibkr-pnl-visualizer
Yes — we can provide a ready‑to‑run zip so folks can double‑click index.html without Node/Vite:
- Build once:
npm run build-
Zip the
distfolder and attach it to a GitHub Release (Releases → Draft new release → Uploaddist.zip). -
Users download the zip, unzip, and open
dist/index.html— it works offline.
Tip: Add a “Assets: dist.zip” link in the README so it’s easy to find.






