Instantly share code, notes, and snippets.

# SeanDaws/IL_Report_Example1.m

Last active December 6, 2021 17:19
Show Gist options
• Save SeanDaws/05c66c1119515e8f168c9f11c2920486 to your computer and use it in GitHub Desktop.
Impermanent Loss Report Mathematica Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 (*This is code that generates Example 1 of the report. Change these \ parameters to see how they affect IL*) Rval = 1;(*This is the skew ratio*) \[Sigma]0val = 1; (*This is the baseline volatility for the given expiry*) \ \[Alpha]val = 0.0125; (*This is the skew ratio update parameter*) \[Beta]val = 0.01; (*This is the baseline update parameter*) ssexample = 20; (*number of contracts in one standard size*) (*\[Alpha]val,\ \[Beta]val and ssexample are the current values on testnet*) rep = {R -> Rval, \[Sigma]0 -> \[Sigma]0val, \[Alpha] -> \[Alpha]val, \[Beta] \ -> \[Beta]val, ss -> ssexample}; \[Sigma]update = (R + \[Alpha]*n/ss)*(\[Sigma]0 + \[Beta]*n/ss) /. rep;(*Update volatility given some number of trades*) (*some functions need to use Black Scholes*) Nn[x_] := CDF[NormalDistribution[0, 1], x]; Nnprime[x_] := 1/Sqrt[2 \[Pi]]*Exp[-x^2/2]; \[Sigma][n_, Rb_, \[Sigma]0_, \[Alpha]_, \[Beta]_, ss_] := (Rb + \[Alpha]*n/ss)*(\[Sigma]0 + \[Beta]*n/ss); d1[\[Sigma]_, KK_, S_, r_, T_] := (Return[ 1/(\[Sigma]*Sqrt[T])*(Log[S/KK] + (r + \[Sigma]^2/2) (T))]); d2[\[Sigma]_, KK_, S_, r_, T_] := Return[d1[\[Sigma], KK, S, r, T] - \[Sigma]*Sqrt[T]]; NumericCost[\[Sigma]_, KK_, S_, r_, T_] := Return[Nn[d1[\[Sigma], KK, S, r, T]]*S - Nn[d2[\[Sigma], KK, S, r, T]]*KK* Exp[-r*(T)]];(*BS cost for a call*) \[Sigma]0TrueMarket = 3;(*This is the true market volatility.*) SpotExample = 2000; (*Spot price of ETH*) StrikeExample = 2100; (*The strike we are considering*) interestsrate = 0; (*We consider 0 interest rate for simplicity*) ExpiryExample = 28/365; (*Expiry in years. I.e. 28 days*) contractsrequired = n /. Solve[\[Sigma]update == \[Sigma]0TrueMarket && n > 0, n][[ 1]](*Compute how many contracts (N) are needed to update the AMM \ trading vol to the true trading vol. This is also known as the make \ up \[Eta]*) discountedcost = NIntegrate[ NumericCost[\[Sigma][n, Rval, \[Sigma]0val, \[Alpha]val, \[Beta]val, ssexample], StrikeExample, SpotExample, interestsrate, ExpiryExample], {n, 0, contractsrequired}](*Compute the most efficient way to extract \ impermanent loss by buying one contract at a time up to \[Eta].*) \ truecost = contractsrequired* NumericCost[\[Sigma][contractsrequired, Rval, \[Sigma]0val, \[Alpha]val, \[Beta]val, ssexample], StrikeExample, SpotExample, interestsrate, ExpiryExample](*This is the true cost of the (N) options at the \ fair market value*) ImpermanentLossExample = truecost - discountedcost (*This is the impermanent loss Lyra will suffer.*)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 (*We now generalise the above example.*) (*The impermanent loss function computes the IL the AMM suffers for a \ set of given parameters. MarketIV is the new market trading vol, \ STRIKEINDEX picks which strike we're tradng, SPOT is the spot price, \ Expiry is the time to expiry in years, SKEWS is a vector of skew \ ratios corresponding to each strike and BASELINE is the baseline vol.*) Clear[\[Sigma]]; \[Sigma][n_, Rb_, \[Sigma]0_, \[Alpha]_, \[Beta]_, ss_] := (Rb + \[Alpha]*n/ss)*(\[Sigma]0 + \[Beta]*n/ss); ImpermanentLoss[MarketIV_, STRIKEINDEX_, SPOT_, Expiry_, BASELINE_, ALPHA_, BETA_, SS_] := (STRIKES = {1800, 2000, 2100, 2300, 2500};(*Strikes on ETH currerntly on testnet*) SKEWS = {1, 1, 1, 1, 1};(*Skews for each strike. We assume all are 1 for simplicity*) contractsneeded = n /. Solve[\[Sigma][n, SKEWS[[STRIKEINDEX]], BASELINE, ALPHA, BETA, SS] == MarketIV && n > 0, n][[ 1]];(*Find the require contracts to get trading vol to the \ market vol*) CheapestCost = NIntegrate[ NumericCost[\[Sigma][n, SKEWS[[STRIKEINDEX]], BASELINE, ALPHA, BETA, SS], STRIKES[[STRIKEINDEX]], SPOT, 0, Expiry], {n, 0, contractsneeded}];(*This is the minimum cost (i.e. the exploit*) TrueMarketCost = contractsneeded* NumericCost[\[Sigma][contractsneeded, SKEWS[[STRIKEINDEX]], BASELINE, ALPHA, BETA, SS], STRIKES[[STRIKEINDEX]], SPOT, 0, Expiry];(*This is the true market value*) newskew = (SKEWS[[STRIKEINDEX]] + ALPHA*n/SS) /. {n -> contractsneeded};(*This is the new skew after the attack*) newbaseline = (BASELINE + BETA*n/SS) /. {n -> contractsneeded};(*This is the new baseline vol after the \ attack*) Return[{TrueMarketCost - CheapestCost, newbaseline, newskew, contractsneeded}]; (*Return: [Imperrmanent Loss, newbaseline vol, new skew vol, how many contracts the exploit took]*) ); (*Figure 1: Changing expiry and spot*) expFig1 = {7/365, 14/365, 21/365, 28/365};(*what expiries are we considering*) SpotFig1 = {1000, 3000, 2000};(*what spots?*) StrikeIndexFig1 = 3;(*Which strike? 3 \[Rule] the 3rd strike in STRIKES, i.e. K=2100*) MAXVOL = 5;(*What is the maximum external market vol*) changingexpiry = Plot[{ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[3]], expFig1[[1]], 1, .0125, .01, 20][[1]], ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[3]], expFig1[[2]], 1, .0125, .01, 20][[1]], ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[3]], expFig1[[3]], 1, .0125, .01, 20][[1]], ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[3]], expFig1[[4]], 1, .0125, .01, 20][[1]]}, {x, 1.7, MAXVOL}, PlotStyle -> {Green, Red, Magenta, Blue}, AxesLabel -> {"Market IV (g)", "Impermanent Loss (\$)"}, ImageSize -> 300];(*effect of changing expiry*) changingspot = Plot[{ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[1]], expFig1[[4]], 1, .0125, .01, 20][[1]], ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[2]], expFig1[[4]], 1, .0125, .01, 20][[1]], ImpermanentLoss[x, StrikeIndexFig1, SpotFig1[[3]], expFig1[[4]], 1, .0125, .01, 20][[1]]}, {x, 1.7, MAXVOL}, PlotStyle -> {Red, Magenta, Blue}, AxesLabel -> {"Market IV (g)", "Impermanent Loss (\$)"}, ImageSize -> 300];(*effect ofo changing spot*) Fig1Pics = {changingexpiry, changingspot} (*Figure 2:Plot the IL for strike 2100 with spot 2000 and expiry 28 \ days. Baseline vol is 1. Now we change alpha,beta and ss*) SpotFig2 = 2000; ExpFig2 = 28/365; baseFig2 = 1; StrikeIndexFig2 = 3; (*let's trade the middle strike K=2100*) alphas = {0.0075, 0.0125, 0.0175}; betas = {0.005, 0.01, 0.015};(*these are the \[Alpha],\[Beta],S vals we're iterating \ over*) Svals = {30, 20, 10}; MAXVOLFig2 = 5; changingalpha = Plot[{ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[1]], betas[[2]], Svals[[2]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[2]], Svals[[2]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[3]], betas[[2]], Svals[[2]]][[1]]}, {x, 1.7, MAXVOLFig2}, PlotStyle -> {Red, Blue, Magenta}, AxesLabel -> {"Market IV (g)", "Impermanent Loss (\$)"}, ImageSize -> 300]; (*Plot IL against market vol but changing the alpha value*) changingbeta = Plot[{ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[1]], Svals[[2]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[2]], Svals[[2]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[3]], Svals[[2]]][[1]]}, {x, 1.7, MAXVOLFig2}, PlotStyle -> {Red, Blue, Magenta}, AxesLabel -> {"Market IV (g)", "Impermanent Loss (\$)"}, ImageSize -> 300]; (*changing beta*) changingSS = Plot[{ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[2]], Svals[[1]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[2]], Svals[[2]]][[1]], ImpermanentLoss[x, StrikeIndexFig2, SpotFig2, ExpFig2, baseFig2, alphas[[2]], betas[[2]], Svals[[3]]][[1]]}, {x, 1.7, MAXVOLFig2}, PlotStyle -> {Red, Blue, Magenta}, AxesLabel -> {"Market IV (g)", "Impermanent Loss (\$)"}, ImageSize -> 300]; (*Changing number of contracts in one standard size*) Fig2Pics = \ {changingalpha, changingbeta, changingSS}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters