APY Calculation
This document contains the formulas used to calculate the APY for Pendle markets.
In this document, we take the market 0x107a2e3cd2bb9a32b9ee2e4d51143149f8367eba
on mainnet as an example.
Variables
name | Description |
---|
market | 0x107a2e3cd2bb9a32b9ee2e4d51143149f8367eba |
sy | 0xC4ed348c56223C5953939e932E315F9d72Cd83fF |
lpPriceUsd | price of the lp token in terms of USD |
syPriceUsd | price of the sy token in terms of USD |
pendlePriceUSD | price of the Pendle token in terms of USD |
totalVotedLastEpoch | total of vePendle voted for the pool in the last epoch |
duration | the interval that we use to calculate the APY. For example, duration=7 means we calculate the APY based on data of the last 7 days. In our system, we use 7 days as the default duration! |
syIndex | the current index of the SY token, can be taken from exchangeRate function of the sy contract |
prevSyIndex | the syIndex at duration days ago. |
yearsToExpiry | the number of years until the expiry of the market. |
Underlying APY
underlyingApy=underlyingInterestApy+underlyingRewardApr
underlyingApy comes in two part, below are how to calculate each of them
UnderlyingInterestApy
interestMultiple=prevSyIndexsyIndex
underlyingInterestApy=interestMultipledays365−1
- Explanation:
- underlyingInterestApy estimates the current APY for the interest of the underlying protocol of the SY token. Interest = returns in the underlying asset, and it’s auto-compounding by default.
- In this formula, we are taking the historical APY for the last 7 days, to extrapolate into the returns for the year.
UnderlyingRewardApr:
impliedAPY:
apy=elnImpliedYield−1
- lnImpliedYield can be read from readState function of the market contract. Do remember to scale it by 1e18.
SwapFeeApy & voterApr
SwapFeeApy
swapFeeApy is the APY that LP holders will get from the swap fees of the pool.
poolValue=lpPriceUsd∗totalSupply
swapFeeForLpHolder=explicitSwapFee∗20%+implicitSwapFee
swapFeeRateForLpHolder=poolValueswapFeeForLpHolder∗syPriceUsd
swapFeeApy=(1+swapFeeRateForLpHolder)durations365−1
- Explanation:
- LP Holder will received 20% from explicit swap fee, and 100% from the implicit swap fee
- swapFeeRateForLpHolder is the rate of swap fee that LP holder will get in terms of USD, then we interpolate it to get the swapFeeApy
VoterApr
VoterApr is the APR that vePendle voters will get from voting for the pool.
swapFeeForVoter=explicitSwapFee∗80%
swapFeeRateForVoter=PendlePriceUSD × totalVotedLastEpochswapFeeForVoter × syPriceUsd
voterApr= swapFeeRateForVoter×durationInDays365
- Explanation:
- Voter will received 80% from explicit swap fee of the pool
longYieldApy:
interestReturns=(1+underlyingInterestApy)yearsToExpiry−1
rewardsReturns=underlyingRewardApy∗yearsToExpiry
ytReturns=interestReturns+rewardsReturns
ytReturnsAfterFee=holdYtReturns×97%
longYieldApy=ytPriceInAssetytReturnsAfterFeeyearsToExpiry1−1
- Explanation:
- interestReturns:
- interest returns, in terms of accounting asset, for holding 1 YT from now until expiry
- rewardsReturns:
- rewards returns, in terms of accounting asset, for holding 1 YT from now until expiry
- ytReturnsAfterFee:
- we charge 3% on YT yield, so we need to scale it down by 97%
- longYieldApy:
- This is the APY if we buy YT today, and hold it all the way to expiry, assuming the underlying APY will stay the same. This can be negative (if the returns from YT is less than YT price)
- Starting with ytPriceInAsset, we got back ytReturnsWithFee after yearsToExpiry.Then we just need to scale it to one year to get the APY
effectiveImpliedApy
Effective Implied APY is the APY based on the actual rate that the user used to swap.
To calculate effectiveImpliedApy, we need to get the ptExchangeRate: how much PT you can get from 1 underlying.
There are 3 type of swaps:
- PT <-> any token except YT
- YT <-> any token except PT
- PT <-> YT
Each of them has different way to calculate the ptExchangeRate
PT <-> any token
- underlying: input/output token amount in terms of the underlying token
- ptAmount: PT input/output amount
ptExchangeRate=underlyingptAmount
YT <-> any token
- ytAmount: YT intput/output amount
ptExchangeRate=1−ytAmountunderlying1
PT <-> YT
ptExchangeRate=1+ytAmountptAmount
From ptExchangeRate you can calculate the effectiveImpliedApy as follow:
effectiveImpliedApy=ptExchangeRatedaysToExpiry365−1