NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

P&L comes in two results: realizedProfitAndLoss for closed trades and unrealizedProfitAndLoss for open ones, valued at their closePrice. Each holds gross (before commissions) and net (after commissions) figures:

$realized = $analytics->realizedProfitAndLoss;     // closed trades
$unrealized = $analytics->unrealizedProfitAndLoss; // open trades, valued at closePrice

$realized->gross->global->total->total;            // '800.00' — before commissions
$realized->net->global->total->total;              // '781.00' — after commissions
$realized->net->global->total->highest;            // '990.00' (highestPair 'BTC/USD')
$realized->net->forPair('ETH/USD')->buy->total;    // '97.00'
$realized->gross->forQuoteCurrency('USD')->sell->average;

$realized->grossProfits->total;                    // '1100.00' — summed positive P&L
$realized->grossLosses->total;                     // '-300.00' — summed negative P&L
$realized->netProfits->forBaseCurrency('BTC');     // also forPair() / forQuoteCurrency()

$unrealized->net->global->total->total;            // open positions, after commissions
  • gross / net — full breakdowns (global, per pair, base and quote currency; total, buy, sell) with total, count, average, highest and lowest. Realized figures average over the closed trades, unrealized ones over the open trades.
  • grossProfits / grossLosses and netProfits / netLosses — the summed positive and the summed negative P&L, as a total and per pair, base and quote currency. Losses stay negative; a break-even trade lands in neither, and realized and unrealized trades never mix.
  • A trade’s P&L is (close − open) × size for a buy and (open − close) × size for a sell; the net variant subtracts its commission.

Profit factor

profitFactor divides the realized gross profits by the absolute realized gross losses, to 2 decimal places, globally and per pair, base and quote currency (there is no buy/sell split). A breakdown without losses reports 0.00, and a loss-only pair or currency reads 0.00 rather than going missing. ProfitFactor reads the totals collected by RealizedGrossProfitAndLoss, which is why only() pulls that calculator in:

$analytics->profitFactor->total;                   // '3.66' — gross profits / |gross losses|
$analytics->profitFactor->forPair('ETH/USD');       // '0.33'
$analytics->profitFactor->forPair('BTC/USD');       // '0.00' — no losing BTC/USD trade
$analytics->profitFactor->forBaseCurrency('ETH');
$analytics->profitFactor->forQuoteCurrency('USD');

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.