Skip to content

tanem/mt5-pnl-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

mt5-pnl-cli

Licence ci coverage

Query MT5 P&L from an encrypted mt5-pnl-exporter snapshot. One static binary β€” no daemon, no database, no third-party service.

   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  writes   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  reads   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ mt5-pnl-     β”‚ ────────► β”‚ snapshot.json  β”‚ ───────► β”‚ mt5-pnl-cli  β”‚
   β”‚ exporter     β”‚           β”‚ .gz.age        β”‚          β”‚ (this repo)  β”‚
   β”‚ Windows host β”‚           β”‚ synced via     β”‚          β”‚ macOS, Linux β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚ Dropbox etc.   β”‚          β”‚ or Windows   β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The exporter runs on the Windows host where MT5 lives and writes one encrypted file. This CLI runs wherever you are, decrypts that file in memory, and prints P&L and account tables β€” or JSON for scripts and AI agents.

Contents

Why

  • Self-hosted. Your trading data never touches a third-party dashboard. The snapshot is yours; this binary reads it locally.
  • One file in, answers out. No config file. Point it at the snapshot once (env var or flag) and mt5-pnl-cli pnl just works.
  • Agent- and script-friendly. --json emits stable machine-readable output, and warnings go to stderr so they never corrupt a pipeline. An agent like Claude Code can turn "show me monthly P&L for Q1" into mt5-pnl-cli pnl --from 2026-01-01 --to 2026-03-31 --by month --json.
  • Secrets stay in the keychain. The decryption passphrase lives in the OS keychain only β€” there is deliberately no env var or flag for it.

Install

Download a binary from Releases (darwin/linux/windows, amd64/arm64, with checksums.txt), or build with Go:

go install github.com/tanem/mt5-pnl-cli@latest

Quick start

# once: store the snapshot passphrase in the OS keychain. Use the SAME
# passphrase you gave mt5-pnl-exporter's set-encryption-passphrase.
mt5-pnl-cli set-passphrase

# once: tell the CLI where the synced snapshot lives
export MT5_PNL_SNAPSHOT=~/snapshots/mt5.json.gz.age

mt5-pnl-cli pnl          # last 30 days, grouped by week
mt5-pnl-cli accounts     # balances, equity, freshness

Demo

Per-account and combined (ALL) rows per period, with a summary line:

$ mt5-pnl-cli pnl --from 2026-01-01 --to 2026-01-31
PERIOD      ACCOUNT     P&L   TRADES  WINS  LOSSES
2026-01-05  Trend EA    5.00  2       1     1
2026-01-05  Scalper EA  0.00  1       0     0
2026-01-05  ALL         5.00  3       1     1
2026-01-12  Trend EA    5.00  1       1     0
2026-01-12  ALL         5.00  1       1     0

Total P&L: 10.00  Trades: 4  Win rate: 50.0%  Profit factor: 3.50  Gross profit: 14.00  Gross loss: -4.00
$ mt5-pnl-cli accounts
LOGIN  LABEL       CURRENCY  BALANCE  EQUITY   LAST SUCCESS          LAST ERROR
111    Trend EA    USD       1000.00  1010.50  2026-06-13T00:00:00Z  -
222    Scalper EA  USD       500.00   500.00   -                     login failed

Snapshot generated: 2026-06-13T00:00:00Z

--json emits the same data for machines ("account": null is the combined row):

$ mt5-pnl-cli pnl --from 2026-01-01 --to 2026-01-31 --by month --accounts "Trend EA" --json
{
  "rows": [
    {
      "period": "2026-01-01",
      "account": 111,
      "pnl": 10,
      "trades": 3,
      "wins": 2,
      "losses": 1,
      "gross_profit": 14,
      "gross_loss": -4
    },
    {
      "period": "2026-01-01",
      "account": null,
      "pnl": 10,
      "trades": 3,
      "wins": 2,
      "losses": 1,
      "gross_profit": 14,
      "gross_loss": -4
    }
  ],
  "summary": {
    "total_pnl": 10,
    "total_trades": 3,
    "win_rate_pct": 66.7,
    "profit_factor": 3.5,
    "gross_profit": 14,
    "gross_loss": -4
  }
}

Commands

  • pnl β€” P&L over a date range.
    • Range: --last Nd|Nw|Nm|Ny (default 30d; months and years are calendar-accurate) or --from YYYY-MM-DD [--to YYYY-MM-DD] (--to defaults to today). --last runs from N units ago through today inclusive, so 30d covers 31 calendar days. Dates, --last and "today" are all interpreted in UTC, and each deal is bucketed by its UTC day β€” so from a far-east timezone (e.g., UTC+12), the UTC day can differ from your local day near midnight.
    • --by day|week|month (default week; weeks start Monday, dates are UTC).
    • --accounts "Trend EA,Scalper EA" filters by account label (case-insensitive; default all).
    • --json for machine output.
  • accounts β€” balances, equity and freshness per account, plus the snapshot's generated_at.
  • set-passphrase β€” store the snapshot decryption passphrase in the OS keychain (macOS Keychain / Windows Credential Manager / Linux Secret Service). Prompted twice, never echoed.
  • version β€” binary version and supported snapshot schema.

Both query commands accept --snapshot PATH (overrides MT5_PNL_SNAPSHOT) and --stale-after (default 2h) β€” when the snapshot is older than that, a warning goes to stderr, never stdout, so --json pipelines stay clean.

How it works

snapshot.json.gz.age ──► age decrypt ──► gunzip ──► JSON ──► aggregate ──► table / JSON
(ciphertext on disk)     passphrase      (in memory only)
                         from keychain

The snapshot is never written to disk decrypted. Per closed deal, net P&L = profit + swap + commission + fee. A deal with net > 0 is a win, net < 0 a loss; a breakeven deal counts toward trades but neither bucket. Sums accumulate at full precision and round only for display. Profit factor = gross profit / |gross loss|.

What counts as a trade is decided upstream. This CLI sums every deal in the snapshot's closed_deals and trusts mt5-pnl-exporter to have emitted only closing deals β€” entry legs and cash flows (deposits, withdrawals) are filtered out there, not here β€” using MT5's native signs, where commission, swap and fees are already negative for costs. The CLI does not re-check this, so if you change that filtering or those signs in the exporter, the P&L here changes with no error. Keep the two in step.

Schema compatibility

schema/snapshot.schema.json is vendored from the exporter release this build supports. The CLI accepts the same major schema version and any minor at or below its own, and refuses anything else with a message naming both versions and which side to upgrade. mt5-pnl-cli version prints the supported schema version.

Threat model

The trust boundary is your OS user session β€” the same as the exporter's.

What's protected

  • The snapshot at rest stays age-encrypted; this CLI never writes a decrypted copy. Sync services and backups only ever see ciphertext.
  • The passphrase lives in the OS keychain. There is deliberately no env var or flag for it: env vars leak via dotfiles, shell history, and child processes, and scripts don't need one β€” the binary reads the keychain itself. (MT5_PNL_SNAPSHOT carries only a file path.)

What's not protected

  • A compromised user session. Anyone with your OS account can read the keychain entry and run this CLI. The exporter's threat model draws the same line.
  • Whatever you do with the output. Tables and JSON contain balances and trade history; treat redirected output accordingly.

See SECURITY.md for scope and private vulnerability reporting.

Contributing

Issues and PRs welcome β€” see CONTRIBUTING.md.

Licence

MIT

About

πŸ“Š Reads an encrypted MT5 snapshot, prints P&L and account tables.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages