Skip to content

Fees, netting and attribution

You hold algos in one venue account. Your own Hyperliquid or Lighter account — you never transfer funds to us, and we cannot withdraw from it.

That single decision determines everything on this page.

Every algo you hold publishes a target exposure per market. Those targets are netted before they reach the venue.

If one algo wants to be long 1.0 BTC and another wants to be short 0.6 BTC, your account trades 0.4 and pays fees on 0.4. You do not pay to hold both sides of a position that cancels.

This is the direct advantage of holding a basket here rather than holding two products somewhere else, and it is impossible if each algo needs its own funded account.

The key that trades for you is a delegated venue key — Hyperliquid calls it an API wallet, Lighter calls it an API key. It can place orders. It cannot withdraw. That is enforced by the venue, not by our code, which is the only kind of enforcement worth claiming.

A full compromise of our systems lets an attacker trade your margin badly. It does not let them take it.

That security property has a direct consequence for fees: we cannot debit your account. A performance fee or a monthly charge would require pulling funds we have no permission to move. So the fee is the one thing a venue collects on our behalf, at the moment of the fill — a builder fee on Hyperliquid, an integrator fee on Lighter.

Linking an account asks for two signatures:

Grant What it authorises
Trading Our key may place orders for you.
Fee The venue may route a small per-fill fee to us.

They are requested as a pair and revoked as a pair — Unlink pnl.xyz undoes both, and re-linking asks for both again. One without the other is not a state worth having: trading without the fee is a service we run for nothing, and the fee without trading collects on orders nobody placed.

But a lapsed fee approval never stops us trading. Your money is at risk in the market, and withholding execution to protect our revenue would be the wrong call, made by a machine, at the worst possible moment. It degrades our revenue and nothing else, and the app tells you to re-approve.

A small fraction of the notional you actually trade — that is, of the netted amount, after your algos have cancelled against each other.

It is worth being blunt about the arithmetic, because a basis point sounds like nothing and is not. Algos rebalancing on 15-minute bars turn over a large multiple of your equity each year. Measured on live Lighter BTC across a range of settings:

Turnover (× equity / year) at 0.5bp (the rate) at 1bp at 2bp
814 — trades on every twitch 4.1% 8.1% 16.3%
728 — a moderate deadband 3.6% 7.3% 14.6%
523 — patient, wide deadband 2.6% 5.2% 10.5%

The rate is 0.5 basis points, and it is set low deliberately. A higher one would take more from every user and fail more strategies at the launch gate’s cost-stress filter — which means fewer algos worth holding, which is the thing the platform is for. Extraction scales with volume; volume does not survive extraction.

Netting reduces it further: a basket whose algos disagree trades less than the sum of its parts, and pays less.

Notice what the table also says about the algos themselves. A strategy that trades on every twitch pays half again what a patient one does for the same exposure — so the cost of churn lands on the algo that causes it, and shows up in its published curve.

A share of profits is the fairer-sounding model and we cannot implement it honestly. It requires taking money out of your account, which the delegated key cannot do. Every workaround either asks you to transfer funds to us — giving up the custody property above — or bills you separately in a token you would have to hold and top up.

There is a second reason, and it is arithmetic rather than plumbing. A profit share has to measure “profit” over some window, and over short windows almost all movement is noise. Charging a fifth of every profitable 15-minute interval on a year that ends exactly flat would take several times your account, because a flat path still contains thousands of up-moves. A high watermark fixes that, and then only works if it is measured over weeks — at which point it is an invoice we cannot collect.

The fee is generated by your account’s trade. Splitting it among the algos you hold is the part that takes care.

  1. 20% goes to the platform.
  2. The remaining 80% is split among the algos you hold, weighted by how much each has made you recently, floored at zero.

So an algo that has been losing you money receives nothing. One that has been making you money receives a share proportional to how much.

“Recently” means a seven-day half-life

Section titled ““Recently” means a seven-day half-life”

Not this fifteen-minute interval. Over fifteen minutes almost all movement is noise, and weighting by it would mean a deployer’s payout was decided by whichever algo happened to be up in the last quarter hour.

So the weight is an exponentially-weighted P&L: recent performance counts most, and an algo that stops working stops being paid within a fortnight rather than coasting on a good month. It is published on your portfolio line, because a split nobody can see the basis for is a split nobody can check.

Why weighted by return, not by how much you allocated

Section titled “Why weighted by return, not by how much you allocated”

Suppose you hold two algos equally, one up 10% and one down 2%.

Weighting The winner gets The loser gets
By allocation 40% of the fee 40% of the fee
By recent P&L, floored at zero 80% of the fee nothing

Allocation weighting pays a losing deployer out of the winner’s gains. Worse, it is farmable: publish a flat algo, get it held alongside a good one, collect. Return weighting cannot be gamed that way — you are paid for being right about this user’s money, and for nothing else.

The platform keeps the whole fee for that window. No deployer is paid for a window in which nothing they built made you money.

Every algo publishes a reference curve: what it made, on its own, running live against real order books, with no other algo netting against it.

Your account will not match it, and the gap is not an error. Three things separate them:

Netting. Your other holdings change what actually gets traded. Two algos that disagree leave your account holding the difference — which is cheaper, and is a different position than either curve describes.

Fees. The reference curve is the algo’s performance. What reaches you is after the builder fee on your own netted turnover, which depends on the rest of your basket.

Timing. The curve runs from the algo’s launch. You bought in on some other day, at some other size, and may have changed that size since.

