Hyperliquid Win Rate: Profit Factor & Expectancy (2026)
Calculate your Hyperliquid win rate, profit factor and expectancy from fills: formulas, breakeven table, a real dated wallet example and a Python script.
The short version: win rate is the share of your closed trades that made money after fees. On Hyperliquid you can calculate it from public fills, but the number changes a lot depending on what you call a "trade": every closing fill, every closing order, or a full round trip from flat to flat. Win rate alone also says nothing about profit. Pair it with average win, average loss, profit factor and expectancy, and remember that funding and unrealized PnL never show up in closed trades. In our 26 October 2026 snapshot, a leaderboard wallet with +$1.64 million of monthly PnL had a closing-fill win rate of just 36.8% and roughly breakeven realized trades. Its money came from open positions and funding.
"What is my win rate on Hyperliquid?" sounds like a simple question. Hyperliquid's own interface shows trade history and PnL, but not a win rate, so traders either export fills to a spreadsheet or trust a third-party number without knowing how it was counted. This guide explains the formulas, the three ways to define a trade (and why they give different answers), the Hyperliquid API fields you need, a real dated example, and a short Python script that computes everything for any public address. No API keys are needed.
The four numbers that matter
All of these are calculated on closed trades, using PnL net of fees.
- Win rate = winning trades ÷ (winning + losing trades). Trades at exactly zero are left out.
- Average win and average loss = total won ÷ number of wins, and total lost ÷ number of losses. Their ratio is the payoff ratio (R).
- Profit factor = gross profit ÷ gross loss. Above 1.0 the trades made money; below 1.0 they lost money.
- Expectancy = net PnL ÷ number of trades, which equals win rate × average win − loss rate × average loss. It is what an average trade is worth in dollars.
The link between them is the breakeven win rate: average loss ÷ (average win + average loss), or 1 ÷ (1 + R). You need a win rate above that line to make money.
| Payoff ratio (avg win ÷ avg loss) | Breakeven win rate |
|---|---|
| 0.5 | 66.7% |
| 1.0 | 50.0% |
| 1.5 | 40.0% |
| 2.0 | 33.3% |
| 3.0 | 25.0% |
That is why a 35% win rate can be excellent and a 90% win rate can be a slow way to blow up an account: it depends entirely on the size of the wins compared with the losses.
What counts as a "trade" on Hyperliquid?
Hyperliquid records fills, not trades. One order can fill in many pieces, and a position can be scaled in and out with dozens of orders. So you have to choose a unit:
- Closing fills. Every fill that reduces a position and carries a
closedPnl. This is the easiest to compute and the most common in dashboards, but it is noisy: one order split into ten fills becomes ten "trades". - Closing orders. Fills grouped by order id (
oid). Closer to how a trader thinks ("I took profit once"), but scaling out of one position in three orders still counts as three trades. - Round trips. From the moment a position opens from zero until it is flat again (or flips to the other side). This matches the idea of "one trade, one idea", and it includes the fees paid on the entry fills, which the other two methods ignore.
None of these is wrong, but they are not comparable. If someone quotes a Hyperliquid win rate, ask which unit they used. For judging your own decisions, round trips are usually the most honest; for checking execution, fills and orders are useful.
The API fields you need
Everything comes from the public info endpoint (POST https://api.hyperliquid.xyz/info):
userFillsByTimereturns fills for an address in a time range. Each fill hascoin,side(Bbuy,Asell),sz,px,startPosition(the position size before the fill),dir(for exampleOpen LongorClose Short),closedPnl,feeandoid. A response holds up to 2,000 fills, so you page by time, and only the 10,000 most recent fills can be reached this way. Very active wallets hit that cap in days or even hours.- The
feefield is reported separately fromclosedPnl, so subtract it yourself to get net PnL. A negative fee is a maker rebate. userFundingreturns funding payments. Funding is not part of any fill, so a win rate built from fills ignores it. The endpoint returns up to 500 rows per call, so page through it too.clearinghouseStatereturns open positions with theirunrealizedPnl, which no closed-trade statistic includes.
If you are new to these fields, our closed PnL guide and unrealized PnL guide explain them in detail, and how to export your trade history covers getting the raw fills into a spreadsheet.
A real example: same wallet, three win rates
We ran the script below on 26 October 2026 at about 08:14 UTC against 0x541e077ac38c56d7bf590924d249c60b0c80071d, a wallet from the public Hyperliquid leaderboard, for the previous 30 days. The leaderboard showed +$1,636,619 of PnL for the month (70% ROI) on an account worth about $1.35 million. The wallet had 1,947 fills in the window, 1,924 of them on perps. All PnL figures below are net of fees.
| Unit | Trades | Win rate | Avg win | Avg loss | Profit factor | Net |
|---|---|---|---|---|---|---|
| Closing fills | 917 | 36.8% | $515 | $299 | 1.00 | +$478 |
| Closing orders | 411 | 36.3% | $1,166 | $661 | 1.00 | +$478 |
| Round trips (opened and closed in the window) | 12 | 41.7% | $1,333 | $1,008 | 0.94 | −$393 |
Three lessons jump out:
- The trade count swings from 917 to 12 depending on the definition. Averages per trade change by the same factor, so never compare an "average win" across tools without knowing the unit.
- The closing-fill numbers check out with the breakeven formula. With an average win of $515 and an average loss of $299, breakeven is 299 ÷ (515 + 299) ≈ 36.7%. The actual win rate was 36.8%, so the profit factor lands at 1.00 and closed trades made only $478.
- Closed trades explained almost none of the month's PnL. In the same window the wallet received about $129,042 of funding (4,680 payments), and its nine open positions, all shorts, carried about $1,056,140 of unrealized PnL at the snapshot. A win-rate dashboard would call this a breakeven trader; the account was up seven figures.
These figures are a dated snapshot of live data and will be different when you run the script.
Python script: win rate, profit factor and expectancy for any address
The script pages through userFillsByTime, keeps perp fills (spot coins start with @), and prints all three definitions plus a per-coin breakdown of round trips. Round trips whose entry happened before the window are skipped, because their entry fees and part of their PnL are missing. It uses a handful of light requests, well within the API rate limits.
import requests, time, collections
from datetime import datetime, timezone
API = "https://api.hyperliquid.xyz/info"
ADDRESS = "0x541e077ac38c56d7bf590924d249c60b0c80071d" # any public address, no keys needed
DAYS = 30
def fills_since(user, start_ms):
"""Page through userFillsByTime (max 2,000 rows per call, newest 10,000 reachable)."""
out, t = [], start_ms
while True:
batch = requests.post(API, json={"type": "userFillsByTime", "user": user,
"startTime": t, "aggregateByTime": True}, timeout=15).json()
if not batch:
break
out += batch
if len(batch) < 2000:
break
t = batch[-1]["time"] + 1
return out
def stats(pnls):
wins = [p for p in pnls if p > 0]
losses = [p for p in pnls if p < 0]
gw, gl = sum(wins), -sum(losses)
n = len(wins) + len(losses)
return {
"trades": n,
"win_rate": len(wins) / n if n else 0,
"avg_win": gw / len(wins) if wins else 0,
"avg_loss": gl / len(losses) if losses else 0,
"profit_factor": gw / gl if gl else float("inf"),
"expectancy": (gw - gl) / n if n else 0,
"net": gw - gl,
}
now = int(time.time() * 1000)
fills = sorted(fills_since(ADDRESS, now - DAYS * 86_400_000), key=lambda f: f["time"])
perp = [f for f in fills if not f["coin"].startswith("@")]
# 1) every closing fill counts as a "trade" (what many dashboards do)
closing = [f for f in perp if f["dir"].startswith("Close") or float(f["closedPnl"]) != 0]
per_fill = [float(f["closedPnl"]) - float(f["fee"]) for f in closing]
# 2) one closing ORDER = one trade (partial fills of the same oid merged)
by_oid = collections.defaultdict(float)
for f in closing:
by_oid[(f["coin"], f["oid"])] += float(f["closedPnl"]) - float(f["fee"])
per_order = list(by_oid.values())
# 3) round trips: a position that opens from 0 and returns to 0 (fees of every fill included)
# positions already open when the window starts are skipped (their entry is missing)
trips, open_pnl = [], {}
for f in perp:
c = f["coin"]
start = float(f["startPosition"])
signed = float(f["sz"]) * (1 if f["side"] == "B" else -1)
if start == 0:
open_pnl[c] = 0.0 # a new position starts here
if c not in open_pnl:
continue # opened before the window
open_pnl[c] += float(f["closedPnl"]) - float(f["fee"])
end = start + signed
if abs(end) < 1e-9 or (start > 0) != (end > 0): # flat again (or flipped side)
trips.append((c, open_pnl.pop(c)))
if abs(end) >= 1e-9:
open_pnl[c] = 0.0 # a flip opens the opposite side
per_trip = [p for _, p in trips]
print(f"{ADDRESS} last {DAYS} days fills={len(fills)} perp fills={len(perp)}")
if not fills:
raise SystemExit("no fills in this window")
first = datetime.fromtimestamp(fills[0]["time"] / 1000, tz=timezone.utc)
print(f"data from {first:%Y-%m-%d %H:%M} UTC" + (" (hit the 10,000-fill cap, window is shorter than asked)" if len(fills) >= 10_000 else ""))
for name, s in (("closing fills", stats(per_fill)), ("closing orders", stats(per_order)), ("round trips", stats(per_trip))):
print(f"{name:14} n={s['trades']:5} win rate {s['win_rate']:.1%} avg win ${s['avg_win']:,.0f} "
f"avg loss ${s['avg_loss']:,.0f} profit factor {s['profit_factor']:.2f} "
f"expectancy ${s['expectancy']:,.0f} net ${s['net']:,.0f}")
by_coin = collections.defaultdict(list)
for c, p in trips:
by_coin[c].append(p)
for c, ps in sorted(by_coin.items(), key=lambda kv: -len(kv[1]))[:5]:
s = stats(ps)
print(f" {c:8} trips={s['trades']:4} win rate {s['win_rate']:.1%} net ${s['net']:,.0f}")
Ideas to extend it: add userFunding per coin to get funding-adjusted round trips, split long and short trades using dir, or bucket trades by holding time. New to the API? Start with the Hyperliquid API Python guide.
How to read your own numbers
- High win rate, small wins, rare big losses. Typical of strategies that cut winners early or let losers run. Check the average loss and your drawdown, not the win rate.
- Low win rate, large wins. Normal for trend following and breakout trading. Fine as long as profit factor stays above 1 after fees.
- Profit factor near 1.0. Your edge is roughly the size of your costs. Fees matter a lot here: see the Hyperliquid fees guide and the real PnL with fees and funding guide.
- Small samples lie. With 12 round trips, one trade moves the win rate by more than 8 percentage points. Wait for a few dozen trades before drawing conclusions.
- Use the same window everywhere. Compare win rate, funding and unrealized PnL over one period, or the story will not add up.
Keeping notes on why you took each trade makes these numbers far more useful; our Hyperliquid trading journal guide shows a simple setup.
Checking other traders' win rates
Because fills are public, you can run the same analysis on any wallet, including leaderboard traders and the wallets in Smart Money. Treat their numbers with the same care: a trader who mostly holds positions, earns funding or market-makes will look very different depending on the unit and window. For the bigger picture, look at their PnL curve and open positions as well, which is exactly what a portfolio tracker shows.
Track your PnL without code
Hyperfolio is a free, read-only tracker for Hyperliquid. Paste one or more addresses to see PnL, open perps, unrealized PnL and recent fills in one place, as a PWA on desktop or mobile. It never asks for a private key or a signature. If you follow several accounts, see how to track multiple Hyperliquid wallets.
FAQ
Does Hyperliquid show my win rate?
Not directly. It shows trade history and PnL. You can calculate win rate from your fills with the public API, as shown above.
What is a good win rate on Hyperliquid?
There is no universal number. It has to be above your breakeven win rate, which depends on your payoff ratio: about 50% if wins and losses are the same size, about 33% if wins are twice as large.
Is closedPnl net of fees?
The fee is reported in its own fee field on each fill, so the script subtracts it from closedPnl to get net PnL. Opening fills have a closedPnl of zero but still pay fees, which only the round-trip method captures.
Does funding count in win rate?
Not if you build win rate from fills. Funding is paid separately and is available through userFunding. For positions held a long time it can be larger than the trading PnL, as in the example above.
What is profit factor?
Gross profit divided by gross loss on closed trades. A profit factor of 1.5 means you made $1.50 for every $1 you lost.
Why does my win rate differ between tools?
Usually because they count trades differently (fills, orders or round trips), use different time windows, or include or exclude fees. In our example the same wallet had 917 closing fills but only 12 complete round trips.
Can I see a whale's win rate?
Yes. Hyperliquid fills are public, so the script works for any address. Very active wallets may hit the 10,000-fill limit, which shortens the window you can analyze.
Trade for less. If you are new to Hyperliquid, use referral code HYPERFOLIO for 4% off trading fees (how the referral works), then follow your PnL, positions and fills for free in Hyperfolio.
Try Hyperfolio for free
Track your Hyperliquid portfolio in real time with PnL, Smart Money, Markets, Perp Calculator, multi-venue portfolio and push alerts.
HYPERLIQUID
-4% feesTrade on Hyperliquid · 4% off fees
Hyperfolio is an independent app, free to use with no subscription. We're funded by Hyperliquid referrals, ad space and donations; we truly appreciate you trading through our link.
Free for you · keeps Hyperfolio running
Related articles
Hyperliquid Liquidation Map: Real Liquidation Levels (2026)
Build a Hyperliquid liquidation map from real on-chain positions instead of estimated heatmaps. Dated example from the 300 largest accounts on 2 Nov 2026, how to read clusters and concentration, and a Python script.
GuideBest Time to Trade on Hyperliquid: Hours & Days (2026)
When Hyperliquid volume and volatility peak, by UTC hour and weekday, measured from 672 hourly candles (4 Oct to 1 Nov 2026) for BTC, ETH, HYPE and SOL, with what it means for slippage, stops and funding, plus a Python script.
GuideHyperliquid Long/Short Ratio: Read Trader Positioning (2026)
Why the market-wide long/short ratio on Hyperliquid is always 1, how to measure it for a cohort of wallets from public data, a dated example of the top 100 leaderboard traders, and a Python script.
GuideHyperliquid Sharpe Ratio: Risk-Adjusted Returns Guide (2026)
Calculate Sharpe and Sortino ratios for any Hyperliquid wallet or vault from the public portfolio endpoint: the deposit and withdrawal trap, dated leaderboard and HLP examples, and a Python script.
GuideHyperliquid Correlation & Beta: Hedging Crypto Perps (2026)
Measure correlation and beta on Hyperliquid from the public candle API: dated 30- and 90-day matrices for BTC, ETH, HYPE, SOL, XRP and DOGE, three portfolio and hedge examples, and a Python script.
GuideHyperliquid Volatility & ATR: Stops, Size, Leverage (2026)
Measure Hyperliquid volatility yourself from the public candle API: realized volatility and ATR for BTC, ETH, HYPE, SOL, XRP and DOGE on a dated snapshot, plus stop, position size and leverage examples and a Python script.