SKY TERMINAL
FeaturesPricingProduct PreviewSignal TransparencySupport
Log inRegister
SKY TERMINAL · See the market before the move.TermsPrivacyMembershipPayments & RefundsRisk DisclosureData SourcesSupportX

Sky Terminal provides market information, research tools, alerts and simulations. It is not an exchange, broker or custodian, does not hold funds and does not execute trades. Nothing here is financial advice. Cryptocurrency futures are highly volatile and leveraged trading can lose more than your initial margin. Exchange data is attributed to its source and may be delayed or incomplete.

Risk calculator formulas

Implementation: src/lib/risk.ts (calculateRisk). It is pure (no database or Node imports) and runs in the browser and on the server. All values are computed in full double precision; only the display strings are rounded.

Notation

SymbolMeaning
Bbalance. Linear: in the settlement/quote currency (e.g. USDT). Inverse: in the base coin (e.g. BTC).
rrisk % (riskPct / 100)
E, S, Tentry, stop, target prices
ddirection: +1 long, −1 short
Lleverage (1–125)
fE, fXentry / exit fee rate = maker or taker fee % ÷ 100, chosen by entryOrderType / exitOrderType
sslippage rate = slippagePct / 100, applied adversely to every fill
Cinverse contract size in USD (Binance COIN-M: 100 for BTC, 10 for others)
Qquantity: base units (linear) or whole contracts (inverse)

Fill prices (slippage)

E' = E × (1 + s·d)      entry fills worse (higher for a long)
S' = S × (1 − s·d)      stop fills worse (lower for a long)
T' = T × (1 − s·d)      target fills worse

Per-unit PnL and fees (account currency)

Linear (unit = 1 base unit)Inverse (unit = 1 contract), in coin
gross PnL from price a to bg(a,b) = (b − a) · dg(a,b) = C · (1/a − 1/b) · d
fee for one unit filled at pp · f(C / p) · f

Position sizing

maxLoss      = B × r                                   (planned maximum loss, account currency)
lossPerUnit  = −g(E', S') + fee(E', fE) + fee(S', fX)  (loss at the stop INCLUDING fees and slippage)
rawQuantity  = maxLoss / lossPerUnit
Q            = floor(rawQuantity to qtyStep)            linear (no step → unrounded)
Q            = floor(rawQuantity)                       inverse (whole contracts)

After rounding, Q is reduced further if floating-point noise would make Q × lossPerUnit > maxLoss. Guarantee: effectiveRiskPct ≤ riskPct, always. (At an exact boundary such as 25.000000 contracts, float noise can cost one step; the calculator always errs on the side of less risk.)

Rounding uses floorToStep, which corrects for representation error (0.3 / 0.1 = 2.999…) by working in integer step counts and fixed decimals derived from the step.

Outputs

positionNotionalUsd = Q × E            (linear; quote ≈ USD)     | Q × C          (inverse)
positionNotional    = Q × E            (account currency)        | Q × C / E      (coin)
initialMargin       = positionNotional / L
fees at stop        = entry: Q·fee(E', fE)   exit: Q·fee(S', fX)
fees at target      = entry: Q·fee(E', fE)   exit: Q·fee(T', fX)
slippageAtStop      = Q × (g(E, S) − g(E', S'))      (PnL lost vs. fills at exact prices)
slippageAtTarget    = Q × (g(E, T) − g(E', T'))
lossAtStop          = Q × lossPerUnit                  (positive number)
profitAtTarget      = Q × g(E', T') − fees at target total
riskReward          = profitAtTarget / lossAtStop      (net, after costs)
grossRiskReward     = |g(E, T)| / |g(E, S)|            (price distance only)
returnOnMarginPct   = profitAtTarget / initialMargin × 100
lossOnMarginPct     = −lossAtStop / initialMargin × 100
effectiveRiskPct    = lossAtStop / B × 100
maxAffordableQuantity = floor_step( B / (E/L + fee(E', fE)) )            linear
                      = floor( B / (C/(E·L) + fee(E', fE)) )             inverse

Currency of each output

  • accountCurrency is the currency input. Every money output is in it unless the field name ends in Usd.
  • Linear: account currency is the quote (USDT/USDC); *Usd fields equal the account-currency values (assumes the stablecoin ≈ 1 USD).
  • Inverse: money outputs are in coin. USD conversions are explicit and use the price at which the amount is realised:

lossAtStopUsd = lossAtStop × S', profitAtTargetUsd = profitAtTarget × T'. positionNotionalUsd = Q × C.

Validation

Errors (ok = false):

CodeCondition
BALANCE, ENTRY_PRICE, STOP_PRICE, TARGET_PRICEnon-finite (NaN/∞) or ≤ 0
STOP_ZERO_DISTANCES = E or `S − E< tickSize`
STOP_WRONG_SIDElong with S > E, short with S < E
TARGET_ZERO_DISTANCE, TARGET_WRONG_SIDEtarget equal to entry / on the losing side
LEVERAGEoutside 1–125
RISK_PCToutside (0, 100]
COSTSfee or slippage negative, NaN or ≥ 100
CONTRACT_SIZEinverse without a positive contractSizeUsd
SLIPPAGEslippage larger than the stop distance
INSUFFICIENT_MARGINinitialMargin + entry fee > B; message reports maxAffordableQuantity (outputs are still returned)
QTY_ZEROquantity rounds down to 0; message reports the risk % of the minimum step

Warnings: RISK_PCT_HIGH (> 5 %), LEVERAGE_HIGH (> 50×, unrealistic), TICK_ALIGNMENT, TARGET_UNPROFITABLE (target does not cover costs), RISK_UNDERUSED (rounding leaves < 50 % of the requested risk), STOP_BEYOND_LIQUIDATION.

Illustrative liquidation (estimate, NOT exchange-precise)

Returned as illustrativeLiquidation { label, price, assumptions[] }. Simplified isolated-margin model in which only the initial margin 1/L of notional absorbs losses:

linear long   E × (1 − 1/L)          (L = 1 → none)
linear short  E × (1 + 1/L)
inverse long  E / (1 + 1/L)
inverse short E / (1 − 1/L)          (L = 1 → none)

Derivation (inverse long): margin in coin = QC/(E·L); loss in coin = QC(1/P − 1/E); equal when 1/P = (1/E)(1 + 1/L).

Assumptions (also returned in the result): isolated margin; ignores maintenance-margin rate and tiers (real liquidation is closer to entry); ignores fees, funding and liquidation fee; uses the entry price rather than the mark price. Rounded to the tick toward the entry when a tick size is given.