Funding is inside the reference curve, not shown separately — you are never quoted a “market funding rate” you have to net out by hand. The builder fee is not inside it, because it depends on your basket rather than on the algo.

Your book shows funding paid per algo, and the numbers add up to the funding your exchange account actually paid. Getting that to be true takes one idea, and it is the opposite of the one the trading fee needed.

Netting makes the bill smaller; it does not make the split hard

Section titled “Netting makes the bill smaller; it does not make the split hard”

Funding is charged on your net position. Two algos that disagree about BTC leave you holding the difference, and you pay funding on the difference — so the bill really is smaller than the two algos would have paid apart. That is a genuine saving and it is genuinely joint.

The attribution still comes out linear, because funding is charged on the signed position:

F(k) = −r(k) · n(k) where n(k) = Σ_i c(u,i,k)

n(k) is a plain sum of what each algo contributed, and F(k) is linear in n(k), so it is linear in the contributions:

F(k) = −r(k) · Σ_i c(u,i,k) = Σ_i ( −r(k) · c(u,i,k) )

Each algo’s share is the funding rate applied to its own position. There is no proportional split, no denominator, and nothing to divide by. The parts sum to the whole by construction rather than by a rounding rule.

Why the trading fee needed a split and this does not

Section titled “Why the trading fee needed a split and this does not”

The trading fee is charged on |Δ position|, and absolute value is not linear. Two algos that cancel cause genuinely less to be traded, so the saving is jointly produced and the only fair thing is to share it — which is why the fee is divided in proportion to each algo’s absolute contribution.

Funding is charged on the signed position, which is linear. Nothing is jointly produced, so nothing needs sharing. Using the absolute-value split here would be actively wrong: it would charge an algo positioned against the net, when that algo is the reason your bill is small.

If one algo is long 100 and another short 50, you pay funding on 50. The first is attributed the funding on 100; the second is credited the funding on −50. They sum to what you paid.

That credit is not an accounting artefact. The second algo halved what the first would otherwise have cost you, and a scheme that showed it paying nothing would hide the only thing it did. It is also why one algo’s share can exceed 100% of your total funding bill — that is the netting being visible, not a bug.

Where it stops being exact, and what we show instead

Section titled “Where it stops being exact, and what we show instead”

The attribution matches your exchange account only while our per-algo positions sum to the position the venue actually holds. Sometimes they do not: a rebalance has not settled yet, a fill was partial, or you traded by hand on the linked account.

When the venue’s funding total and ours disagree, the difference is shown as a residual rather than spread across your algos. A residual is a fact about the account, not about any algo. Smearing it pro-rata would dress the one number that proves something is out of line as though it were understood.

Two reasons your position changes, and only one is an algo’s doing

Section titled “Two reasons your position changes, and only one is an algo’s doing”

Everything above splits a cost between algos, because the position moved for an algo’s reason. There is a second reason it moves, and attributing that one to algos would be plainly wrong.

An algo changed its mind. A signal updates, the algo’s target position changes, and your account drifts from where the book says it should be. You did nothing. The per-account worker notices and rebalances. The trading fee that causes is attributed across algos by the absolute-contribution split described above, because the algos are the entire reason anything traded.

You changed your mind. You reduce your weight in algo B to put it into algo A. Nothing about A, B or C has changed — their targets are what they were a second ago. What changed is how much of your account each one speaks for, and the resulting trade exists because you asked for it.

The weight change is a trade you are placing

Section titled “The weight change is a trade you are placing”

Given the current per-algo targets, a weight change resolves to an immediate, fully-determined set of position deltas. There is nothing to wait for and nothing to infer: new weights times current targets, minus what you hold, at current leverage. That is arithmetic the browser can do while you drag the slider, which is why the number you are shown before you confirm is the number that gets executed.

So it runs through the trading terminal, on the path any exchange front-end would use: compute the deltas, show them, place the orders. It does not go through the per-account worker at all.

That separation is deliberate. The worker exists to answer a question nobody asked — the algos moved, what does this account need? — and it answers it on its own schedule. A weight change is the opposite: you asked, you are watching, and you expect it to happen now rather than at the next rebalance. Routing an intentional trade through a background reconciler would make a deliberate act feel like a delay, and would mix two things whose costs belong in different places.

A weight change’s trading fee is wholly the platform’s builder/integrator fee, and no part of it reaches an algo’s ledger.

There is nothing to attribute. No algo emitted a signal, no algo’s target moved, and no algo caused a single unit of the volume. Charging a share of it to A, B and C would make an algo’s cost line depend on how often its holders rearranged their portfolios — so an algo that never traded could accumulate fees on a quiet week because its holders were busy, and its published cost figures would stop being a property of the strategy at all.

It also protects the number that matters. An algo’s fee attribution is supposed to answer what did this strategy cost to run. The moment user-initiated volume enters it, that answer becomes what did this strategy cost to run, plus whatever its holders happened to do, which is a different question with the same name.

The split does not change what the venue charged. Algo-caused fees are attributed across algos, weight-change fees are booked to the platform, and the two together must equal the account’s real trading fees. Where they do not, the difference is a residual and is shown as one — the same treatment funding gets, and for the same reason.

A published backtest is charged the same platform fee a live account pays, plus modelled execution costs. A strategy whose edge disappears under its own trading costs is one the launch gate should refuse, and it does.

This makes the number on an algo’s card a harder target than a naive backtest would show — which is the point. It is a figure to beat, not a figure to admire.