Reads an encrypted MT5 snapshot, renders a P&L dashboard in the browser.
ββββββββββββββββ writes ββββββββββββββββββ reads ββββββββββββββββ
β mt5-pnl- β βββββββββΊ β snapshot.json β ββββββββΊ β mt5-pnl-cli β
β exporter β β .gz.age β β mt5-pnl-ui β
β β β (the contract) β β (this repo) β
ββββββββ¬ββββββββ ββββββββββββββββββ ββββββββββββββββ
β² MT5 deal history
ββββββββ΄ββββββββ
β Windows host β
ββββββββββββββββ
The exporter runs on the Windows host where MT5 lives and writes one age-encrypted file. This app runs in a browser β any OS, no install β decrypts that file in memory, and renders the same figures as mt5-pnl-cli, visually.
- Self-hosted, nothing leaves the machine. The app is a static bundle;
once loaded it makes no network requests at all. This is enforced, not
just promised: the built page ships a Content Security Policy with
connect-src 'none', so the browser refuses any fetch, XHR, or WebSocket the code might attempt. Verify it yourself β view-source the page and look for theContent-Security-Policy<meta>tag, or open DevTools' Network tab, load a snapshot, and confirm nothing appears after the initial asset load. - One file in, a dashboard out. Decryption, decompression, and aggregation all happen client-side; the decrypted snapshot exists only in the tab's memory.
- Semantics mirror the CLI. Same net P&L decomposition, same mixed-currency guard, same UTC bucketing β see Semantics.
The hosted build is at https://tanem.github.io/mt5-pnl-ui/ β open it and pick a snapshot.
To self-host, build and serve the static output from any web server:
npm ci
npm run build
npx serve dist # or any static file serverThe File System Access API (used for the one-click reopen described
below) requires a secure context β https:// or http://localhost. A
plain file:// open works for the drag-and-drop and file-picker paths
but not for reopen.
Each session you provide the snapshot.json.gz.age file written by
mt5-pnl-exporter and its decryption passphrase β drag-and-drop, a file
picker, or (Chromium browsers only) a saved file handle:
- What's persisted: on Chromium, the File System Access API file handle is saved in IndexedDB, so a returning visit offers a one-click "Reopen " button (re-prompting for read permission as the browser requires).
- What's never persisted: the passphrase, and the decrypted snapshot contents. Both live in memory only, for the life of the tab.
- Firefox and Safari don't implement the File System Access API, so they fall back to drag-and-drop or the standard file-picker input β the reopen shortcut just isn't offered.
- Overview β headline statistics (net P&L, win rate, profit factor, max drawdown, trade count, average win/loss, costs), a cumulative net P&L curve, and monthly/last-30-days bar charts. Also shows lifetime account returns (deposited, withdrawn, floating, profit, percentage gain) per currency group, affected by the account filter only.
- Calendar β a month grid with one cell per trading day, given a flat colour wash by net P&L sign, plus a week-total column and a running month total.
- Trades β closed deals, open positions, and cash flows in sortable, virtualised tables (closed deals also carry a computed net column).
- Strategies β the same summary statistics as Overview, broken down per account or per magic number, each row with an equity sparkline.
Every view respects the global filter bar (accounts, date range, symbol, magic) and, where accounts in scope span more than one currency, renders one section per currency rather than combining them (see Semantics).
Figures mirror mt5-pnl-cli β see its README Notes for the definitions this app uses without restating them:
- Net P&L components (
trade_profit + commission + swap + fee) - Win / loss / breakeven classification
- Max drawdown on the realised P&L curve, not account equity
- UTC day/week/month bucketing
- The mixed-currency guard β figures are never summed across account currencies; this app renders one section per currency instead of suppressing the combined view
schema/snapshot.schema.json is vendored
from exporter release schema/EXPORTER_TAG
(currently v1.0.4). The app accepts the same major schema version and
any minor at or below its own, and rejects anything else with a message
naming both versions.
Issues and PRs welcome β see CONTRIBUTING.md. For security reports, see SECURITY.md.
