Weighted Price Ratio
The weighted geometric ratio a multi-leg basket trades on, where the weights live in the API, and why the value on GET /markets/baskets is computed differently.
While a simple price ratio works for one long vs. one short, traders often use baskets of assets: multiple longs and multiple shorts with different weightings. The Weighted Ratio generalizes the idea of the price ratio into a combined performance measure for the entire strategy.
This is the formula a weighted_ratio trigger condition is evaluated against, and the formula @pear-protocol/market-sdk plots. It is not how weightRatio on GET /markets/baskets is computed. See Which formula runs where.
How It Works
Each asset price is raised to the power of its allocation weight:
- Long positions have positive weights
- Short positions have negative weights
On the wire the weight is always positive. side supplies the sign: BUY is +1, SELL is -1.
So, for the example portfolio:
- 50% Long $HYPE
- 25% Short $ASTER
- 25% Short $XPL (Plasma)
The weighted ratio becomes:
This is effectively the geometric return of the portfolio, a mathematically clean way to encode long/short performance.
The value is computed in log space, as exp(Σ sign × weight × ln price). A leg with no price, or a price of zero or less, has no logarithm, so the whole basket is unpriceable and the condition holds instead of firing on a wrong number.
What It Tells You
The absolute value of the ratio at any moment isn’t very important. What is important is how it changes over time:
- If the weighted ratio trends upward, your basket is performing well:
- longs are winning
- shorts are losing
- or both
- If it trends downward, the basket is underperforming.
This makes the weighted ratio a direct measure of strategy PnL momentum.
Reading the Chart
- Rising, longs are outperforming shorts. The trade is working.
- Falling, shorts are outperforming longs. The trade is losing.
Using the example above: if the ratio is trending up, HYPE is outperforming the ASTER+XPL basket. Flipping the structure (long ASTER+XPL / short HYPE) would show a downtrend — same information, opposite perspective.
You don't need to track each asset individually. The ratio chart shows the combined PnL path of the entire strategy in one line.
Where the Weights Come From
Weights come from what the caller sends. Every endpoint in the table below carries them explicitly on the request.
An open position does not store them. It exposes exposure per instrument on GET /positions, and the effective weights follow from that, drifting as prices move. The one place opening weights are read back is auto-rebalance, whose INITIAL_WEIGHT source returns the position to the shares it opened with.
Code Example
Weights here are percents, matching @pear-protocol/market-sdk, which divides each weight by 100. The gateway's own conditions take fractions instead. Passing a fraction to this function raises each price to a hundredth of the intended power.
type Token = { symbol: string; weight: number }; // weight is a percent: 50, not 0.5
type TokenPriceMap = Map<string, { markPrice: number }>;
function computeWeightedRatio(
longTokens: Token[],
shortTokens: Token[],
prices: TokenPriceMap,
): number | null {
const legs = [
...longTokens.map((t) => ({ token: t, sign: 1 })),
...shortTokens.map((t) => ({ token: t, sign: -1 })),
];
let logSum = 0;
for (const { token, sign } of legs) {
const price = prices.get(token.symbol)?.markPrice;
// One unpriceable leg leaves the whole basket without a value.
if (price === undefined || price <= 0) return null;
logSum += ((sign * token.weight) / 100) * Math.log(price);
}
return Math.exp(logSum);
}Reading it from the API
GET /markets/baskets returns weightRatio and weightRatioChange24h on every basket. Those two fields do not use the formula above.
On that endpoint weightRatio is the average price of the long legs divided by the average price of the short legs, unweighted, and it holds the same value as price. weightRatioChange24h likewise equals priceChange24h. A basket there carries no weights at all: a leg is { id, symbol, side }. See Price Ratio.
To chart the weighted geometric ratio, compute it yourself from the code above, or read it from @pear-protocol/market-sdk.
Where weights live in the API
Weights appear wherever Pear has to split one number across the basket.
| Endpoint | Field | Meaning |
|---|---|---|
POST /schedules | legs[].weight | Each leg's share of one targetNotional. |
POST /rebalance/manual/{positionId} | weightings[].weight | The target shares to trade back to. |
POST /triggers/open | condition.data.basket[].weight | The basket a weighted_ratio condition watches. |
POST /triggers/close | condition.data.basket[].weight | The same, on a weighted_ratio or weighted_ratio_trailing close condition. |
POST /ladders | condition.data.basket[].weight | The same, on a ladder's weighted_ratio condition. |
POST /saved-baskets | legs[].weight | A stored template, sized at the moment you trade it. |
Every weight obeys the same four rules:
- A weight is a fraction, above 0 and at most 1.
0.25, not25. - The legs must sum to exactly 1, within a rounding tolerance of
1e-9. - Each leg must name a distinct instrument. A repeated
symbolis rejected. - A
weighted_ratiobasket needs at least two legs. A one-leg basket is rejected. A one-sided basket is allowed, and is then the weighted geometric mean of its legs' prices.
A market open through POST /trade/open takes no weights: you size each leg directly with mode and amount.
Trading it
A weighted_ratio condition watches the whole basket rather than a single pair:
{
"condition": {
"type": "weighted_ratio",
"data": {
"priceSource": "mid",
"basket": [
{ "symbol": "159", "side": "BUY", "weight": 0.5 },
{ "symbol": "207", "side": "SELL", "weight": 0.25 },
{ "symbol": "203", "side": "SELL", "weight": 0.25 }
],
"track": "PEAK",
"threshold": 1.15
}
}
}That watches the 50% HYPE / 25% ASTER / 25% XPL basket from the example above, on Hyperliquid instrument IDs.
priceSource is required. track and threshold follow the same endpoint-by-endpoint rules as a ratio condition: a close condition takes no track, and a ladder takes no threshold. See Price Ratio.
Price Ratio
How one long and one short collapse into a single line, which formula the API actually uses, and how to trade the ratio with a trigger.
Net Funding
What it costs to hold a basket once the paid and received funding legs net out, and why the sign on GET /markets/baskets is the opposite of the trader's-cost convention.