UNPKG

hm-aftermath-ts-sdk

Version:
218 lines (217 loc) 10.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PerpetualsMarket = void 0; const __1 = require("../.."); const caller_1 = require("../../general/utils/caller"); const iFixedUtils_1 = require("../../general/utils/iFixedUtils"); const perpetuals_1 = require("./perpetuals"); const utils_1 = require("./utils"); class PerpetualsMarket extends caller_1.Caller { // ========================================================================= // Constructor // ========================================================================= constructor(marketData, network) { super(network, `perpetuals/${marketData.collateralCoinType}/markets/${marketData.objectId}`); this.marketData = marketData; this.network = network; this.getMaxOrderSizeUsd = (inputs) => __awaiter(this, void 0, void 0, function* () { const { side, price, account, indexPrice, leverage } = inputs; const maxSize = yield this.fetchApi("max-order-size", { accountId: account.accountCap.accountId, collateral: account.collateralBalance(), side, price, leverage, }); return Number(maxSize) * this.lotSize() * indexPrice; }); // ========================================================================= // Calculations // ========================================================================= this.timeUntilNextFundingMs = () => { return this.nextFundingTimeMs() - Date.now(); }; this.nextFundingTimeMs = () => { const fundingFrequencyMs = Number(this.marketParams.fundingFrequencyMs); const lastFundingIntervalNumber = Math.floor(this.marketState.fundingLastUpdMs / fundingFrequencyMs); return (lastFundingIntervalNumber + 1) * fundingFrequencyMs; }; // The funding rate as the difference between book and index TWAPs relative to the index price, // scaled by the funding period adjustment: // (bookTwap - indexTwap) / indexPrice * (fundingFrequency / fundingPeriod) // // To get the rate as a percentage, multiply the output by 100. this.estimatedFundingRate = (inputs) => { const { indexPrice } = inputs; const premiumTwap = iFixedUtils_1.IFixedUtils.numberFromIFixed(this.marketState.premiumTwap); const relativePremium = premiumTwap / indexPrice; const periodAdjustment = Number(this.marketParams.fundingFrequencyMs) / Number(this.marketParams.fundingPeriodMs); return relativePremium * periodAdjustment; }; this.priceToOrderPrice = (inputs) => { const { price } = inputs; const lotSize = this.marketParams.lotSize; const tickSize = this.marketParams.tickSize; return perpetuals_1.Perpetuals.priceToOrderPrice({ price, lotSize, tickSize, }); }; this.orderPriceToPrice = (inputs) => { const { orderPrice } = inputs; const lotSize = this.marketParams.lotSize; const tickSize = this.marketParams.tickSize; return perpetuals_1.Perpetuals.orderPriceToPrice({ orderPrice, lotSize, tickSize, }); }; this.calcCollateralUsedForOrder = (inputs) => { const { leverage, orderData, indexPrice, collateralPrice } = inputs; const imr = 1 / leverage; // const imr = this.initialMarginRatio(); const collateralUsd = Number(orderData.initialSize - orderData.filledSize) * this.lotSize() * indexPrice * imr; const collateral = collateralUsd / collateralPrice; return { collateralUsd, collateral, }; }; this.roundToValidPrice = (inputs) => { return Math.round(inputs.price / this.tickSize()) * this.tickSize(); }; this.roundToValidSize = (inputs) => { const lots = inputs.size / this.lotSize(); return ((inputs.floor ? Math.floor(lots) : Math.round(lots)) * this.lotSize()); }; this.marketId = marketData.objectId; this.collateralCoinType = marketData.collateralCoinType; this.marketParams = marketData.marketParams; this.marketState = marketData.marketState; } // ========================================================================= // Inspections // ========================================================================= getOrderbookPrice() { return this.fetchApi("orderbook-price"); } get24hrVolume() { return this.fetchApi("24hr-volume"); } getPrice24hrsAgo() { return this.fetchApi("price-24hrs-ago"); } getOrderbookState(inputs) { return this.fetchApi("orderbook-state", Object.assign(Object.assign({}, inputs), { lotSize: this.lotSize(), tickSize: this.tickSize() })); } // ========================================================================= // Trade History // ========================================================================= getTradeHistory(inputs) { return __awaiter(this, void 0, void 0, function* () { return this.fetchApi(`trade-history`, inputs); }); } // ========================================================================= // Value Conversions // ========================================================================= lotSize() { return perpetuals_1.Perpetuals.lotOrTickSizeToNumber(this.marketParams.lotSize); } tickSize() { return perpetuals_1.Perpetuals.lotOrTickSizeToNumber(this.marketParams.tickSize); } maxLeverage() { return (1 / __1.Casting.IFixed.numberFromIFixed(this.marketParams.marginRatioInitial)); } initialMarginRatio() { return __1.Casting.IFixed.numberFromIFixed(this.marketParams.marginRatioInitial); } // ========================================================================= // Helpers // ========================================================================= orderPrice(inputs) { const { orderId } = inputs; const orderPrice = utils_1.PerpetualsOrderUtils.price(orderId); return this.orderPriceToPrice({ orderPrice }); } // ========================================================================= // Private Helpers // ========================================================================= // private getExecutionPrice(inputs: { // side: PerpetualsOrderSide; // size: bigint; // collateral: Balance; // price?: PerpetualsOrderPrice; // }) { // return this.fetchApi< // ApiPerpetualsExecutionPriceResponse, // ApiPerpetualsExecutionPriceBody // >("execution-price", { // ...inputs, // lotSize: this.lotSize(), // basePriceFeedId: this.marketParams.basePriceFeedId, // collateralPriceFeedId: this.marketParams.collateralPriceFeedId, // }); // } simulateClosePosition(inputs) { const { position, indexPrice, executionPrice, size, percentFilled } = inputs; const imr = 1 / position.leverage; // const imr = this.initialMarginRatio(); const takerFee = __1.Casting.IFixed.numberFromIFixed(this.marketParams.takerFee); const positionSizeNum = __1.Casting.IFixed.numberFromIFixed(position.baseAssetAmount); const positionBidsNum = __1.Casting.IFixed.numberFromIFixed(position.bidsQuantity); const positionAsksNum = __1.Casting.IFixed.numberFromIFixed(position.asksQuantity); const netSizeBefore = Math.max(Math.abs(positionSizeNum + positionBidsNum), Math.abs(positionSizeNum - positionAsksNum)); let sizeFilled = size * percentFilled; let sizePosted = size * (1 - percentFilled); let positionSizeFilledNum; let positionSizePosted; const positionSizeAbs = Math.abs(positionSizeNum); if (sizeFilled >= positionSizeAbs) { positionSizeFilledNum = positionSizeAbs; positionSizePosted = 0; sizeFilled = sizeFilled - positionSizeAbs; } else { positionSizeFilledNum = sizeFilled; positionSizePosted = positionSizeAbs - sizeFilled; sizeFilled = 0; sizePosted = sizePosted - positionSizePosted; } const netSizeAfter = Math.max(Math.abs(positionSizeAbs - positionSizeFilledNum + positionBidsNum - positionSizePosted), Math.abs(positionSizeAbs - positionSizeFilledNum + positionAsksNum - positionSizePosted)); const entryPrice = perpetuals_1.Perpetuals.calcEntryPrice(position); const uPnl = positionSizeFilledNum * (indexPrice - entryPrice); const rPnl = positionSizeFilledNum * (executionPrice - entryPrice); // pessimistically don't consider positive pnl since the order may not actually be // matched at the sell price const fees = Math.abs(positionSizeFilledNum) * executionPrice * takerFee; const marginDelta = rPnl - uPnl - fees; const reqDelta = (netSizeAfter - netSizeBefore) * indexPrice * imr; return { marginDelta, reqDelta, sizeFilled, sizePosted }; } } exports.PerpetualsMarket = PerpetualsMarket;