---
title: "Testing — Trading Analytics for Laravel | Roundly"
description: "Unit-test your reports with hand-built trades — no database, no fakes — and assert exact string figures."
url: https://roundly-consulting.com/open-source/docs/trading-analytics-for-laravel/testing
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)

# Testing

There is no TradingAnalytics::fake(): the engine is a pure calculation with no side effects — no database, HTTP or queue — so a test feeds it the trades it needs and asserts on the numbers. Build a few trades with Trade::make(), in close-time order, and assert exact strings; bcmath output is deterministic:

```php
use RoundlyConsulting\TradingAnalytics\DataTransferObjects\Trade;
use RoundlyConsulting\TradingAnalytics\Facades\TradingAnalytics;

it('reports realized p&l, win ratio and drawdown', function () {
    $trades = [
        Trade::make('BTC', 'USD', '40000', '42000', '0.5', 'buy', '2024-03-01 09:00', '10', '2024-03-01 15:00'),
        Trade::make('ETH', 'USD', '3000', '3150', '2', 'sell', '2024-03-02 10:00', '6', '2024-03-02 12:00'),
    ];

    $analytics = TradingAnalytics::for($trades)->scale(2)->calculate();

    expect((string) $analytics->realizedProfitAndLoss->gross->global->total->total)->toBe('700.00')
        ->and((string) $analytics->realizedProfitAndLoss->net->global->total->total)->toBe('684.00')
        ->and((string) $analytics->wins->winRatio->global->total)->toBe('0.50')
        ->and((string) $analytics->maxDrawdown->value)->toBe('306.00');
});
```

Set ->scale() in tests so the expected strings stay short, and cast results with (string) before comparing. The facade needs the Laravel container; in a plain PHPUnit test without a booted app, run the engine class itself — the built-in defaults apply:

```php
use Illuminate\Support\LazyCollection;
use RoundlyConsulting\TradingAnalytics\Analytics;

// No booted app (plain PHPUnit): run the engine class itself
$analytics = Analytics::for(LazyCollection::make($trades))->scale(2)->calculate();
```

## The package’s own suite

The package ships a Pest suite with static analysis: an end-to-end test that stores 600 trades from a committed reference dataset in SQLite and checks every headline metric against frozen expected values, frozen golden vectors, hand-computed metrics, and a streaming test that pushes 50,000 trades through every calculator — from a generator and from a query builder in 500-row pages — in constant memory. Run it from the package directory:

```bash
composer test
```

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