From f75188202608555028c36bb6ae8ad8a6bc5aca3b Mon Sep 17 00:00:00 2001 From: Riordan Panayides Date: Mon, 24 Apr 2023 19:03:11 +0100 Subject: [PATCH] Compute funding rate from L2 data --- components/trade/PerpFundingRate.tsx | 82 +++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/components/trade/PerpFundingRate.tsx b/components/trade/PerpFundingRate.tsx index 8911fd67..ba6a5bf0 100644 --- a/components/trade/PerpFundingRate.tsx +++ b/components/trade/PerpFundingRate.tsx @@ -8,6 +8,7 @@ import { MANGO_DATA_API_URL } from 'utils/constants' import Tooltip from '@components/shared/Tooltip' import { useTranslation } from 'next-i18next' import mangoStore from '@store/mangoStore' +import { OrderbookL2 } from 'types' const fetchFundingRate = async (groupPk: string | undefined) => { const res = await fetch( @@ -38,6 +39,57 @@ export const formatFunding = Intl.NumberFormat('en', { style: 'percent', }) +function getImpactPriceL2( + bookside: number[][], + baseDepth: number +): number | undefined { + let total = 0 + for (const level of bookside) { + total += level[1] + if (total >= baseDepth) { + return level[0] + } + } + return undefined +} + +function getInstantaneousFundingRateL2( + market: PerpMarket, + orderbook: OrderbookL2 +) { + const MIN_FUNDING = market.minFunding.toNumber() + const MAX_FUNDING = market.maxFunding.toNumber() + + const bid = getImpactPriceL2( + orderbook.bids, + market.baseLotsToUi(market.impactQuantity) + ) + console.log(bid) + const ask = getImpactPriceL2( + orderbook.asks, + market.baseLotsToUi(market.impactQuantity) + ) + console.log(ask) + const indexPrice = market._uiPrice + + let funding + if (bid !== undefined && ask !== undefined) { + const bookPrice = (bid + ask) / 2 + funding = Math.min( + Math.max(bookPrice / indexPrice - 1, MIN_FUNDING), + MAX_FUNDING + ) + } else if (bid !== undefined) { + funding = MAX_FUNDING + } else if (ask !== undefined) { + funding = MIN_FUNDING + } else { + funding = 0 + } + + return funding +} + const PerpFundingRate = () => { const { selectedMarket } = useSelectedMarket() const rate = usePerpFundingRate() @@ -45,6 +97,7 @@ const PerpFundingRate = () => { const bids = mangoStore((s) => s.selectedMarket.bidsAccount) const asks = mangoStore((s) => s.selectedMarket.asksAccount) + const orderbook = mangoStore((s) => s.selectedMarket.orderbook) const fundingRate = useMemo(() => { if (rate.isSuccess && selectedMarket instanceof PerpMarket) { @@ -56,6 +109,25 @@ const PerpFundingRate = () => { } }, [rate, selectedMarket]) + const instantaneousRate = useMemo(() => { + if (!(selectedMarket instanceof PerpMarket)) return undefined + if (bids instanceof BookSide && asks instanceof BookSide) { + return selectedMarket.getInstantaneousFundingRateUi(bids, asks).toFixed(4) + } + + console.log(orderbook.bids.length, orderbook.asks.length) + if (orderbook.asks.length && orderbook.bids.length) { + console.log( + getInstantaneousFundingRateL2(selectedMarket, orderbook).toFixed(4) + ) + return ( + getInstantaneousFundingRateL2(selectedMarket, orderbook) * 100 + ).toFixed(4) + } + + return undefined + }, [orderbook, bids, asks, selectedMarket]) + return ( <>
@@ -76,15 +148,9 @@ const PerpFundingRate = () => { {formatFunding.format(fundingRate * 8760)}.
) : null} - {selectedMarket instanceof PerpMarket && - bids instanceof BookSide && - asks instanceof BookSide ? ( + {instantaneousRate ? (
- The latest instantaneous rate is{' '} - {selectedMarket - .getInstantaneousFundingRateUi(bids, asks) - .toFixed(4)} - % + The latest instantaneous rate is {instantaneousRate}%
) : null}