Nothing
utils::globalVariables(c("Scenario", "Value"))
#' Impermanent Loss Calculator for Weighted AMM Pools
#'
#' Calculates the Nominal Impermanent Loss (IL), Percentage IL, and Net Profit and Loss (PnL)
#' for a liquidity position in a weighted Automated Market Maker (AMM) pool.
#' This function is crucial for assessing the performance of liquidity provider positions
#' in protocols like Balancer and Uniswap.
#' @param prices_old A numeric vector of initial prices for each asset.
#' @param prices_new A numeric vector of new prices for each asset.
#' @param weights A numeric vector of weights (must sum to 1) corresponding to the assets.
#' @param investment The initial total dollar value invested in the pool.
#' @param fees The total dollar value of trading fees earned by the LP during the period.
#' @param plot A logical value. If TRUE, generates a bar chart comparing the value if held,
#' value in the pool, and the net value (pool + fees).
#' @return A list containing the core metrics:
#' \itemize{
#' \item \code{Value if held}: Total current value if assets were held outside the pool.
#' \item \code{Value in pool}: Total current value of the tokens in the pool.
#' \item \code{impermanent_loss_percent}: The IL as a percentage of the held portfolio value.
#' \item \code{Nominal impermanent loss}: The IL as a dollar-value opportunity loss.
#' \item \code{Fee offset ($)}: The total dollar fees earned.
#' \item \code{Net gain}: The LP's net PnL (Fees MINUS Nominal IL) relative to holding.
#' }
#' @references Tiruviluamala, N., Port, A., & Lewis, E. (2022). A general framework for impermanent loss in automated market makers. arXiv preprint arXiv:2203.11352.
#' @import ggplot2
#' @examples
#' library(impermanentlosscalc)
#' library(ggplot2)
#' # Example 1: 3-Asset Unbalanced Pool (Weights: 30/20/50)
#' impermanent_loss(
#' prices_old = c(10, 20, 40),
#' prices_new = c(9, 22, 35),
#' weights = c(0.3, 0.2, 0.5),
#' investment = 1000,
#' fees = 10,
#' plot = TRUE
#' )
#'
#'
#' # Example 2: No price change, demonstrating IL is zero.
#' impermanent_loss(
#' prices_old = c(3, 3),
#' prices_new = c(3, 3),
#' weights = c(0.5, 0.5),
#' investment = 500,
#' fees = 0
#' )
#' @export
impermanent_loss <- function(
prices_old,
prices_new,
weights,
investment,
fees,
plot = FALSE){
# Check inputs
if(length(prices_old) != length(prices_new) ||
length(prices_old) != length(weights)){stop(
"Old Prices, New Prices, and Weights must be equal length"
)}
if(abs(sum(weights) - 1) > 1e-6){stop("Weights must sum to 1")}
#Relative price changes
r <- prices_new/prices_old
#Weighted geometric mean
geom_mean <- prod(r ^ weights)
#Weighted arithmetic mean
arithmetic_mean <- sum(weights * r)
#Value if held outside pool
value_if_held <- investment * arithmetic_mean
#Impermanent loss factor
impermanent_loss_factor <- geom_mean/arithmetic_mean
#Value in pool
value_in_pool <- value_if_held * impermanent_loss_factor
#Nominal impermanent loss
nominal_impermanent_loss <- value_if_held - value_in_pool
#Percent impermanent loss
impermanent_loss_percent <- nominal_impermanent_loss / value_if_held
#Net Impermanent Loss
net_gain <- fees - nominal_impermanent_loss
#Net value adjusted for fees
net_value <- value_in_pool + fees
if(plot){
# Inside the if(plot) block:
plot_data <- data.frame(
Scenario = c("Held","Pool","Pool + Fees"),
Value = c(value_if_held, value_in_pool, net_value)
)
graph <- ggplot2::ggplot(data = plot_data, aes(x = Scenario,
y = Value, fill = Scenario))+
ggplot2::geom_bar(stat = "identity")+
ggplot2::labs(title = "Holding vs Lending")+
ggplot2::theme(plot.title = ggplot2::element_text(hjust = .5))
print(graph)
}
return(list(
"Value if held" = value_if_held,
"Value in pool" = value_in_pool,
"impermanent_loss_percent" = impermanent_loss_percent,
"Nominal impermanent loss" = nominal_impermanent_loss,
"Fee offset ($)" = fees,
"Net gain" = net_gain
))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.