Skip to content

Instantly share code, notes, and snippets.

@0xperp
Last active July 20, 2023 18:04
Show Gist options
  • Save 0xperp/fe5327d05b59c9122332d860adf2ba42 to your computer and use it in GitHub Desktop.
Save 0xperp/fe5327d05b59c9122332d860adf2ba42 to your computer and use it in GitHub Desktop.
greek_concentrated_lp_shares.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "greek_concentrated_lp_shares.ipynb",
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/0xperp/784a061d04fc6eecc240fd062860d588/greek_concentrated_lp_shares.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# Concentrated LP Shares and their Greeks\n",
"Given any concentrated LP share determine it's greek values, starting with `delta` and `gamma`. \n",
"\n",
"# Defining Virtual Liquidity\n",
"In a uniswap v2 pool each contract tracks the pool's current reserves: x and y. This is what keeps track of the price. In uniswap v3 there is what is known as virtual reserves, values for x and y that show the relationship in between ticks. \n",
"\n",
"Rather than tracking the virtual reserves, the liquididty (L) and sqrtPrice (sqrt(P)) are tracked. Of which virtual reserves can be calculated \n",
"\n",
"#### Liquidity and Price\n",
"$$ \n",
"L = \\sqrt{xy}\n",
"$$\n",
"$$\n",
"\\sqrt(P) = \\sqrt{\\frac y x}\n",
"$$\n",
"\n",
"#### Virtual Reserves\n",
"$$\n",
"x = \\frac{L} {\\sqrt{P}}\n",
"$$\n",
"$$\n",
"y = L * \\sqrt{P}\n",
"$$\n",
"\n",
"Once you know the virtual reserves (derived from token amounts and your tick ranges) calculations become very easy as they are similar to the `xy=k` uniswap v2\n",
"\n",
"You can calculate virtual liquididty by solving for `L`\n",
"\n",
"$$\n",
"(R_a + \\frac {L} {\\sqrt{p_b}})(R_b + L\\sqrt{p_b}) = L^2 \n",
"$$\n",
"\n",
"where `R_a` is the actual reserve of token a, `R_b` is the actual reserve of token b, `p_a` is the lower tick range, `p_b` is the upper tick range, `p` is the current price, and `L` is the virtual liquidity of the reserves.\n",
"\n",
"After you have calculated the virtual reserve liquidity `L`, you can move on to calculating the virtual reserves per each token, the total value of the position, and the greeks of the position.\n",
"\n",
"# Resources \n",
"- [Uniswap V3 Whitepaper](https://uniswap.org/whitepaper-v3.pdf) \n",
"- [The Replicating Portfolio of a Constant Product Market with Bounded Liquidity](https://deliverypdf.ssrn.com/delivery.php?ID=189069123081091108031087004085028103025072088045028034119098091076097075072089120027106016006035108029051124112102083069094027038010070008020104089092006103105022111020033003094088007079116001116088031018116116003092000068005090019006078006093017116031&EXT=pdf&INDEX=TRUE)\n",
"- [Hedging Uniswap v3 with Squeeth](https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11)\n"
],
"metadata": {
"id": "1q_BLPezj32V"
}
},
{
"cell_type": "code",
"source": [
"### determining `V` given virtual liquididty, range bounds, and current price \n",
"\n",
"import math\n",
"\n",
"# lower range \n",
"p_a = 3747\n",
"# upper range \n",
"p_b = 5024\n",
"# current price\n",
"p = 4360.61\n",
"# virtual liquididty\n",
"L = 1398.7\n",
"# expected `V` from https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11 \n",
"E_v = 13109.67\n",
"\n",
"v = 2*L*math.sqrt(p) - L*math.sqrt(p_a) - ((p*L)/math.sqrt(p_b))\n",
"print(f\"Virtual Liquidity {v}\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ZvtwrhYfkJ6N",
"outputId": "4696f410-e7be-4bbb-e6c5-4b6d61973a9d"
},
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Virtual Liquidity 13058.573068033904\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"### determining delta and gamma given virtual liquidity, range bounds, and current price \n",
"\n",
"import math\n",
"\n",
"# lower range \n",
"p_a = 3747\n",
"# upper range \n",
"p_b = 5024\n",
"# current price\n",
"p = 4360.61\n",
"# virtual liquididty\n",
"L = 1398.7\n",
"# expected `delta` from https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11 \n",
"E_delta = 1.448\n",
"# expected `gamma` from https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11 \n",
"E_gamma = 0.00243\n",
"\n",
"delta = L * (1/math.sqrt(p) - 1/math.sqrt(p_b))\n",
"gamma = 0.5 * L * math.pow(p, -1.5)\n",
"assert round(delta, 2) == round(E_delta, 2)\n",
"assert round(gamma, 2) == round(E_gamma, 2)\n",
"\n",
"def delta(L, p, p_b):\n",
" # print(L, p, p_b)\n",
" return L * (1/math.sqrt(p) - 1/math.sqrt(p_b))\n",
"\n",
"def gamma(L, p):\n",
" return 0.5 * L * math.pow(p, -1.5)\n",
"\n",
"print(f\" Delta: {delta(L, p, p_b)} \\n Gamma: {gamma(L, p)}\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hpjl4mmqlxLY",
"outputId": "36553b5b-038b-4bc8-9862-abd42ba0e862"
},
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" Delta: 1.447917185976956 \n",
" Gamma: 0.0024286990873210418\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"### determining the virtual liquidity given the token units supplied, range bounds and current price\n",
"\n",
"import math\n",
"import cmath\n",
"\n",
"# \u0001α token units as referenced in \"The Replicating Portfolio of a Constant Product Market with Bounded Liquidity\" paper \n",
"R_a = 10 \n",
"# β token units as referenced in \"The Replicating Portfolio of a Constant Product Market with Bounded Liquidity\" paper \n",
"R_b = 159.611 \n",
"# lower range \n",
"p_a = 5\n",
"# upper range \n",
"p_b = 15\n",
"# current price \n",
"p = 10\n",
"# expected virtual liquididty\n",
"E_Rv = 172.34\n",
"# expected virtual liquididty a\n",
"E_Rv_a = 54.49\n",
"# expected virtual liquidity b\n",
"E_Rv_b = 544.95\n",
"\n",
"# if you know the virtual liquididty of the entire position you can determine the virtual liquididty of each token pair\n",
"# R_a and R_b are the virtual liquididty values for the a and b tokens in the \"The Replicating Portfolio of a Constant Product Market with Bounded Liquidity\" paper \n",
"# in the \"Uniswap V3 Whitepaper\" when x and y are reffered to (ex. when describing the relationship between x, y, L and P see \"Price and Liquidity\") they already refer to the virtual liquiidty not the unit value of the tokens \n",
"\n",
"# virtual liquidity of token a\n",
"Rv_a = E_Rv / math.sqrt(p)\n",
"# virtual liquidity of token b \n",
"Rv_b = E_Rv * math.sqrt(p)\n",
"\n",
"# checking a and b virtual liquididty positions are equal to their expected values\n",
"assert round(Rv_a, 1) == round(E_Rv_a, 1)\n",
"assert round(Rv_b, 1) == round(E_Rv_b, 1)\n",
"# checking virtual liquididty ^ 2 is equal to the product of each virtual liquididty\n",
"assert round(Rv_a * Rv_b, 2) == round(E_Rv * E_Rv, 2)\n",
"\n",
"# full equations for calculating:\n",
"# - virtual reserves from liquididty and price \n",
"# - actual reserves from liquididty, price, and range \n",
"# can be found in equations 3-6 in \"The Replicating Portfolio of a Constant Product Market with Bounded Liquidity\" paper \n",
"\n",
"# actual reserves for token a\n",
"# R_a = L/math.sqrt(p) - L/math.sqrt(p_a)\n",
"\n",
"# actual reserves for token b \n",
"# R_b = L * math.sqrt(p) - L * math.sqrt(p_a)\n",
"\n",
"# calculating virtual liquidity given units supplied, range bounds, and price (a, b, p_a, p_b, p)\n",
"\n",
"def virtual_liquidity(p_a, p_b, R_a, R_b):\n",
" # solving \"bounded liquidity position\" eq. 1 for L \n",
" # terms for quadratic eq.\n",
" a = ((math.sqrt(p_a)/math.sqrt(p_b)) - 1)\n",
" b = ((R_b / math.sqrt(p_b)) + (R_a * math.sqrt(p_a)))\n",
" c = R_a * R_b\n",
"\n",
" # discriminant\n",
" d = (b**2) - (4*a*c)\n",
"\n",
" # solutions\n",
" solution1 = (-b - cmath.sqrt(d)) / (2 * a)\n",
" solution2 = (-b + cmath.sqrt(d)) / (2 * a)\n",
"\n",
" # virtual reserves\n",
" R_v = solution1.real if solution1.real > 0 else solution2.real\n",
"\n",
" # assert round(R_v, 1) == round(E_Rv, 1)\n",
"\n",
" # print(\n",
" # f\" Token a reserves: {R_a} \\n Token b reserves: {R_b} \\n Range: ({p_a}, {p_b}) \\n Current Price: {p} \\n Virtual Reserve a: {Rv_a} \\n Virtual Reserve b: {Rv_b} \\n Virtual Liquidity: {R_v}\"\n",
" # )\n",
"\n",
" return R_v\n",
"\n",
"# example of getting virtual liquidity from range and actual reserves\n",
"vR = virtual_liquidity(p_a, p_b, R_a, R_b)"
],
"metadata": {
"id": "kRbzKvdDmpW3"
},
"execution_count": 3,
"outputs": []
},
{
"cell_type": "code",
"source": [
"\n",
"# example of greeks given a concentrated LP share range and its actual token reserves\n",
"\n",
"# # a token reserves\n",
"# R_a = 10 \n",
"# # b token reserves\n",
"# R_b = 159.611 \n",
"# # lower range \n",
"# p_a = 5\n",
"# # upper range \n",
"# p_b = 15\n",
"# # currenet price \n",
"# p = 10\n",
"\n",
"# # lower range \n",
"# p_a = 3747\n",
"# # upper range \n",
"# p_b = 5024\n",
"# # current price\n",
"# p = 4360.61\n",
"# # virtual liquididty\n",
"# L = 1398.7\n",
"# # expected `delta` from https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11 \n",
"# E_delta = 1.448\n",
"# # expected `gamma` from https://medium.com/opyn/hedging-uniswap-v3-with-squeeth-bcaf1750ea11 \n",
"# E_gamma = 0.00243\n",
"\n",
"# a token reserves\n",
"R_a = 6779\n",
"# b token reserves\n",
"R_b = 1.448\n",
"# lower range \n",
"p_a = 3747.0\n",
"# upper range\n",
"p_b = 5024.0\n",
"# current price\n",
"p = 4360.61\n",
"\n",
"# virtual liquidity\n",
"L = virtual_liquidity(p_a, p_b, R_b, R_a)\n",
"\n",
"# greeks \n",
"d = delta(L, p, p_b)\n",
"g = gamma(L, p)\n",
"\n",
"print(f\" Delta: {d} \\n Gamma: {g}\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "t81oWOtKa8fC",
"outputId": "f90c9f2d-8511-47b2-df6b-d3ceab543eb8"
},
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" Delta: 1.4517521820181736 \n",
" Gamma: 0.002435131811150409\n"
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment