hm-aftermath-ts-sdk
Version:
Aftermath TypeScript SDK
218 lines (217 loc) • 10.3 kB
JavaScript
"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;