Skip to content
markpaper

src/markets/leverage.ts

v0.2.0 · 1.5 KB

Download file
// Leverage on Nado is not a setting: unified cross margin derives the initial margin requirement from the
// product's `long_weight_initial`. There is no `updateLeverage`; sizing clamps use the implied maximum.

/**
 * Effective maximum leverage implied by `long_weight_initial`: `round(1 / (1 - weight))`, at least 1.
 * 0.98 -> 50x (BTC), 0.9 -> 10x (ZEC), 0.8 -> 5x (PONS).
 *
 * @throws RangeError when the weight is not in (0, 1).
 */
export function maxLeverageFromWeights(longWeightInitial: number): number {
  if (!(longWeightInitial > 0 && longWeightInitial < 1)) {
    throw new RangeError(`long_weight_initial must be in (0, 1), got ${String(longWeightInitial)}`);
  }
  return Math.max(1, Math.round(1 / (1 - longWeightInitial)));
}

/** Initial margin fraction of a product: `1 - long_weight_initial` (0.02 for BTC at 0.98). */
export function initialMarginFraction(longWeightInitial: number): number {
  if (!(longWeightInitial > 0 && longWeightInitial < 1)) {
    throw new RangeError(`long_weight_initial must be in (0, 1), got ${String(longWeightInitial)}`);
  }
  return 1 - longWeightInitial;
}

/**
 * Picks the weight to use for a position: the one reported by `subaccount_info.perp_products[].risk`
 * when it is a valid fraction, otherwise the product's weight from `symbols`.
 */
export function effectiveLongWeight(fromSubaccount: number | null | undefined, fromSymbols: number): number {
  if (typeof fromSubaccount === 'number' && fromSubaccount > 0 && fromSubaccount < 1) return fromSubaccount;
  return fromSymbols;
}
All files