Liquidity-Provider Fee APR
Install and import
npm install fintech-algorithmsimport { feeApr } from "fintech-algorithms/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr";Signature
feeApr(data, config)Annualised fee return for a liquidity position. Meaningful only net of impermanent loss: a headline APR quoted against a divergent pair routinely describes a losing position.
Parameters
| Name | Type | Notes |
|---|---|---|
data | PositionInput | Position state — balances, prices, and the protocol parameters the calculation depends on. |
config | ProtocolConfig | Protocol-specific thresholds and factors. These differ per protocol and per asset, so a figure computed under the wrong config is confidently wrong. |
Returns
{ status, value, components, diagnostics }
The result with every component, so a position's state can be reconciled against the protocol's own interface.
Errors
- When a required protocol parameter is missing — reported as a status rather than thrown
Complexity: time O(assets),
space O(assets).
Worked example
executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.
Input
{
"rows": [
{
"timestamp": "2026-01-01T00:00:00Z",
"duration_days": 1,
"volume": 2500000,
"fee_rate": 0.003,
"lp_share": 0.02,
"lp_capital": 1000000
},
{
"timestamp": "2026-01-02T00:00:00Z",
"duration_days": 1,
"volume": 2738636.056514657,
"fee_rate": 0.003,
"lp_share": 0.02,
"lp_capital": 1000000
},
{
"timestamp": "2026-01-03T00:00:00Z",
"duration_days": 1,
"volume": 2930007.3153574164,
"fee_rate": 0.003,
"lp_share": 0.02,
"lp_capital": 1000000
}
]
}{
"annualization_days": 365,
"protocol_fee_share": 0,
"capital_basis": "time_weighted"
}Call
feeApr(data, config)Returns
object with 11 fields: elapsed_days, gross_volume, lp_fee_income, time_weighted_average_capital, capital_denominator, capital_basis, protocol_fee_share, simple_fee_apr, …
{
"elapsed_days": 365,
"gross_volume": 912500000,
"lp_fee_income": 54750,
"time_weighted_average_capital": 1000000,
"capital_denominator": 1000000,
"capital_basis": "time_weighted",
"protocol_fee_share": 0,
"simple_fee_apr": 0.05475,
"period_fee_return": 0.05475,
"annualization_days": 365,
"trace": [
{
"index": 0,
"timestamp": "2026-01-01T00:00:00Z",
"volume": 2500000,
"lp_capital": 1000000,
"daily_fee_income": 150,
"cumulative_fee_income": 150,
"running_apr": 0.05475
},
{
"index": 1,
"timestamp": "2026-01-02T00:00:00Z",
"volume": 2738636.056514657,
"lp_capital": 1000000,
"daily_fee_income": 164.3181633909,
"cumulative_fee_income": 314.3181633909,
"running_apr": 0.0573630648
},
{
"index": 2,
"timestamp": "2026-01-03T00:00:00Z",
"volume": 2930007.3153574164,
"lp_capital": 1000000,
"daily_fee_income": 175.8004389214,
"cumulative_fee_income": 490.1186023123,
"running_apr": 0.0596310966
}
]
}Other exports
This module also exports
impermanentLoss, healthFactor, liquidationPrice, liquidationWaterfall, runTopic. Every module additionally exports run as an alias of its
primary function, and a meta object carrying its catalog id, domain, family,
shape and article URL.
Diagrams
How it works
This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.
References
- Uniswap v2 Core — Uniswap; Hayden Adams, Noah Zinsmeister, and Dan Robinson
- Uniswap v3 Core — Uniswap; Hayden Adams, Noah Zinsmeister, Moody Salem, River Keefer, and Dan Robinson
- UniswapV3Pool.sol — Uniswap; Uniswap Labs and protocol contributors
- Evidence boundary