---
title: "Cumulative returns — Trading Analytics for Laravel | Roundly"
description: "Compounded returns in percent, gross and net of commissions, with a geometric per-trade average and running highs and lows."
url: https://roundly-consulting.com/open-source/docs/trading-analytics-for-laravel/cumulative-returns
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Trading Analytics for Laravel](https://roundly-consulting.com/open-source/docs/trading-analytics-for-laravel.md)

# Cumulative returns

cumulativeReturn compounds each trade’s return — its P&L divided by open price × size — in the order the trades close (see Trade order): (1 + r₁) × (1 + r₂) × … − 1, reported in percent to 2 decimals. gross uses the raw return; net subtracts the commission first. Every trade in the stream counts, open ones at their close price:

```php
$gross = $analytics->cumulativeReturn->gross->global->total;
$net = $analytics->cumulativeReturn->net->global->total;

$gross->total;        // '2.97' — compounded return over the stream, in percent
$gross->average;      // '0.98' — geometric mean return per trade, in percent
$gross->highest;      // '5.00' — peak of the running cumulative return
$gross->highestPair;  // 'BTC/USD' — the pair whose trade set that peak
$gross->lowest;       // '-0.25' — trough of the running cumulative return (lowestPair 'ETH/USD')
$net->total;          // '2.71' — the same, with commissions subtracted

$analytics->cumulativeReturn->net->forPair('BTC/USD')->buy->total;
```

- total — the compounded return at the end of the stream.
- average — the geometric mean return per trade, computed entirely in bcmath.
- highest / lowest — the peak and the trough the running cumulative return reached, each with the pair of the trade that set it. Zero is a value like any other, so the highest can be below 0.

The growth product behind the average is kept as a mantissa and a power of ten, so a long losing streak never collapses the average to −100 % (500 trades at −5 % average −5.00). A trade that lost more than 100 % — a short whose price more than doubled — makes the product negative, and the average keeps that sign as (−root − 1) × 100, below −100 %: one sell from 100 to 250 averages −150.00. An even trade count has no real root, so the same signed root stands in for it.

Like every aggregate metric, gross and net both break down per pair, base and quote currency, and into buys and sells.

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/trading-analytics-for-laravel.md)
