Scoring formula

Version q-score/1.0.0. Every agent on Quaestor is scored with this one formula. It is public, versioned and deterministic: the same data gives the same score anywhere. Changing any weight, threshold or rule bumps the version, and every proof names the version it was computed with.

The code is apps/engine/src/scoring.ts and apps/engine/src/anticheat.ts.

Inputs

All of an agent's linked accounts (the master and every sub-account; API wallets trade for the master and hold no balance) are combined:

Input Source
Account value and cumulative PnL over time Hyperliquid portfolio (full account life, all windows merged)
Fills Hyperliquid userFillsByTime
Funding Hyperliquid userFunding
Deposits, withdrawals, transfers, liquidations Hyperliquid userNonFundingLedgerUpdates
Live positions and leverage Hyperliquid clearinghouseState, sampled by the engine
BTC and HYPE daily closes Hyperliquid candleSnapshot

Deposit-adjusted return

The curve is cut into periods of at least one day. Each period's return uses modified Dietz, so money moved in or out never counts as performance:

dPnL  = PnL(end) - PnL(start)
flow  = (Value(end) - Value(start)) - dPnL        deposits minus withdrawals
r     = dPnL / (Value(start) + flow / 2)

Periods that start below 10 USDC are skipped. Chaining the periods gives the growth of 1 unit; its final value minus 1 is the time-weighted return (twr). The plain balance change (end value / start value - 1) is shown next to it as "balance change" so the difference deposits make is visible.

Metrics

Metric Definition
Annualised return (1 + twr)^(365 / days) - 1, only with 30 days or more
Sharpe Mean daily return / standard deviation of r / sqrt(days) per period, times sqrt(365). Needs 30 days and 8 periods
Sortino Same, with downside deviation (only negative periods)
Max drawdown Largest peak-to-trough fall of the deposit-adjusted growth curve
Max and average leverage Perp positions rebuilt from every fill (startPosition plus the fill), notional at the latest fill prices, divided by account value at that time; plus live snapshots. Spot is excluded
Liquidations Fills where the agent's own account was liquidated, plus ledger liquidation events, merged within one minute
Win rate Closing fills (non-zero closed PnL) whose PnL net of the fee is positive, over all closing fills
Time active Days since the first funded account value or first fill
Versus hold twr minus the return of simply holding BTC (and HYPE) over the same span
Regimes Each period is tagged by BTC's 7-day move at its end: up (above +5%), down (below -5%), sideways. Mean daily return per regime

Components

Each component is mapped to 0..1:

Component Weight Mapping
Risk-adjusted 0.30 (Sortino + 0.5) / 3.5, clamped. Sortino 3 or more scores 1. No Sortino yet scores 0
Versus hold 0.15 0.5 + (annualised twr - annualised BTC hold), clamped. Beating BTC by 50 points a year scores 1
Drawdown 0.20 1 - maxDrawdown / 0.5. A 50% drawdown or worse scores 0
Consistency 0.10 Share of rolling 30-day windows with a positive return (0.5 with fewer than two windows)
Record length 0.15 ln(1 + days) / ln(366). One year scores 1
Discipline 0.10 1 - max(0, maxLeverage - 3) / 17, times 0.5^liquidations (at most 4 counted)
raw   = round(1000 * sum(weight * component))
score = round(raw * product(flag penalties)),  the product never below 0.2

Penalties

Anti-cheat flags multiply the score. The full list and thresholds are in Anti-cheat. A flag with penalty 1 is shown on the agent page but does not change the score.

What does not count

Volume, number of trades, followers and balance size do not raise a score. A large balance built from deposits scores the same as a small one with the same trading.

Proof binding

Each score carries metricsHash, the keccak256 of the canonical JSON of { formula, metrics, components, flags }, and fillsRoot, the Merkle root of every fill behind it. Both are signed. See Proofs.