APY of two growth rates

This commit is contained in:
Finn 2024-02-27 15:30:05 +00:00
parent f264c31994
commit 4a37c9072f
4 changed files with 134 additions and 114 deletions

View File

@ -138,11 +138,11 @@ const PositionItem = ({
console.log('liq price change percentage', liqPriceChangePercentage)
const { estimatedNetAPY, stakeBankDepositRate } = useBankRates(
const { financialMetrics, stakeBankDepositRate } = useBankRates(
bank.name,
leverage,
)
const uiRate = bank.name == 'USDC' ? stakeBankDepositRate : estimatedNetAPY
const uiRate = bank.name == 'USDC' ? stakeBankDepositRate : financialMetrics.APY
return (
<div className="rounded-2xl border-2 border-th-fgd-1 bg-th-bkg-1 p-6">
@ -188,7 +188,7 @@ const PositionItem = ({
<div>
<p className="mb-1 text-th-fgd-4">Est. APY</p>
<span className="text-xl font-bold text-th-fgd-1">
<FormatNumericValue value={uiRate} decimals={2} />%
<FormatNumericValue value={Number(uiRate)} decimals={2} />%
</span>
</div>
<div>

View File

@ -102,10 +102,8 @@ function StakeForm({ token: selectedToken }: StakeFormProps) {
const { group } = useMangoGroup()
const groupLoaded = mangoStore((s) => s.groupLoaded)
const {
financialMetrics,
borrowBankBorrowRate,
leveragedAPY,
estimatedNetAPY,
collateralFeeAPY,
} = useBankRates(selectedToken, leverage)
const leverageMax = useLeverageMax(selectedToken) * 0.9 // Multiplied by 0.975 becuase you cant actually get to the end of the inifinite geometric series?
@ -406,13 +404,13 @@ function StakeForm({ token: selectedToken }: StakeFormProps) {
<p className="font-medium">Est. Net APY</p>
<div className="flex items-center space-x-2">
<span className="text-lg font-bold text-th-success">
{estimatedNetAPY >= 0
{financialMetrics.APY >= 0
? '+'
: estimatedNetAPY === 0
: financialMetrics.APY === 0
? ''
: '-'}
<FormatNumericValue
value={estimatedNetAPY}
value={financialMetrics.APY}
decimals={2}
/>
%
@ -426,77 +424,8 @@ function StakeForm({ token: selectedToken }: StakeFormProps) {
</div>
</Disclosure.Button>
<Disclosure.Panel className="space-y-2 rounded-xl rounded-t-none border-2 border-t-0 border-th-bkg-3 px-4 pb-3">
<div className="flex justify-between">
<p className="text-th-fgd-4">
{formatTokenSymbol(selectedToken)} Leveraged APY
</p>
<span className="font-bold text-th-success">
{leveragedAPY > 0.01 ? '+' : ''}
<FormatNumericValue
value={leveragedAPY}
decimals={2}
/>
%
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">
{formatTokenSymbol(selectedToken)} Collateral Fee APY
</p>
<span
className={`font-bold ${
collateralFeeAPY > 0.01
? 'text-th-error'
: 'text-th-bkg-4'
}`}
>
{collateralFeeAPY > 0.01 ? '-' : ''}
<FormatNumericValue
value={collateralFeeAPY?.toString()}
decimals={2}
/>
%
</span>
</div>
{borrowBank ? (
<>
<div className="flex justify-between">
<p className="text-th-fgd-4">{`${borrowBank?.name} Borrow Rate`}</p>
<span
className={`font-bold ${
borrowBankBorrowRate > 0.01
? 'text-th-error'
: 'text-th-bkg-4'
}`}
>
-
<FormatNumericValue
value={borrowBankBorrowRate}
decimals={2}
/>
%
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">{`${borrowBank.name} Borrowed`}</p>
<span
className={`font-bold ${
amountToBorrow > 0.001
? 'text-th-fgd-1'
: 'text-th-bkg-4'
}`}
>
<FormatNumericValue
value={amountToBorrow}
decimals={3}
/>
<span className="font-body text-th-fgd-4">
{' '}
{borrowBank.name}
</span>
</span>
</div>
<div className="flex justify-between">
<div className="flex justify-between">
<p className="text-th-fgd-4">{`${stakeBank.name} Position`}</p>
<span
className={`font-bold ${
@ -528,6 +457,76 @@ function StakeForm({ token: selectedToken }: StakeFormProps) {
</span>
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">{`${borrowBank.name} Borrowed`}</p>
<span
className={`font-bold ${
amountToBorrow > 0.001
? 'text-th-fgd-1'
: 'text-th-bkg-4'
}`}
>
<FormatNumericValue
value={amountToBorrow}
decimals={3}
/>
<span className="font-body text-th-fgd-4">
{' '}
{borrowBank.name}
</span>
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">
{formatTokenSymbol(selectedToken)} Returns APY
</p>
<span className="font-bold text-th-success">
{financialMetrics.collectedReturnsAPY > 0.01 ? '+' : ''}
<FormatNumericValue
value={financialMetrics.collectedReturnsAPY}
decimals={2}
/>
%
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">
{formatTokenSymbol(selectedToken)} Collateral Fee APY
</p>
<span
className={`font-bold ${
financialMetrics?.collateralFeeAPY > 0.01
? 'text-th-error'
: 'text-th-bkg-4'
}`}
>
{financialMetrics?.collateralFeeAPY > 0.01 ? '-' : ''}
<FormatNumericValue
value={financialMetrics?.collateralFeeAPY?.toString()}
decimals={2}
/>
%
</span>
</div>
{borrowBank ? (
<>
<div className="flex justify-between">
<p className="text-th-fgd-4">{`${borrowBank?.name} Borrow APY Rate`}</p>
<span
className={`font-bold ${
borrowBankBorrowRate > 0.01
? 'text-th-error'
: 'text-th-bkg-4'
}`}
>
-
<FormatNumericValue
value={financialMetrics.borrowsAPY}
decimals={2}
/>
%
</span>
</div>
<div className="flex justify-between">
<p className="text-th-fgd-4">{`Liquidation Price`}</p>
<span

View File

@ -14,12 +14,12 @@ const TokenButton = ({
}) => {
const leverage = useLeverageMax(tokenName) * 0.9
const { stakeBankDepositRate, estimatedNetAPY } = useBankRates(
const { stakeBankDepositRate, financialMetrics } = useBankRates(
tokenName,
leverage,
)
const { estimatedNetAPY: estimatedNetAPYFor1xLev } = useBankRates(
const { financialMetrics: estimatedNetAPYFor1xLev } = useBankRates(
tokenName,
1,
)
@ -27,7 +27,7 @@ const TokenButton = ({
const UiRate =
tokenName === 'USDC'
? stakeBankDepositRate
: Math.max(estimatedNetAPYFor1xLev, estimatedNetAPY)
: Math.max(estimatedNetAPYFor1xLev.APY, financialMetrics.APY)
return (
<button

View File

@ -22,56 +22,77 @@ export default function useBankRates(selectedToken: string, leverage: number) {
}, [group])
const stakeBankDepositRate = useMemo(() => {
return stakeBank ? stakeBank.getDepositRateUi() : 0
return stakeBank ? stakeBank.getDepositRate() : 0
}, [stakeBank])
const borrowBankBorrowRate = useMemo(() => {
return borrowBank ? borrowBank.getBorrowRateUi() : 0
return borrowBank ? Number(borrowBank.getBorrowRate()) : 0
}, [borrowBank])
const borrowBankStakeRate = useMemo(() => {
return stakeRates ? stakeRates[selectedToken.toLowerCase()] * 100 : 0
const jlpStakeRateAPY = useMemo(() => {
return stakeRates ? stakeRates[selectedToken.toLowerCase()] : 0
}, [stakeRates, selectedToken])
const leveragedAPY = useMemo(() => {
return borrowBankStakeRate ? borrowBankStakeRate * leverage : 0
}, [borrowBankStakeRate, leverage])
const financialMetrics = useMemo(() => {
let borrowMultiplier = leverage - 1;
let depositMultiplier = leverage;
let collectedCollateralFees = 0
let collectedReturns = 0
const collateralFeeAPY = useMemo(() => {
if (!stakeBank) return 0
const borrowedAmount = leverage - 1
const assetsCovered = borrowedAmount / Number(stakeBank?.maintAssetWeight)
return stakeBank?.collateralFeePerDay * 365 * 100 * assetsCovered
}, [stakeBank, leverage])
const maintAssetWeight = Number(stakeBank?.maintAssetWeight);
const collateralFeePerDay = Number(stakeBank?.collateralFeePerDay);
const borrowFeeRatePerDay = Number(borrowBankBorrowRate) / 365;
const jlpStakeRatePerDay = (jlpStakeRateAPY ** (1 / 365)) - 1;
const estimatedNetAPY = useMemo(() => {
return (
borrowBankStakeRate * leverage - borrowBankBorrowRate * (leverage - 1) - collateralFeeAPY
)
}, [borrowBankStakeRate, leverage, borrowBankBorrowRate, collateralFeeAPY])
for (let day = 1; day <= 365; day++) {
// Collateral Fee Multiplier
const collateralFeeMultiplier = borrowMultiplier / (depositMultiplier * maintAssetWeight);
const collateralFeeRate = collateralFeeMultiplier * collateralFeePerDay;
// useEffect(() => {
// set((s) => {
// s.estimatedMaxAPY.current =
// borrowBankStakeRate * leverageMax -
// borrowBankBorrowRate * (leverageMax - 1)
// })
// }, [borrowBankStakeRate, borrowBankBorrowRate, leverageMax])
// USDC Liabilities Multiplier
borrowMultiplier *= (1 + borrowFeeRatePerDay);
// Daily Collateral Fees
const dailyCollateralFee = depositMultiplier * collateralFeeRate;
const collectedReturnsDaily = depositMultiplier * jlpStakeRatePerDay;
collectedCollateralFees += dailyCollateralFee;
collectedReturns += collectedReturnsDaily
depositMultiplier += collectedReturnsDaily - dailyCollateralFee;
}
// APY's for the calculation
const depositAPY = 100 * leverage * (((depositMultiplier + 1) / leverage) - 1); // Composed of the below two
const collateralFeeAPY = leverage * (collectedCollateralFees / leverage) * 100;
const collectedReturnsAPY = leverage * ((collectedReturns + 1) / leverage) * 100;
// Interest Fee APY: Reflecting borrowing cost as an annual percentage yield
const interestCost = (borrowMultiplier - (leverage - 1)); // APY on interest
const borrowsAPY = 100 * interestCost;
// Total APY taking into account interest, collateral fees and returns
const APY = 100 * (depositMultiplier - borrowMultiplier)
// Comparisons to outside
const nonMangoAPY = jlpStakeRateAPY * leverage * 100;
const diffToNonMango = (depositAPY - nonMangoAPY);
const diffToNonLeveraged = (depositAPY - (jlpStakeRateAPY * 100));
return { APY, depositAPY, collectedReturnsAPY, collateralFeeAPY, borrowsAPY, nonMangoAPY, diffToNonMango, diffToNonLeveraged };
}, [leverage, borrowBankBorrowRate, jlpStakeRateAPY, stakeBank?.collateralFeePerDay, stakeBank?.maintAssetWeight ]);
const estimatedMaxAPY = useMemo(() => {
return (
borrowBankStakeRate * leverageMax - borrowBankBorrowRate * (leverageMax - 1)
jlpStakeRateAPY * leverageMax - Number(borrowBankBorrowRate) * (leverageMax - 1)
)
}, [borrowBankStakeRate, borrowBankBorrowRate, leverageMax])
}, [jlpStakeRateAPY, borrowBankBorrowRate, leverageMax])
return {
financialMetrics,
stakeBankDepositRate,
borrowBankBorrowRate,
borrowBankStakeRate,
leveragedAPY,
estimatedNetAPY,
jlpStakeRateAPY,
estimatedMaxAPY,
collateralFeeAPY
}
}