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

Wins and win ratio

A closed trade wins when its gross P&L is above zero; a break-even trade is a closed trade that did not win. Open trades have no outcome yet, so they count towards neither. wins counts the winners, wins->closed the closed trades, and wins->winRatio holds wins divided by closed trades — a fraction to 2 decimals, so 0.66 means 66%, in line with expectancy->winRate. The ratio is listed for every key with a closed trade, a 0.00 included:

$analytics->wins->global->total;                     // '2' — winning closed trades
$analytics->wins->forPair('ETH/USD')->buy;           // '1'
$analytics->wins->closed->global->total;             // '3' — closed trades, the ratio's denominator
$analytics->wins->winRatio->global->total;           // '0.66' — wins / closed trades
$analytics->wins->winRatio->forPair('ETH/USD');      // total '0.50', buy '1.00', sell '0.00'
$analytics->wins->winRatio->forQuoteCurrency('USD')->sell;

Streaks

streaks walks the closed trades in close-time order (see Trade order) and records the longest run of consecutive winners and of consecutive losers — globally, per pair, base and quote currency, and per direction. The buy streak only looks at buys and the sell streak only at sells; a break-even trade ends both the winning and the losing run:

$analytics->streaks->wins->global->total;               // longest run of winners
$analytics->streaks->losses->global->total;             // longest run of losers
$analytics->streaks->wins->global->buy;                 // longest winning run among buys
$analytics->streaks->losses->forPair('ETH/USD')->total;
$analytics->streaks->wins->forBaseCurrency('BTC')->sell;

Win rate by period

winRateByPeriod buckets closed trades by their open time and reports wins, totals and the win rate (4 decimals) per bucket. Set the period per run, or for the whole app with the win_rate_period config key:

use RoundlyConsulting\TradingAnalytics\Enums\Period;

$analytics = TradingAnalytics::for($trades)
    ->usingWinRatePeriod(Period::MONTHLY) // DAILY (default), WEEKLY, MONTHLY
    ->calculate();

$result = $analytics->winRateByPeriod;

$result->period;   // Period::MONTHLY
$result->totals;   // ['2024-03' => 3] — closed trades per bucket
$result->wins;     // ['2024-03' => 2] — winners per bucket
$result->rates;    // ['2024-03' => NumericValueAsString] — wins / totals

$result->toArray()['rates']; // ['2024-03' => '0.6666']

// Period::WEEKLY instead: ['2024-W09' => '0.5000', '2024-W10' => '1.0000']
PeriodBucket keyExample
Period::DAILYY-m-d2024-03-05
Period::WEEKLYISO year + week2024-W10
Period::MONTHLYY-m2024-03

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.