@reyaxyz/common 0.344.0 → 0.344.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/types/utils/calculate.d.ts +14 -2
- package/dist/types/utils/calculate.d.ts.map +1 -1
- package/dist/utils/calculate.js +119 -16
- package/dist/utils/calculate.js.map +1 -1
- package/package.json +2 -2
- package/src/utils/calculate.ts +156 -21
package/README.md
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
|
|
7
7
|
| Statements | Branches | Functions | Lines |
|
|
8
8
|
| --------------------------- | ----------------------- | ------------------------- | ----------------- |
|
|
9
|
-
|  |  |  |  |
|
|
10
10
|
|
|
@@ -99,18 +99,30 @@ export declare const calculateRequiredMargin: ({ currIMR, currentNotional, lever
|
|
|
99
99
|
leverage: number;
|
|
100
100
|
tradeNotional: number;
|
|
101
101
|
}) => number;
|
|
102
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Calculates the maximum notional trade size (unsigned, always ≥ 0).
|
|
104
|
+
*
|
|
105
|
+
* Implements the UI quant spec v2 ("Maximum trade") with two cases:
|
|
106
|
+
* Case 1 — Extending: trade same direction as existing position.
|
|
107
|
+
* Case 2 — Reverting: decompose into (a) close position exactly, then
|
|
108
|
+
* (b) extend from zero in the opposite direction.
|
|
109
|
+
*
|
|
110
|
+
* All quadratics use the unsigned convention (t = |tradeNotional|) so the
|
|
111
|
+
* positive root always corresponds to the correct direction.
|
|
112
|
+
*/
|
|
113
|
+
export declare const calculateMaxOrderSize: ({ currIMR, currNodeBalance, currNotional, depthFactor, feeRate, isShortTrade, leverage, maxExposure, oraclePrice, poolPrice, currentLogF, netExposure, }: {
|
|
103
114
|
currIMR: number;
|
|
104
115
|
currNodeBalance: number;
|
|
105
116
|
currNotional: number;
|
|
106
117
|
depthFactor: number;
|
|
107
|
-
extendingPosition: boolean;
|
|
108
118
|
feeRate: number;
|
|
109
119
|
isShortTrade: boolean;
|
|
110
120
|
leverage: number;
|
|
111
121
|
maxExposure: number;
|
|
112
122
|
oraclePrice: number;
|
|
113
123
|
poolPrice: number;
|
|
124
|
+
currentLogF: number;
|
|
125
|
+
netExposure: number;
|
|
114
126
|
}) => number;
|
|
115
127
|
export declare const calculateIMR: ({ marketLeverages, marketPrices, positions, }: {
|
|
116
128
|
marketLeverages: Map<MarketId, number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculate.d.ts","sourceRoot":"/","sources":["utils/calculate.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,KAAK,QAAQ,GAAG,MAAM,CAAC;AACvB,KAAK,OAAO,GAAG,MAAM,CAAC;AAEtB;;;GAGG;AACH,eAAO,MAAM,oBAAoB;IAO/B,sEAAsE;gBAC1D,MAAM;IAClB,iGAAiG;mBAClF,MAAM;IACrB;;;;OAIG;iBACU,MAAM;IACnB;;;OAGG;aACM,MAAM;IACf,uCAAuC;WAChC,MAAM;MACX,MAiBH,CAAC;AAEF,eAAO,MAAM,oBAAoB;iBAKlB,MAAM;;gBAEP,MAAM;YACiC,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,kBACd,MAAM,mBACJ,MAAM;iBACP,MAAM;iBAAe,MAAM;CA+B5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc;iBAOZ,MAAM;mBACJ,MAAM;qBACJ,MAAM;iBACV,MAAM;iBACN,MAAM;MACjB,MAuBH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gCAAgC;iBAS9B,MAAM;iBACN,MAAM;mBACJ,MAAM;qBACJ,MAAM;iBACV,MAAM;iBACN,MAAM;iBACN,MAAM;MACjB,MAoBH,CAAC;AAEF,eAAO,MAAM,iBAAiB;aAInB,MAAM;mBACA,MAAM;YACgB,CAAC;AAExC,eAAO,MAAM,eAAe;iBAOb,MAAM;iBACN,MAAM;iBACN,MAAM;eACR,MAAM;mBACF,MAAM;YAIR,CAAC;AAEhB,eAAO,MAAM,kCAAkC;SAOxC,MAAM;oBACK,MAAM;aACb,OAAO;cACN,MAAM;iBACH,MAAM;YAMlB,CAAC;AAEJ,eAAO,MAAM,iBAAiB;mBAIb,MAAM;gBACT,MAAM;YAC6B,CAAC;AAElD,eAAO,MAAM,uBAAuB;aAMzB,MAAM;qBACE,MAAM;cACb,MAAM;mBACD,MAAM;YAIX,CAAC;AAEb,eAAO,MAAM,qBAAqB;
|
|
1
|
+
{"version":3,"file":"calculate.d.ts","sourceRoot":"/","sources":["utils/calculate.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/calculate.js
CHANGED
|
@@ -159,23 +159,126 @@ var calculateRequiredMargin = function (_a) {
|
|
|
159
159
|
leverage;
|
|
160
160
|
};
|
|
161
161
|
exports.calculateRequiredMargin = calculateRequiredMargin;
|
|
162
|
+
/**
|
|
163
|
+
* Calculates the maximum notional trade size (unsigned, always ≥ 0).
|
|
164
|
+
*
|
|
165
|
+
* Implements the UI quant spec v2 ("Maximum trade") with two cases:
|
|
166
|
+
* Case 1 — Extending: trade same direction as existing position.
|
|
167
|
+
* Case 2 — Reverting: decompose into (a) close position exactly, then
|
|
168
|
+
* (b) extend from zero in the opposite direction.
|
|
169
|
+
*
|
|
170
|
+
* All quadratics use the unsigned convention (t = |tradeNotional|) so the
|
|
171
|
+
* positive root always corresponds to the correct direction.
|
|
172
|
+
*/
|
|
162
173
|
var calculateMaxOrderSize = function (_a) {
|
|
163
|
-
var currIMR = _a.currIMR, currNodeBalance = _a.currNodeBalance, currNotional = _a.currNotional, depthFactor = _a.depthFactor,
|
|
164
|
-
var
|
|
165
|
-
var
|
|
166
|
-
var
|
|
167
|
-
var
|
|
168
|
-
var
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
var currIMR = _a.currIMR, currNodeBalance = _a.currNodeBalance, currNotional = _a.currNotional, depthFactor = _a.depthFactor, feeRate = _a.feeRate, isShortTrade = _a.isShortTrade, leverage = _a.leverage, maxExposure = _a.maxExposure, oraclePrice = _a.oraclePrice, poolPrice = _a.poolPrice, currentLogF = _a.currentLogF, netExposure = _a.netExposure;
|
|
175
|
+
var D = depthFactor * maxExposure;
|
|
176
|
+
var rho = poolPrice / oraclePrice;
|
|
177
|
+
var tradeSign = isShortTrade ? -1 : 1;
|
|
178
|
+
var s0 = currNotional > 0 ? 1 : currNotional < 0 ? -1 : tradeSign;
|
|
179
|
+
var absN0 = Math.abs(currNotional);
|
|
180
|
+
/**
|
|
181
|
+
* Solve the extending quadratic (spec §Case 1) for max trade size.
|
|
182
|
+
* a·t² + b·t + c = 0 where a = ρ·γ, b = s₀·(1/lev + fee) + (ρ−1), c = −surplus.
|
|
183
|
+
* Root selection: pick the root whose sign matches s₀ (dir).
|
|
184
|
+
* For rebalancing (a < 0), caps at |NE| (beyond which γ switches to unbalancing).
|
|
185
|
+
*/
|
|
186
|
+
var solveExtending = function (dir, surplus, // aka, IMRDelta
|
|
187
|
+
rho_, gamma_, isRebal, absNE) {
|
|
188
|
+
if (surplus <= 0)
|
|
189
|
+
return 0;
|
|
190
|
+
var a = rho_ * gamma_;
|
|
191
|
+
var b = dir * (1 / leverage + feeRate) + (rho_ - 1);
|
|
192
|
+
var c = -surplus;
|
|
193
|
+
// Degenerate: γ = 0 → linear equation b·t + c = 0 (rebalancing with f = 0)
|
|
194
|
+
if (a === 0) {
|
|
195
|
+
if (b === 0)
|
|
196
|
+
return isRebal ? absNE : 0;
|
|
197
|
+
var t_1 = -c / b;
|
|
198
|
+
if (t_1 * dir <= 0)
|
|
199
|
+
return isRebal ? absNE : 0;
|
|
200
|
+
return isRebal ? Math.min(Math.abs(t_1), absNE) : Math.abs(t_1);
|
|
201
|
+
}
|
|
202
|
+
var disc = b * b - 4 * a * c;
|
|
203
|
+
if (isRebal) {
|
|
204
|
+
if (disc < 0)
|
|
205
|
+
return absNE;
|
|
206
|
+
var t_2 = (-b + dir * Math.sqrt(disc)) / (2 * a);
|
|
207
|
+
return t_2 * dir <= 0 ? absNE : Math.min(Math.abs(t_2), absNE);
|
|
208
|
+
}
|
|
209
|
+
if (disc < 0)
|
|
210
|
+
throw new Error("calculateMaxOrderSize: negative discriminant (".concat(disc, ")"));
|
|
211
|
+
var t = (-b + dir * Math.sqrt(disc)) / (2 * a);
|
|
212
|
+
if (t * dir <= 0)
|
|
213
|
+
throw new Error("calculateMaxOrderSize: no valid root (".concat(t, ")"));
|
|
214
|
+
return Math.abs(t);
|
|
215
|
+
};
|
|
216
|
+
// Determine γ for a trade of given direction against the current pool state
|
|
217
|
+
var getGamma = function (dir, logF, ne) {
|
|
218
|
+
var isRebal = ne !== 0 && dir === Math.sign(ne);
|
|
219
|
+
var gamma = isRebal ? -logF / ne : 1 / D;
|
|
220
|
+
return { gamma: gamma, isRebal: isRebal };
|
|
221
|
+
};
|
|
222
|
+
// ── Case 1: Extending ──────────────────────────────────────────────────
|
|
223
|
+
if (tradeSign === s0) {
|
|
224
|
+
var _b = getGamma(tradeSign, currentLogF, netExposure), gamma = _b.gamma, isRebal = _b.isRebal;
|
|
225
|
+
return solveExtending(s0, currNodeBalance - currIMR, rho, gamma, isRebal, Math.abs(netExposure));
|
|
226
|
+
}
|
|
227
|
+
// ── Case 2: Reverting — close N₀, then re-extend ──────────────────────
|
|
228
|
+
// Step 1: Close N₀ entirely (spec §Case 2, Step 1)
|
|
229
|
+
var closeTrade = -currNotional;
|
|
230
|
+
var closeDir = -s0;
|
|
231
|
+
var _c = getGamma(closeDir, currentLogF, netExposure), gammaC = _c.gamma, closeIsRebal = _c.isRebal;
|
|
232
|
+
var closeFlipsPool = closeIsRebal && absN0 > Math.abs(netExposure);
|
|
233
|
+
// Exec price ratio: ρ·exp(γ_c·closeTrade) for non-flip, dedicated formula for flip
|
|
234
|
+
var closeExecRatio = closeFlipsPool
|
|
235
|
+
? Math.exp((closeTrade - netExposure) / D)
|
|
236
|
+
: rho * Math.exp(gammaC * closeTrade);
|
|
237
|
+
var balClose = currNodeBalance - feeRate * absN0 + closeTrade * (1 - closeExecRatio);
|
|
238
|
+
var imrClose = currIMR - absN0 / leverage;
|
|
239
|
+
var surplusClose = balClose - imrClose;
|
|
240
|
+
// Insolvency: can't fully close without going under margin.
|
|
241
|
+
// Solve partial-close quadratic (spec appendix): b has flipped feeRate sign.
|
|
242
|
+
// Falls back to full close (|N₀|) when no valid partial-close root exists.
|
|
243
|
+
if (surplusClose <= 0) {
|
|
244
|
+
var IMRDelta = currNodeBalance - currIMR;
|
|
245
|
+
var gammaP = getGamma(closeDir, currentLogF, netExposure).gamma;
|
|
246
|
+
var a = rho * gammaP;
|
|
247
|
+
var b = s0 * (1 / leverage - feeRate) + (rho - 1);
|
|
248
|
+
var c = -IMRDelta;
|
|
249
|
+
if (a === 0) {
|
|
250
|
+
if (b === 0)
|
|
251
|
+
return absN0;
|
|
252
|
+
var t_3 = -c / b;
|
|
253
|
+
if (t_3 * closeDir <= 0)
|
|
254
|
+
return absN0;
|
|
255
|
+
return Math.min(Math.abs(t_3), absN0);
|
|
256
|
+
}
|
|
257
|
+
var disc = b * b - 4 * a * c;
|
|
258
|
+
if (disc < 0)
|
|
259
|
+
return absN0;
|
|
260
|
+
var t = (-b + closeDir * Math.sqrt(disc)) / (2 * a);
|
|
261
|
+
if (t * closeDir <= 0)
|
|
262
|
+
return absN0;
|
|
263
|
+
return Math.min(Math.abs(t), absN0);
|
|
264
|
+
}
|
|
265
|
+
// Step 2: Extend from zero in -s₀ direction with post-close pool state
|
|
266
|
+
var neAfter = netExposure + currNotional;
|
|
267
|
+
var fPrime;
|
|
268
|
+
if (closeFlipsPool) {
|
|
269
|
+
fPrime = (closeTrade - netExposure) / D;
|
|
270
|
+
}
|
|
271
|
+
else if (closeIsRebal) {
|
|
272
|
+
fPrime = currentLogF * (1 + currNotional / netExposure);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
fPrime = currentLogF + closeTrade / D;
|
|
276
|
+
}
|
|
277
|
+
var rhoPrime = Math.exp(fPrime);
|
|
278
|
+
var extDir = -s0;
|
|
279
|
+
var _d = getGamma(extDir, fPrime, neAfter), gammaPrime = _d.gamma, isExtRebal = _d.isRebal;
|
|
280
|
+
return (absN0 +
|
|
281
|
+
solveExtending(extDir, surplusClose, rhoPrime, gammaPrime, isExtRebal, Math.abs(neAfter)));
|
|
179
282
|
};
|
|
180
283
|
exports.calculateMaxOrderSize = calculateMaxOrderSize;
|
|
181
284
|
var calculateIMR = function (_a) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculate.js","sourceRoot":"/","sources":["utils/calculate.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeMap } from './struct';\nimport BigNumber from 'bignumber.js';\n\nexport const POOL_IMR = 9.1;\n\ntype MarketId = string;\ntype Address = string;\n\n/**\n * Calculates the maximum amount that can be withdrawn in terms of the token\n * (e.g., if rUSD then in rUSD terms, if WETH then in WETH terms)\n */\nexport const calculateMaxWithdraw = ({\n currentIMR,\n marginBalance,\n realBalance,\n haircut,\n price,\n}: {\n /** Current Initial Margin Requirement of the account in rUSD terms */\n currentIMR: number;\n /** Current margin balance of the account (expected to already include haircuts) in rUSD terms */\n marginBalance: number;\n /**\n * Current real balance of the token the user wants to withdraw in token terms.\n * For rUSD: this equals net deposits (balanceDeprecated from v2 endpoints + realized PnL).\n * For all other tokens: this equals balanceDeprecated (since realized PnL is 0 for them).\n */\n realBalance: number;\n /**\n * Haircut parameter of the token.\n * Note: haircut for rUSD is always expected to be 0.\n */\n haircut: number;\n /** Price of the token in rUSD terms */\n price: number;\n}): number => {\n if (currentIMR < 0 || price < 0 || haircut < 0) {\n throw new Error('currentIMR, price, and haircut cannot be negative');\n }\n\n if (currentIMR === 0) {\n return realBalance;\n }\n\n if (haircut === 1 || price === 0) {\n return 0;\n }\n\n const availableMargin = marginBalance - currentIMR;\n const maxFromMargin = availableMargin / (price * (1 - haircut));\n\n return Math.max(0, Math.min(realBalance, maxFromMargin));\n};\n\nexport const calculateMaxExposure = ({\n poolBalance,\n riskFactor,\n poolIMR = POOL_IMR,\n}: {\n poolBalance: number;\n poolIMR?: number;\n riskFactor: number;\n}) => poolBalance / (poolIMR * Math.sqrt(riskFactor));\n\n/**\n * Splits a trade exposure into rebalancing and unbalancing portions relative to pool net exposure.\n * Rebalancing reduces pool's absolute exposure; unbalancing increases it.\n */\nexport const splitTradeExposure = (\n tradeExposure: number,\n poolNetExposure: number,\n): { rebalancing: number; unbalancing: number } => {\n if (tradeExposure === 0) {\n return { rebalancing: 0, unbalancing: 0 };\n }\n\n // If pool has no exposure, entire trade is unbalancing\n if (poolNetExposure === 0) {\n return { rebalancing: 0, unbalancing: tradeExposure };\n }\n\n // Opposite sign means trade increases pool exposure → pure unbalancing\n const sameSign =\n (poolNetExposure > 0 && tradeExposure > 0) ||\n (poolNetExposure < 0 && tradeExposure < 0);\n if (!sameSign) {\n return { rebalancing: 0, unbalancing: tradeExposure };\n }\n\n // Same sign: trade reduces pool exposure (pool takes opposite side)\n const absPool = Math.abs(poolNetExposure);\n const absTrade = Math.abs(tradeExposure);\n\n if (absTrade <= absPool) {\n // Pure rebalancing — trade doesn't cross zero\n return { rebalancing: tradeExposure, unbalancing: 0 };\n }\n\n // Mixed: rebalance up to pool exposure, then unbalance the rest\n const rebalancing = poolNetExposure;\n const unbalancing = tradeExposure - rebalancing;\n return { rebalancing, unbalancing };\n};\n\n/**\n * Computes the new log price multiplier (logF) after a trade, handling both\n * rebalancing and unbalancing portions.\n *\n * Mirrors on-chain logic in PriceMultiplier.sol:computeNewLogPriceMultiplier.\n */\nexport const computeNewLogF = ({\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n}: {\n currentLogF: number;\n tradeExposure: number;\n poolNetExposure: number;\n depthFactor: number;\n maxExposure: number;\n}): number => {\n if (tradeExposure === 0) return currentLogF;\n\n const { rebalancing, unbalancing } = splitTradeExposure(\n tradeExposure,\n poolNetExposure,\n );\n\n // Case 1: Has unbalancing portion (includes mixed trades)\n if (unbalancing !== 0) {\n // If also rebalancing, it brings logF to 0 by definition (trade crosses zero)\n const startLogF = rebalancing === 0 ? currentLogF : 0;\n return startLogF + unbalancing / (depthFactor * maxExposure);\n }\n\n // Case 2: Only rebalancing\n // Both rebalancing and poolNetExposure have the same sign, so ratio is in [0, 1]\n if (rebalancing !== 0 && poolNetExposure !== 0) {\n const ratio = rebalancing / poolNetExposure;\n return currentLogF * (1 - ratio);\n }\n\n return currentLogF;\n};\n\n/**\n * Estimates the execution price for a trade using the exponential logPriceMultiplier formula.\n *\n * Mirrors on-chain logic:\n * 1. computeNewLogPriceMultiplier (PriceMultiplier.sol)\n * 2. computeAmmPrice: ammPrice = oraclePrice * exp(logF)\n * 3. computeSignedSpread: executionPrice = ammPrice * (1 + signedSpread)\n *\n * @audit spreadDiscount not applied — known limitation, to be addressed later\n * @audit priceSpacing rounding not applied\n */\nexport const calculateEstimatedExecutionPrice = ({\n oraclePrice,\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n priceSpread,\n}: {\n oraclePrice: number;\n currentLogF: number;\n tradeExposure: number;\n poolNetExposure: number;\n depthFactor: number;\n maxExposure: number;\n priceSpread: number;\n}): number => {\n if (tradeExposure === 0) {\n return oraclePrice * Math.exp(currentLogF);\n }\n\n // 1. Compute new logF after trade impact\n const newLogF = computeNewLogF({\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n });\n\n // 2. Compute AMM price: oraclePrice * exp(newLogF)\n const ammPrice = oraclePrice * Math.exp(newLogF);\n\n // 3. Apply signed spread\n const signedSpread = tradeExposure > 0 ? priceSpread : -priceSpread;\n return Math.max(0, ammPrice * (1 + signedSpread));\n};\n\nexport const calculateTradeFee = ({\n feeRate,\n tradeNotional,\n}: {\n feeRate: number;\n tradeNotional: number;\n}) => feeRate * Math.abs(tradeNotional);\n\nexport const calculateSpread = ({\n depthFactor,\n maxExposure,\n oraclePrice,\n poolPrice,\n tradeNotional,\n}: {\n depthFactor: number;\n maxExposure: number;\n oraclePrice: number;\n poolPrice: number;\n tradeNotional: number;\n}) =>\n (poolPrice / oraclePrice) *\n (1 + tradeNotional / (depthFactor * maxExposure) - 1) *\n tradeNotional;\n\nexport const calculateEstimatedLiquidationPrice = ({\n LMR,\n accountBalance,\n isShort,\n notional,\n oraclePrice,\n}: {\n LMR: number;\n accountBalance: number;\n isShort: boolean;\n notional: number;\n oraclePrice: number;\n}) =>\n Math.max(\n 0,\n oraclePrice *\n (1 - ((accountBalance - LMR) / notional) * (isShort ? -1 : 1)),\n );\n\nexport const calculateLeverage = ({\n imrMultiplier,\n riskFactor,\n}: {\n imrMultiplier: number;\n riskFactor: number;\n}) => 1 / (imrMultiplier * Math.sqrt(riskFactor));\n\nexport const calculateRequiredMargin = ({\n currIMR,\n currentNotional,\n leverage,\n tradeNotional,\n}: {\n currIMR: number;\n currentNotional: number;\n leverage: number;\n tradeNotional: number;\n}) =>\n currIMR +\n (Math.abs(currentNotional + tradeNotional) - Math.abs(currentNotional)) /\n leverage;\n\nexport const calculateMaxOrderSize = ({\n currIMR,\n currNodeBalance,\n currNotional,\n depthFactor,\n extendingPosition,\n feeRate,\n isShortTrade,\n leverage,\n maxExposure,\n oraclePrice,\n poolPrice,\n}: {\n currIMR: number;\n currNodeBalance: number;\n currNotional: number;\n depthFactor: number;\n extendingPosition: boolean;\n feeRate: number;\n isShortTrade: boolean;\n leverage: number;\n maxExposure: number;\n oraclePrice: number;\n poolPrice: number;\n}) => {\n const a = poolPrice / oraclePrice;\n const c = 1 / (depthFactor * maxExposure);\n const R = a - 1 - feeRate * (isShortTrade ? -1 : 1);\n const SN = currNotional < 0 ? -1 : 1;\n const Q = R - (SN / leverage) * (extendingPosition ? 1 : -1);\n return Math.abs(\n (-1 * Q +\n Math.sqrt(\n Math.pow(Q, 2) -\n 4 *\n a *\n c *\n (currNodeBalance -\n currIMR +\n (extendingPosition ? 0 : ((2 * SN) / leverage) * currNotional)),\n ) *\n (isShortTrade ? 1 : -1)) /\n (2 * a * c),\n );\n};\n\nexport const calculateIMR = ({\n marketLeverages,\n marketPrices,\n positions,\n}: {\n marketLeverages: Map<MarketId, number>;\n marketPrices: Map<MarketId, number>;\n positions: Map<MarketId, number>;\n}) => {\n return Array.from(positions.entries()).reduce(\n (sum, [marketId, positionSize]) => {\n const leverage = marketLeverages.get(marketId);\n return leverage\n ? sum +\n (Math.abs(positionSize) * (marketPrices.get(marketId) ?? 0)) /\n leverage\n : sum;\n },\n 0,\n );\n};\n\nexport const calculateLMR = ({\n marketPrices,\n positions,\n riskFactors,\n marketId,\n tradeSize,\n}: {\n marketId?: string;\n marketPrices: Map<MarketId, number>;\n positions: Map<MarketId, number>;\n riskFactors: Map<MarketId, number>;\n tradeSize?: number;\n}) =>\n Array.from(\n (marketId && tradeSize\n ? mergeMap(positions, [\n [marketId, (positions.get(marketId) ?? 0) + tradeSize],\n ])\n : positions\n ).entries(),\n ).reduce((sum, [marketId, positionSize]) => {\n const riskFactor = riskFactors.get(marketId);\n return riskFactor\n ? sum +\n Math.abs(positionSize) *\n (marketPrices.get(marketId) ?? 0) *\n Math.sqrt(riskFactor)\n : sum;\n }, 0);\n\n// if account balance is below LMR position is liquidable\n\nexport const calculateMarginRatio = ({\n LMR,\n totalBalance,\n tradeCost,\n}: {\n LMR: number;\n totalBalance: number;\n tradeCost: number;\n}) => {\n if (LMR === 0) {\n return 0;\n }\n if (tradeCost > totalBalance) {\n return 1;\n }\n if (totalBalance === tradeCost) {\n return Infinity;\n }\n return Math.min(1, LMR / (totalBalance - tradeCost));\n};\n\nexport const calculateTotalMargin = ({\n marketsTrackers,\n accountBalances,\n assetPrices,\n markPrices,\n marketsTokenInfo,\n positions,\n rUSDAddress,\n}: {\n accountBalances: Map<Address, number>;\n assetPrices: Map<Address, number>;\n markPrices: Map<Address, number>;\n marketsTokenInfo: Map<\n MarketId,\n {\n quoteTokenId: string;\n underlyingAssetId: string;\n }\n >;\n marketsTrackers: Map<\n MarketId,\n {\n longADLUnwindPrice: number;\n longBaseMultiplier: number;\n longFundingValue: number;\n shortADLUnwindPrice: number;\n shortBaseMultiplier: number;\n shortFundingValue: number;\n }\n >;\n positions: {\n adlUnwindPrice: number;\n base: number;\n baseMultiplier: number;\n fundingValue: number;\n lastPrice: number;\n marketId: string;\n realizedPnl: number;\n }[];\n rUSDAddress?: string;\n}) => {\n const pnl = new Map<Address, number>();\n const rUSDPrice = (rUSDAddress && assetPrices.get(rUSDAddress)) ?? 1;\n positions.forEach((position) => {\n const marketTracker = marketsTrackers?.get(position.marketId);\n const tokenInfo = marketsTokenInfo.get(position.marketId);\n if (!tokenInfo) return;\n let fundingCashFlow = 0;\n let adlCashFlow = 0;\n\n if (marketTracker) {\n // fundingCashFlow\n const marketTrackerFundingValue =\n position.base < 0\n ? marketTracker.shortFundingValue\n : marketTracker.longFundingValue;\n const trackerDelta = marketTrackerFundingValue - position.fundingValue;\n fundingCashFlow =\n (trackerDelta / position.baseMultiplier) * -1 * position.base;\n\n // adlCashFlow\n const adlUnwindPrice =\n ((position.base < 0\n ? marketTracker.shortADLUnwindPrice\n : marketTracker.longADLUnwindPrice) -\n position.adlUnwindPrice) /\n position.baseMultiplier;\n const baseMultiplier =\n (position.base < 0\n ? marketTracker.shortBaseMultiplier\n : marketTracker.longBaseMultiplier) / position.baseMultiplier;\n const lastPriceCoefficient = 1 - baseMultiplier;\n const initialPrice = lastPriceCoefficient * position.lastPrice;\n adlCashFlow = (adlUnwindPrice - initialPrice) * position.base;\n }\n\n const unrealizedPnl =\n ((markPrices.get(tokenInfo.quoteTokenId) ?? 0) - position.lastPrice) *\n position.base;\n\n pnl.set(\n tokenInfo.underlyingAssetId,\n (pnl.get(tokenInfo.underlyingAssetId) ?? 0) +\n position.realizedPnl +\n fundingCashFlow +\n adlCashFlow +\n unrealizedPnl,\n );\n });\n\n return Array.from(accountBalances.entries()).reduce(\n (sum, [address, balance]) =>\n sum +\n (balance + (pnl.get(address) ?? 0)) *\n (address === rUSDAddress\n ? 1\n : (assetPrices.get(address) ?? 0) / (rUSDPrice || 1)),\n 0,\n );\n};\n\nexport const calculateFundingPnl = ({\n marketFundingValue,\n marketBaseMultiplier,\n positionAvgEntryFundingValue,\n positionAdjustedBase,\n}: {\n marketFundingValue: number;\n marketBaseMultiplier: number;\n positionAvgEntryFundingValue: number;\n positionAdjustedBase: number;\n}): number => {\n return (\n -1 *\n (((marketFundingValue - positionAvgEntryFundingValue) *\n positionAdjustedBase) /\n marketBaseMultiplier)\n );\n};\n\nexport const calculatePricePnl = ({\n price,\n positionAvgEntryPrice,\n positionAdjustedBase,\n}: {\n price: number;\n positionAvgEntryPrice: number;\n positionAdjustedBase: number;\n}): number => {\n return (price - positionAvgEntryPrice) * positionAdjustedBase;\n};\n\nexport const calculateRealBalance = (\n netDeposits: BigNumber,\n realized_pnl: BigNumber,\n) => {\n return netDeposits.plus(realized_pnl);\n};\n\nexport const calculatePositionAdjustedQty = (\n origQty: BigNumber,\n marketBaseMultiplier: BigNumber,\n positionBaseMultiplier: BigNumber,\n): BigNumber => {\n return origQty.times(marketBaseMultiplier).div(positionBaseMultiplier);\n};\n\n/**\n * Linearly interpolate a depth ratio from a (thresholds, ratios) curve.\n * The curve implicitly starts at (exposure=0, ratio=1.0).\n * - Between thresholds: linear interpolation\n * - Above last threshold: last ratio (flat extrapolation)\n *\n * @param thresholds - Sorted ascending exposure thresholds in notional USD (must be non-empty)\n * @param ratios - Depth ratio at each threshold (same length as thresholds, must be non-empty)\n * @param exposure - Absolute exposure notional (must be >= 0)\n * @throws if thresholds or ratios are empty, or if they have different lengths\n */\nexport const interpolateDepthRatio = (\n thresholds: number[],\n ratios: number[],\n exposure: number,\n): number => {\n if (exposure < 0) {\n throw new Error('interpolateDepthRatio: exposure must be >= 0');\n }\n if (thresholds.length === 0 || ratios.length === 0) {\n throw new Error(\n 'interpolateDepthRatio: thresholds and ratios must be non-empty',\n );\n }\n if (thresholds.length !== ratios.length) {\n throw new Error(\n 'interpolateDepthRatio: thresholds and ratios must have equal length',\n );\n }\n\n const allThresholds = [0, ...thresholds];\n const allRatios = [1.0, ...ratios];\n\n if (exposure === 0) return 1.0;\n if (exposure >= allThresholds[allThresholds.length - 1]) {\n return allRatios[allRatios.length - 1];\n }\n\n for (let i = 0; i < allThresholds.length - 1; i++) {\n if (exposure <= allThresholds[i + 1]) {\n const t =\n (exposure - allThresholds[i]) /\n (allThresholds[i + 1] - allThresholds[i]);\n return allRatios[i] + t * (allRatios[i + 1] - allRatios[i]);\n }\n }\n\n throw new Error('interpolateDepthRatio: unreachable');\n};\n\n/**\n * Calculate the dynamic depth factor for a trade given pool state and config.\n *\n * The pool takes the opposite side of the trade, so:\n * poolNotionalAfterTrade = currentPoolNotional - signedTradeNotional\n *\n * The depth ratio is interpolated from the exposure curve, then multiplied\n * by baseDepth to produce the final depth factor.\n *\n * @param baseDepth - Base depth multiplier for this market\n * @param thresholds - Sorted ascending exposure thresholds (notional USD)\n * @param ratios - Depth ratio at each threshold\n * @param currentPoolNotional - Pool's current notional in this market (signed)\n * @param signedTradeNotional - Trade notional (positive=buy, negative=sell)\n */\nexport const calculateDynamicDepthFactor = ({\n baseDepth,\n thresholds,\n ratios,\n currentPoolNotional,\n signedTradeNotional,\n}: {\n baseDepth: number;\n thresholds: number[];\n ratios: number[];\n currentPoolNotional: number;\n signedTradeNotional: number;\n}): number => {\n const poolNotionalAfterTrade = currentPoolNotional - signedTradeNotional;\n const absExposureNotional = Math.abs(poolNotionalAfterTrade);\n const depthRatio = interpolateDepthRatio(\n thresholds,\n ratios,\n absExposureNotional,\n );\n return depthRatio * baseDepth;\n};\n\nexport const calculatePositionAdlPnL = ({\n marketTrackerAdlUnwindPrice,\n marketTrackerBaseMultiplier,\n positionBase,\n positionAvgEntryPrice,\n positionTrackerBaseMultiplier,\n positionTrackerAdlUnwindPrice,\n}: {\n marketTrackerAdlUnwindPrice: BigNumber;\n marketTrackerBaseMultiplier: BigNumber;\n positionBase: BigNumber;\n positionAvgEntryPrice: BigNumber;\n positionTrackerBaseMultiplier: BigNumber;\n positionTrackerAdlUnwindPrice: BigNumber;\n}): BigNumber => {\n const currentAdlUnwindPrice = marketTrackerAdlUnwindPrice\n .minus(positionTrackerAdlUnwindPrice)\n .multipliedBy(1e18)\n .div(positionTrackerBaseMultiplier);\n\n const initialPrice = positionAvgEntryPrice\n .times(\n BigNumber(1e18).minus(\n marketTrackerBaseMultiplier\n .multipliedBy(1e18)\n .div(positionTrackerBaseMultiplier),\n ),\n )\n .div(1e18);\n\n const adlPnL = positionBase\n .times(currentAdlUnwindPrice.minus(initialPrice))\n .div(1e18);\n\n return adlPnL;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"calculate.js","sourceRoot":"/","sources":["utils/calculate.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeMap } from './struct';\nimport BigNumber from 'bignumber.js';\n\nexport const POOL_IMR = 9.1;\n\ntype MarketId = string;\ntype Address = string;\n\n/**\n * Calculates the maximum amount that can be withdrawn in terms of the token\n * (e.g., if rUSD then in rUSD terms, if WETH then in WETH terms)\n */\nexport const calculateMaxWithdraw = ({\n currentIMR,\n marginBalance,\n realBalance,\n haircut,\n price,\n}: {\n /** Current Initial Margin Requirement of the account in rUSD terms */\n currentIMR: number;\n /** Current margin balance of the account (expected to already include haircuts) in rUSD terms */\n marginBalance: number;\n /**\n * Current real balance of the token the user wants to withdraw in token terms.\n * For rUSD: this equals net deposits (balanceDeprecated from v2 endpoints + realized PnL).\n * For all other tokens: this equals balanceDeprecated (since realized PnL is 0 for them).\n */\n realBalance: number;\n /**\n * Haircut parameter of the token.\n * Note: haircut for rUSD is always expected to be 0.\n */\n haircut: number;\n /** Price of the token in rUSD terms */\n price: number;\n}): number => {\n if (currentIMR < 0 || price < 0 || haircut < 0) {\n throw new Error('currentIMR, price, and haircut cannot be negative');\n }\n\n if (currentIMR === 0) {\n return realBalance;\n }\n\n if (haircut === 1 || price === 0) {\n return 0;\n }\n\n const availableMargin = marginBalance - currentIMR;\n const maxFromMargin = availableMargin / (price * (1 - haircut));\n\n return Math.max(0, Math.min(realBalance, maxFromMargin));\n};\n\nexport const calculateMaxExposure = ({\n poolBalance,\n riskFactor,\n poolIMR = POOL_IMR,\n}: {\n poolBalance: number;\n poolIMR?: number;\n riskFactor: number;\n}) => poolBalance / (poolIMR * Math.sqrt(riskFactor));\n\n/**\n * Splits a trade exposure into rebalancing and unbalancing portions relative to pool net exposure.\n * Rebalancing reduces pool's absolute exposure; unbalancing increases it.\n */\nexport const splitTradeExposure = (\n tradeExposure: number,\n poolNetExposure: number,\n): { rebalancing: number; unbalancing: number } => {\n if (tradeExposure === 0) {\n return { rebalancing: 0, unbalancing: 0 };\n }\n\n // If pool has no exposure, entire trade is unbalancing\n if (poolNetExposure === 0) {\n return { rebalancing: 0, unbalancing: tradeExposure };\n }\n\n // Opposite sign means trade increases pool exposure → pure unbalancing\n const sameSign =\n (poolNetExposure > 0 && tradeExposure > 0) ||\n (poolNetExposure < 0 && tradeExposure < 0);\n if (!sameSign) {\n return { rebalancing: 0, unbalancing: tradeExposure };\n }\n\n // Same sign: trade reduces pool exposure (pool takes opposite side)\n const absPool = Math.abs(poolNetExposure);\n const absTrade = Math.abs(tradeExposure);\n\n if (absTrade <= absPool) {\n // Pure rebalancing — trade doesn't cross zero\n return { rebalancing: tradeExposure, unbalancing: 0 };\n }\n\n // Mixed: rebalance up to pool exposure, then unbalance the rest\n const rebalancing = poolNetExposure;\n const unbalancing = tradeExposure - rebalancing;\n return { rebalancing, unbalancing };\n};\n\n/**\n * Computes the new log price multiplier (logF) after a trade, handling both\n * rebalancing and unbalancing portions.\n *\n * Mirrors on-chain logic in PriceMultiplier.sol:computeNewLogPriceMultiplier.\n */\nexport const computeNewLogF = ({\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n}: {\n currentLogF: number;\n tradeExposure: number;\n poolNetExposure: number;\n depthFactor: number;\n maxExposure: number;\n}): number => {\n if (tradeExposure === 0) return currentLogF;\n\n const { rebalancing, unbalancing } = splitTradeExposure(\n tradeExposure,\n poolNetExposure,\n );\n\n // Case 1: Has unbalancing portion (includes mixed trades)\n if (unbalancing !== 0) {\n // If also rebalancing, it brings logF to 0 by definition (trade crosses zero)\n const startLogF = rebalancing === 0 ? currentLogF : 0;\n return startLogF + unbalancing / (depthFactor * maxExposure);\n }\n\n // Case 2: Only rebalancing\n // Both rebalancing and poolNetExposure have the same sign, so ratio is in [0, 1]\n if (rebalancing !== 0 && poolNetExposure !== 0) {\n const ratio = rebalancing / poolNetExposure;\n return currentLogF * (1 - ratio);\n }\n\n return currentLogF;\n};\n\n/**\n * Estimates the execution price for a trade using the exponential logPriceMultiplier formula.\n *\n * Mirrors on-chain logic:\n * 1. computeNewLogPriceMultiplier (PriceMultiplier.sol)\n * 2. computeAmmPrice: ammPrice = oraclePrice * exp(logF)\n * 3. computeSignedSpread: executionPrice = ammPrice * (1 + signedSpread)\n *\n * @audit spreadDiscount not applied — known limitation, to be addressed later\n * @audit priceSpacing rounding not applied\n */\nexport const calculateEstimatedExecutionPrice = ({\n oraclePrice,\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n priceSpread,\n}: {\n oraclePrice: number;\n currentLogF: number;\n tradeExposure: number;\n poolNetExposure: number;\n depthFactor: number;\n maxExposure: number;\n priceSpread: number;\n}): number => {\n if (tradeExposure === 0) {\n return oraclePrice * Math.exp(currentLogF);\n }\n\n // 1. Compute new logF after trade impact\n const newLogF = computeNewLogF({\n currentLogF,\n tradeExposure,\n poolNetExposure,\n depthFactor,\n maxExposure,\n });\n\n // 2. Compute AMM price: oraclePrice * exp(newLogF)\n const ammPrice = oraclePrice * Math.exp(newLogF);\n\n // 3. Apply signed spread\n const signedSpread = tradeExposure > 0 ? priceSpread : -priceSpread;\n return Math.max(0, ammPrice * (1 + signedSpread));\n};\n\nexport const calculateTradeFee = ({\n feeRate,\n tradeNotional,\n}: {\n feeRate: number;\n tradeNotional: number;\n}) => feeRate * Math.abs(tradeNotional);\n\nexport const calculateSpread = ({\n depthFactor,\n maxExposure,\n oraclePrice,\n poolPrice,\n tradeNotional,\n}: {\n depthFactor: number;\n maxExposure: number;\n oraclePrice: number;\n poolPrice: number;\n tradeNotional: number;\n}) =>\n (poolPrice / oraclePrice) *\n (1 + tradeNotional / (depthFactor * maxExposure) - 1) *\n tradeNotional;\n\nexport const calculateEstimatedLiquidationPrice = ({\n LMR,\n accountBalance,\n isShort,\n notional,\n oraclePrice,\n}: {\n LMR: number;\n accountBalance: number;\n isShort: boolean;\n notional: number;\n oraclePrice: number;\n}) =>\n Math.max(\n 0,\n oraclePrice *\n (1 - ((accountBalance - LMR) / notional) * (isShort ? -1 : 1)),\n );\n\nexport const calculateLeverage = ({\n imrMultiplier,\n riskFactor,\n}: {\n imrMultiplier: number;\n riskFactor: number;\n}) => 1 / (imrMultiplier * Math.sqrt(riskFactor));\n\nexport const calculateRequiredMargin = ({\n currIMR,\n currentNotional,\n leverage,\n tradeNotional,\n}: {\n currIMR: number;\n currentNotional: number;\n leverage: number;\n tradeNotional: number;\n}) =>\n currIMR +\n (Math.abs(currentNotional + tradeNotional) - Math.abs(currentNotional)) /\n leverage;\n\n/**\n * Calculates the maximum notional trade size (unsigned, always ≥ 0).\n *\n * Implements the UI quant spec v2 (\"Maximum trade\") with two cases:\n * Case 1 — Extending: trade same direction as existing position.\n * Case 2 — Reverting: decompose into (a) close position exactly, then\n * (b) extend from zero in the opposite direction.\n *\n * All quadratics use the unsigned convention (t = |tradeNotional|) so the\n * positive root always corresponds to the correct direction.\n */\nexport const calculateMaxOrderSize = ({\n currIMR,\n currNodeBalance,\n currNotional,\n depthFactor,\n feeRate,\n isShortTrade,\n leverage,\n maxExposure,\n oraclePrice,\n poolPrice,\n currentLogF,\n netExposure,\n}: {\n currIMR: number;\n currNodeBalance: number;\n currNotional: number;\n depthFactor: number;\n feeRate: number;\n isShortTrade: boolean;\n leverage: number;\n maxExposure: number;\n oraclePrice: number;\n poolPrice: number;\n currentLogF: number;\n netExposure: number;\n}): number => {\n const D = depthFactor * maxExposure;\n const rho = poolPrice / oraclePrice;\n const tradeSign = isShortTrade ? -1 : 1;\n const s0 = currNotional > 0 ? 1 : currNotional < 0 ? -1 : tradeSign;\n const absN0 = Math.abs(currNotional);\n\n /**\n * Solve the extending quadratic (spec §Case 1) for max trade size.\n * a·t² + b·t + c = 0 where a = ρ·γ, b = s₀·(1/lev + fee) + (ρ−1), c = −surplus.\n * Root selection: pick the root whose sign matches s₀ (dir).\n * For rebalancing (a < 0), caps at |NE| (beyond which γ switches to unbalancing).\n */\n const solveExtending = (\n dir: number,\n surplus: number, // aka, IMRDelta\n rho_: number,\n gamma_: number,\n isRebal: boolean,\n absNE: number,\n ): number => {\n if (surplus <= 0) return 0;\n const a = rho_ * gamma_;\n const b = dir * (1 / leverage + feeRate) + (rho_ - 1);\n const c = -surplus;\n // Degenerate: γ = 0 → linear equation b·t + c = 0 (rebalancing with f = 0)\n if (a === 0) {\n if (b === 0) return isRebal ? absNE : 0;\n const t = -c / b;\n if (t * dir <= 0) return isRebal ? absNE : 0;\n return isRebal ? Math.min(Math.abs(t), absNE) : Math.abs(t);\n }\n const disc = b * b - 4 * a * c;\n if (isRebal) {\n if (disc < 0) return absNE;\n const t = (-b + dir * Math.sqrt(disc)) / (2 * a);\n return t * dir <= 0 ? absNE : Math.min(Math.abs(t), absNE);\n }\n if (disc < 0)\n throw new Error(`calculateMaxOrderSize: negative discriminant (${disc})`);\n const t = (-b + dir * Math.sqrt(disc)) / (2 * a);\n if (t * dir <= 0)\n throw new Error(`calculateMaxOrderSize: no valid root (${t})`);\n return Math.abs(t);\n };\n\n // Determine γ for a trade of given direction against the current pool state\n const getGamma = (dir: number, logF: number, ne: number) => {\n const isRebal = ne !== 0 && dir === Math.sign(ne);\n const gamma = isRebal ? -logF / ne : 1 / D;\n return { gamma, isRebal };\n };\n\n // ── Case 1: Extending ──────────────────────────────────────────────────\n if (tradeSign === s0) {\n const { gamma, isRebal } = getGamma(tradeSign, currentLogF, netExposure);\n return solveExtending(\n s0,\n currNodeBalance - currIMR,\n rho,\n gamma,\n isRebal,\n Math.abs(netExposure),\n );\n }\n\n // ── Case 2: Reverting — close N₀, then re-extend ──────────────────────\n\n // Step 1: Close N₀ entirely (spec §Case 2, Step 1)\n const closeTrade = -currNotional;\n const closeDir = -s0;\n const { gamma: gammaC, isRebal: closeIsRebal } = getGamma(\n closeDir,\n currentLogF,\n netExposure,\n );\n const closeFlipsPool = closeIsRebal && absN0 > Math.abs(netExposure);\n\n // Exec price ratio: ρ·exp(γ_c·closeTrade) for non-flip, dedicated formula for flip\n const closeExecRatio = closeFlipsPool\n ? Math.exp((closeTrade - netExposure) / D)\n : rho * Math.exp(gammaC * closeTrade);\n\n const balClose =\n currNodeBalance - feeRate * absN0 + closeTrade * (1 - closeExecRatio);\n const imrClose = currIMR - absN0 / leverage;\n const surplusClose = balClose - imrClose;\n\n // Insolvency: can't fully close without going under margin.\n // Solve partial-close quadratic (spec appendix): b has flipped feeRate sign.\n // Falls back to full close (|N₀|) when no valid partial-close root exists.\n if (surplusClose <= 0) {\n const IMRDelta = currNodeBalance - currIMR;\n const { gamma: gammaP } = getGamma(closeDir, currentLogF, netExposure);\n const a = rho * gammaP;\n const b = s0 * (1 / leverage - feeRate) + (rho - 1);\n const c = -IMRDelta;\n\n if (a === 0) {\n if (b === 0) return absN0;\n const t = -c / b;\n if (t * closeDir <= 0) return absN0;\n return Math.min(Math.abs(t), absN0);\n }\n\n const disc = b * b - 4 * a * c;\n if (disc < 0) return absN0;\n const t = (-b + closeDir * Math.sqrt(disc)) / (2 * a);\n if (t * closeDir <= 0) return absN0;\n return Math.min(Math.abs(t), absN0);\n }\n\n // Step 2: Extend from zero in -s₀ direction with post-close pool state\n const neAfter = netExposure + currNotional;\n let fPrime: number;\n if (closeFlipsPool) {\n fPrime = (closeTrade - netExposure) / D;\n } else if (closeIsRebal) {\n fPrime = currentLogF * (1 + currNotional / netExposure);\n } else {\n fPrime = currentLogF + closeTrade / D;\n }\n const rhoPrime = Math.exp(fPrime);\n\n const extDir = -s0;\n const { gamma: gammaPrime, isRebal: isExtRebal } = getGamma(\n extDir,\n fPrime,\n neAfter,\n );\n\n return (\n absN0 +\n solveExtending(\n extDir,\n surplusClose,\n rhoPrime,\n gammaPrime,\n isExtRebal,\n Math.abs(neAfter),\n )\n );\n};\n\nexport const calculateIMR = ({\n marketLeverages,\n marketPrices,\n positions,\n}: {\n marketLeverages: Map<MarketId, number>;\n marketPrices: Map<MarketId, number>;\n positions: Map<MarketId, number>;\n}) => {\n return Array.from(positions.entries()).reduce(\n (sum, [marketId, positionSize]) => {\n const leverage = marketLeverages.get(marketId);\n return leverage\n ? sum +\n (Math.abs(positionSize) * (marketPrices.get(marketId) ?? 0)) /\n leverage\n : sum;\n },\n 0,\n );\n};\n\nexport const calculateLMR = ({\n marketPrices,\n positions,\n riskFactors,\n marketId,\n tradeSize,\n}: {\n marketId?: string;\n marketPrices: Map<MarketId, number>;\n positions: Map<MarketId, number>;\n riskFactors: Map<MarketId, number>;\n tradeSize?: number;\n}) =>\n Array.from(\n (marketId && tradeSize\n ? mergeMap(positions, [\n [marketId, (positions.get(marketId) ?? 0) + tradeSize],\n ])\n : positions\n ).entries(),\n ).reduce((sum, [marketId, positionSize]) => {\n const riskFactor = riskFactors.get(marketId);\n return riskFactor\n ? sum +\n Math.abs(positionSize) *\n (marketPrices.get(marketId) ?? 0) *\n Math.sqrt(riskFactor)\n : sum;\n }, 0);\n\n// if account balance is below LMR position is liquidable\n\nexport const calculateMarginRatio = ({\n LMR,\n totalBalance,\n tradeCost,\n}: {\n LMR: number;\n totalBalance: number;\n tradeCost: number;\n}) => {\n if (LMR === 0) {\n return 0;\n }\n if (tradeCost > totalBalance) {\n return 1;\n }\n if (totalBalance === tradeCost) {\n return Infinity;\n }\n return Math.min(1, LMR / (totalBalance - tradeCost));\n};\n\nexport const calculateTotalMargin = ({\n marketsTrackers,\n accountBalances,\n assetPrices,\n markPrices,\n marketsTokenInfo,\n positions,\n rUSDAddress,\n}: {\n accountBalances: Map<Address, number>;\n assetPrices: Map<Address, number>;\n markPrices: Map<Address, number>;\n marketsTokenInfo: Map<\n MarketId,\n {\n quoteTokenId: string;\n underlyingAssetId: string;\n }\n >;\n marketsTrackers: Map<\n MarketId,\n {\n longADLUnwindPrice: number;\n longBaseMultiplier: number;\n longFundingValue: number;\n shortADLUnwindPrice: number;\n shortBaseMultiplier: number;\n shortFundingValue: number;\n }\n >;\n positions: {\n adlUnwindPrice: number;\n base: number;\n baseMultiplier: number;\n fundingValue: number;\n lastPrice: number;\n marketId: string;\n realizedPnl: number;\n }[];\n rUSDAddress?: string;\n}) => {\n const pnl = new Map<Address, number>();\n const rUSDPrice = (rUSDAddress && assetPrices.get(rUSDAddress)) ?? 1;\n positions.forEach((position) => {\n const marketTracker = marketsTrackers?.get(position.marketId);\n const tokenInfo = marketsTokenInfo.get(position.marketId);\n if (!tokenInfo) return;\n let fundingCashFlow = 0;\n let adlCashFlow = 0;\n\n if (marketTracker) {\n // fundingCashFlow\n const marketTrackerFundingValue =\n position.base < 0\n ? marketTracker.shortFundingValue\n : marketTracker.longFundingValue;\n const trackerDelta = marketTrackerFundingValue - position.fundingValue;\n fundingCashFlow =\n (trackerDelta / position.baseMultiplier) * -1 * position.base;\n\n // adlCashFlow\n const adlUnwindPrice =\n ((position.base < 0\n ? marketTracker.shortADLUnwindPrice\n : marketTracker.longADLUnwindPrice) -\n position.adlUnwindPrice) /\n position.baseMultiplier;\n const baseMultiplier =\n (position.base < 0\n ? marketTracker.shortBaseMultiplier\n : marketTracker.longBaseMultiplier) / position.baseMultiplier;\n const lastPriceCoefficient = 1 - baseMultiplier;\n const initialPrice = lastPriceCoefficient * position.lastPrice;\n adlCashFlow = (adlUnwindPrice - initialPrice) * position.base;\n }\n\n const unrealizedPnl =\n ((markPrices.get(tokenInfo.quoteTokenId) ?? 0) - position.lastPrice) *\n position.base;\n\n pnl.set(\n tokenInfo.underlyingAssetId,\n (pnl.get(tokenInfo.underlyingAssetId) ?? 0) +\n position.realizedPnl +\n fundingCashFlow +\n adlCashFlow +\n unrealizedPnl,\n );\n });\n\n return Array.from(accountBalances.entries()).reduce(\n (sum, [address, balance]) =>\n sum +\n (balance + (pnl.get(address) ?? 0)) *\n (address === rUSDAddress\n ? 1\n : (assetPrices.get(address) ?? 0) / (rUSDPrice || 1)),\n 0,\n );\n};\n\nexport const calculateFundingPnl = ({\n marketFundingValue,\n marketBaseMultiplier,\n positionAvgEntryFundingValue,\n positionAdjustedBase,\n}: {\n marketFundingValue: number;\n marketBaseMultiplier: number;\n positionAvgEntryFundingValue: number;\n positionAdjustedBase: number;\n}): number => {\n return (\n -1 *\n (((marketFundingValue - positionAvgEntryFundingValue) *\n positionAdjustedBase) /\n marketBaseMultiplier)\n );\n};\n\nexport const calculatePricePnl = ({\n price,\n positionAvgEntryPrice,\n positionAdjustedBase,\n}: {\n price: number;\n positionAvgEntryPrice: number;\n positionAdjustedBase: number;\n}): number => {\n return (price - positionAvgEntryPrice) * positionAdjustedBase;\n};\n\nexport const calculateRealBalance = (\n netDeposits: BigNumber,\n realized_pnl: BigNumber,\n) => {\n return netDeposits.plus(realized_pnl);\n};\n\nexport const calculatePositionAdjustedQty = (\n origQty: BigNumber,\n marketBaseMultiplier: BigNumber,\n positionBaseMultiplier: BigNumber,\n): BigNumber => {\n return origQty.times(marketBaseMultiplier).div(positionBaseMultiplier);\n};\n\n/**\n * Linearly interpolate a depth ratio from a (thresholds, ratios) curve.\n * The curve implicitly starts at (exposure=0, ratio=1.0).\n * - Between thresholds: linear interpolation\n * - Above last threshold: last ratio (flat extrapolation)\n *\n * @param thresholds - Sorted ascending exposure thresholds in notional USD (must be non-empty)\n * @param ratios - Depth ratio at each threshold (same length as thresholds, must be non-empty)\n * @param exposure - Absolute exposure notional (must be >= 0)\n * @throws if thresholds or ratios are empty, or if they have different lengths\n */\nexport const interpolateDepthRatio = (\n thresholds: number[],\n ratios: number[],\n exposure: number,\n): number => {\n if (exposure < 0) {\n throw new Error('interpolateDepthRatio: exposure must be >= 0');\n }\n if (thresholds.length === 0 || ratios.length === 0) {\n throw new Error(\n 'interpolateDepthRatio: thresholds and ratios must be non-empty',\n );\n }\n if (thresholds.length !== ratios.length) {\n throw new Error(\n 'interpolateDepthRatio: thresholds and ratios must have equal length',\n );\n }\n\n const allThresholds = [0, ...thresholds];\n const allRatios = [1.0, ...ratios];\n\n if (exposure === 0) return 1.0;\n if (exposure >= allThresholds[allThresholds.length - 1]) {\n return allRatios[allRatios.length - 1];\n }\n\n for (let i = 0; i < allThresholds.length - 1; i++) {\n if (exposure <= allThresholds[i + 1]) {\n const t =\n (exposure - allThresholds[i]) /\n (allThresholds[i + 1] - allThresholds[i]);\n return allRatios[i] + t * (allRatios[i + 1] - allRatios[i]);\n }\n }\n\n throw new Error('interpolateDepthRatio: unreachable');\n};\n\n/**\n * Calculate the dynamic depth factor for a trade given pool state and config.\n *\n * The pool takes the opposite side of the trade, so:\n * poolNotionalAfterTrade = currentPoolNotional - signedTradeNotional\n *\n * The depth ratio is interpolated from the exposure curve, then multiplied\n * by baseDepth to produce the final depth factor.\n *\n * @param baseDepth - Base depth multiplier for this market\n * @param thresholds - Sorted ascending exposure thresholds (notional USD)\n * @param ratios - Depth ratio at each threshold\n * @param currentPoolNotional - Pool's current notional in this market (signed)\n * @param signedTradeNotional - Trade notional (positive=buy, negative=sell)\n */\nexport const calculateDynamicDepthFactor = ({\n baseDepth,\n thresholds,\n ratios,\n currentPoolNotional,\n signedTradeNotional,\n}: {\n baseDepth: number;\n thresholds: number[];\n ratios: number[];\n currentPoolNotional: number;\n signedTradeNotional: number;\n}): number => {\n const poolNotionalAfterTrade = currentPoolNotional - signedTradeNotional;\n const absExposureNotional = Math.abs(poolNotionalAfterTrade);\n const depthRatio = interpolateDepthRatio(\n thresholds,\n ratios,\n absExposureNotional,\n );\n return depthRatio * baseDepth;\n};\n\nexport const calculatePositionAdlPnL = ({\n marketTrackerAdlUnwindPrice,\n marketTrackerBaseMultiplier,\n positionBase,\n positionAvgEntryPrice,\n positionTrackerBaseMultiplier,\n positionTrackerAdlUnwindPrice,\n}: {\n marketTrackerAdlUnwindPrice: BigNumber;\n marketTrackerBaseMultiplier: BigNumber;\n positionBase: BigNumber;\n positionAvgEntryPrice: BigNumber;\n positionTrackerBaseMultiplier: BigNumber;\n positionTrackerAdlUnwindPrice: BigNumber;\n}): BigNumber => {\n const currentAdlUnwindPrice = marketTrackerAdlUnwindPrice\n .minus(positionTrackerAdlUnwindPrice)\n .multipliedBy(1e18)\n .div(positionTrackerBaseMultiplier);\n\n const initialPrice = positionAvgEntryPrice\n .times(\n BigNumber(1e18).minus(\n marketTrackerBaseMultiplier\n .multipliedBy(1e18)\n .div(positionTrackerBaseMultiplier),\n ),\n )\n .div(1e18);\n\n const adlPnL = positionBase\n .times(currentAdlUnwindPrice.minus(initialPrice))\n .div(1e18);\n\n return adlPnL;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reyaxyz/common",
|
|
3
|
-
"version": "0.344.
|
|
3
|
+
"version": "0.344.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"generate:coverage-badges": "npx istanbul-badges-readme --silent"
|
|
46
46
|
},
|
|
47
47
|
"packageManager": "pnpm@8.3.1",
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "d053c2a017e7831f3c4dfcb8351bf1f963ea6f9d"
|
|
49
49
|
}
|
package/src/utils/calculate.ts
CHANGED
|
@@ -262,49 +262,184 @@ export const calculateRequiredMargin = ({
|
|
|
262
262
|
(Math.abs(currentNotional + tradeNotional) - Math.abs(currentNotional)) /
|
|
263
263
|
leverage;
|
|
264
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Calculates the maximum notional trade size (unsigned, always ≥ 0).
|
|
267
|
+
*
|
|
268
|
+
* Implements the UI quant spec v2 ("Maximum trade") with two cases:
|
|
269
|
+
* Case 1 — Extending: trade same direction as existing position.
|
|
270
|
+
* Case 2 — Reverting: decompose into (a) close position exactly, then
|
|
271
|
+
* (b) extend from zero in the opposite direction.
|
|
272
|
+
*
|
|
273
|
+
* All quadratics use the unsigned convention (t = |tradeNotional|) so the
|
|
274
|
+
* positive root always corresponds to the correct direction.
|
|
275
|
+
*/
|
|
265
276
|
export const calculateMaxOrderSize = ({
|
|
266
277
|
currIMR,
|
|
267
278
|
currNodeBalance,
|
|
268
279
|
currNotional,
|
|
269
280
|
depthFactor,
|
|
270
|
-
extendingPosition,
|
|
271
281
|
feeRate,
|
|
272
282
|
isShortTrade,
|
|
273
283
|
leverage,
|
|
274
284
|
maxExposure,
|
|
275
285
|
oraclePrice,
|
|
276
286
|
poolPrice,
|
|
287
|
+
currentLogF,
|
|
288
|
+
netExposure,
|
|
277
289
|
}: {
|
|
278
290
|
currIMR: number;
|
|
279
291
|
currNodeBalance: number;
|
|
280
292
|
currNotional: number;
|
|
281
293
|
depthFactor: number;
|
|
282
|
-
extendingPosition: boolean;
|
|
283
294
|
feeRate: number;
|
|
284
295
|
isShortTrade: boolean;
|
|
285
296
|
leverage: number;
|
|
286
297
|
maxExposure: number;
|
|
287
298
|
oraclePrice: number;
|
|
288
299
|
poolPrice: number;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
300
|
+
currentLogF: number;
|
|
301
|
+
netExposure: number;
|
|
302
|
+
}): number => {
|
|
303
|
+
const D = depthFactor * maxExposure;
|
|
304
|
+
const rho = poolPrice / oraclePrice;
|
|
305
|
+
const tradeSign = isShortTrade ? -1 : 1;
|
|
306
|
+
const s0 = currNotional > 0 ? 1 : currNotional < 0 ? -1 : tradeSign;
|
|
307
|
+
const absN0 = Math.abs(currNotional);
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Solve the extending quadratic (spec §Case 1) for max trade size.
|
|
311
|
+
* a·t² + b·t + c = 0 where a = ρ·γ, b = s₀·(1/lev + fee) + (ρ−1), c = −surplus.
|
|
312
|
+
* Root selection: pick the root whose sign matches s₀ (dir).
|
|
313
|
+
* For rebalancing (a < 0), caps at |NE| (beyond which γ switches to unbalancing).
|
|
314
|
+
*/
|
|
315
|
+
const solveExtending = (
|
|
316
|
+
dir: number,
|
|
317
|
+
surplus: number, // aka, IMRDelta
|
|
318
|
+
rho_: number,
|
|
319
|
+
gamma_: number,
|
|
320
|
+
isRebal: boolean,
|
|
321
|
+
absNE: number,
|
|
322
|
+
): number => {
|
|
323
|
+
if (surplus <= 0) return 0;
|
|
324
|
+
const a = rho_ * gamma_;
|
|
325
|
+
const b = dir * (1 / leverage + feeRate) + (rho_ - 1);
|
|
326
|
+
const c = -surplus;
|
|
327
|
+
// Degenerate: γ = 0 → linear equation b·t + c = 0 (rebalancing with f = 0)
|
|
328
|
+
if (a === 0) {
|
|
329
|
+
if (b === 0) return isRebal ? absNE : 0;
|
|
330
|
+
const t = -c / b;
|
|
331
|
+
if (t * dir <= 0) return isRebal ? absNE : 0;
|
|
332
|
+
return isRebal ? Math.min(Math.abs(t), absNE) : Math.abs(t);
|
|
333
|
+
}
|
|
334
|
+
const disc = b * b - 4 * a * c;
|
|
335
|
+
if (isRebal) {
|
|
336
|
+
if (disc < 0) return absNE;
|
|
337
|
+
const t = (-b + dir * Math.sqrt(disc)) / (2 * a);
|
|
338
|
+
return t * dir <= 0 ? absNE : Math.min(Math.abs(t), absNE);
|
|
339
|
+
}
|
|
340
|
+
if (disc < 0)
|
|
341
|
+
throw new Error(`calculateMaxOrderSize: negative discriminant (${disc})`);
|
|
342
|
+
const t = (-b + dir * Math.sqrt(disc)) / (2 * a);
|
|
343
|
+
if (t * dir <= 0)
|
|
344
|
+
throw new Error(`calculateMaxOrderSize: no valid root (${t})`);
|
|
345
|
+
return Math.abs(t);
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
// Determine γ for a trade of given direction against the current pool state
|
|
349
|
+
const getGamma = (dir: number, logF: number, ne: number) => {
|
|
350
|
+
const isRebal = ne !== 0 && dir === Math.sign(ne);
|
|
351
|
+
const gamma = isRebal ? -logF / ne : 1 / D;
|
|
352
|
+
return { gamma, isRebal };
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// ── Case 1: Extending ──────────────────────────────────────────────────
|
|
356
|
+
if (tradeSign === s0) {
|
|
357
|
+
const { gamma, isRebal } = getGamma(tradeSign, currentLogF, netExposure);
|
|
358
|
+
return solveExtending(
|
|
359
|
+
s0,
|
|
360
|
+
currNodeBalance - currIMR,
|
|
361
|
+
rho,
|
|
362
|
+
gamma,
|
|
363
|
+
isRebal,
|
|
364
|
+
Math.abs(netExposure),
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ── Case 2: Reverting — close N₀, then re-extend ──────────────────────
|
|
369
|
+
|
|
370
|
+
// Step 1: Close N₀ entirely (spec §Case 2, Step 1)
|
|
371
|
+
const closeTrade = -currNotional;
|
|
372
|
+
const closeDir = -s0;
|
|
373
|
+
const { gamma: gammaC, isRebal: closeIsRebal } = getGamma(
|
|
374
|
+
closeDir,
|
|
375
|
+
currentLogF,
|
|
376
|
+
netExposure,
|
|
377
|
+
);
|
|
378
|
+
const closeFlipsPool = closeIsRebal && absN0 > Math.abs(netExposure);
|
|
379
|
+
|
|
380
|
+
// Exec price ratio: ρ·exp(γ_c·closeTrade) for non-flip, dedicated formula for flip
|
|
381
|
+
const closeExecRatio = closeFlipsPool
|
|
382
|
+
? Math.exp((closeTrade - netExposure) / D)
|
|
383
|
+
: rho * Math.exp(gammaC * closeTrade);
|
|
384
|
+
|
|
385
|
+
const balClose =
|
|
386
|
+
currNodeBalance - feeRate * absN0 + closeTrade * (1 - closeExecRatio);
|
|
387
|
+
const imrClose = currIMR - absN0 / leverage;
|
|
388
|
+
const surplusClose = balClose - imrClose;
|
|
389
|
+
|
|
390
|
+
// Insolvency: can't fully close without going under margin.
|
|
391
|
+
// Solve partial-close quadratic (spec appendix): b has flipped feeRate sign.
|
|
392
|
+
// Falls back to full close (|N₀|) when no valid partial-close root exists.
|
|
393
|
+
if (surplusClose <= 0) {
|
|
394
|
+
const IMRDelta = currNodeBalance - currIMR;
|
|
395
|
+
const { gamma: gammaP } = getGamma(closeDir, currentLogF, netExposure);
|
|
396
|
+
const a = rho * gammaP;
|
|
397
|
+
const b = s0 * (1 / leverage - feeRate) + (rho - 1);
|
|
398
|
+
const c = -IMRDelta;
|
|
399
|
+
|
|
400
|
+
if (a === 0) {
|
|
401
|
+
if (b === 0) return absN0;
|
|
402
|
+
const t = -c / b;
|
|
403
|
+
if (t * closeDir <= 0) return absN0;
|
|
404
|
+
return Math.min(Math.abs(t), absN0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const disc = b * b - 4 * a * c;
|
|
408
|
+
if (disc < 0) return absN0;
|
|
409
|
+
const t = (-b + closeDir * Math.sqrt(disc)) / (2 * a);
|
|
410
|
+
if (t * closeDir <= 0) return absN0;
|
|
411
|
+
return Math.min(Math.abs(t), absN0);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Step 2: Extend from zero in -s₀ direction with post-close pool state
|
|
415
|
+
const neAfter = netExposure + currNotional;
|
|
416
|
+
let fPrime: number;
|
|
417
|
+
if (closeFlipsPool) {
|
|
418
|
+
fPrime = (closeTrade - netExposure) / D;
|
|
419
|
+
} else if (closeIsRebal) {
|
|
420
|
+
fPrime = currentLogF * (1 + currNotional / netExposure);
|
|
421
|
+
} else {
|
|
422
|
+
fPrime = currentLogF + closeTrade / D;
|
|
423
|
+
}
|
|
424
|
+
const rhoPrime = Math.exp(fPrime);
|
|
425
|
+
|
|
426
|
+
const extDir = -s0;
|
|
427
|
+
const { gamma: gammaPrime, isRebal: isExtRebal } = getGamma(
|
|
428
|
+
extDir,
|
|
429
|
+
fPrime,
|
|
430
|
+
neAfter,
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
return (
|
|
434
|
+
absN0 +
|
|
435
|
+
solveExtending(
|
|
436
|
+
extDir,
|
|
437
|
+
surplusClose,
|
|
438
|
+
rhoPrime,
|
|
439
|
+
gammaPrime,
|
|
440
|
+
isExtRebal,
|
|
441
|
+
Math.abs(neAfter),
|
|
442
|
+
)
|
|
308
443
|
);
|
|
309
444
|
};
|
|
310
445
|
|