Created
February 21, 2025 20:58
-
-
Save sambacha/09f630a22d340c23f4e7a2370744f98c to your computer and use it in GitHub Desktop.
Chitra Airdrop Python script
This file contains hidden or 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
import argparse | |
import numpy as np | |
from scipy.optimize import fsolve | |
def payoff(Pt, C, tau_s, r): | |
"""Calculates the payoff of the airdrop for a single user. | |
Args: | |
Pt: Asset price at time t. | |
C: Capital committed by the user at time tau_s. | |
tau_s: Random stopping time (airdrop time). | |
r: risk free rate | |
Returns: | |
The payoff, which is max(e^(-r*tau_s) * Pt * C - C, 0). Simplified. | |
""" | |
return max(np.exp(-r * tau_s) * Pt - 1, 0) * C | |
def hurdle_rate_multiplier(r, sigma): | |
"""Calculates the hurdle rate multiplier (phi). | |
Args: | |
r: Risk-free interest rate. | |
sigma: Volatility of the asset price. | |
Returns: | |
The hurdle rate multiplier (phi). | |
""" | |
def equation(a): | |
return 2 * a**2 - (2 * r / sigma**2 + 1) * a + 0.5 | |
# Find the root that leads to a positive hurdle rate | |
a_roots = fsolve(equation, [0, 1]) # Provide initial guesses | |
a = a_roots[np.argmin(np.abs(a_roots- 0.5))] # get the lowest | |
phi = (np.sqrt(1 + 4 * (1/a)) - 1) / (1/a) - 3/2. | |
return phi | |
def hurdle_rate(C, r, sigma): | |
"""Calculates the hurdle rate Li(t). Here, assuming t=gamma^-1 | |
Args: | |
C: Capital committed. | |
r: risk free rate. | |
sigma: Volatility | |
Returns: hurdle_rate Li | |
""" | |
phi = hurdle_rate_multiplier(r, sigma) | |
return (phi + 1) * C | |
def expected_exercise_time_simplified(x, L, nu, sigma_squared): | |
"""Calculates a simplified expected exercise time (O notation). | |
Args: | |
x: initial price. | |
L: Hurdle Rate. | |
nu: mu - sigma^2 / 2 | |
sigma_squared: sigma squared | |
Returns: | |
An approximation of the expected exercise time. O(nu) (x/L)^(-O(1)) | |
This version makes simplifying assumptions. | |
""" | |
#These need to be sufficiently large for the simplifications | |
if sigma_squared >= nu**2: | |
return (x / L)**(-2) / nu # Use -2 as a stand-in for -Theta(1) | |
else: | |
return np.inf | |
def expected_exercise_time(x, L, mu, sigma, gamma, simplified=True): | |
"""Calculates the expected exercise time. | |
Args: | |
x: Initial price (X0). | |
L: Hurdle rate (Li(gamma^-1)). | |
mu: Drift of the asset price. | |
sigma: Volatility of the asset price. | |
gamma: Parameter of the exponential distribution for tau_s. | |
simplified: calculate simplified version. | |
Returns: | |
The expected exercise time (E[T*]). | |
""" | |
nu = mu - sigma**2 / 2 | |
if simplified: | |
return expected_exercise_time_simplified(x, L, nu, sigma**2) | |
# Full calculation (more complex, less intuitive) | |
if x >= L: | |
alpha = (2 * gamma) / (np.sqrt(nu**2 + 2 * gamma * sigma**2) - nu) | |
return ( | |
(nu**2 + gamma * sigma**2 - nu * np.sqrt(nu**2 + 2 * gamma * sigma**2)) | |
/ (2 * nu * gamma**2) | |
* (x / L) ** (-alpha) | |
+ 1 / gamma | |
) | |
else: # x < L | |
term1 = ((np.sqrt(nu**2 + 2 * gamma * sigma**2) - nu) ** 2) / ( | |
4 * nu * gamma**2 | |
) | |
term2 = (sigma**2 / (2 * nu)) * np.log(x/L) | |
term3 = ((sigma**2 / (nu * (np.sqrt(nu**2 + 2*gamma*(sigma**2)) - nu) ) ) * (x/L)**( (2*nu) / (np.sqrt(nu**2 + 2*gamma*sigma**2) - nu) ) -1 ) | |
return term1 * (term2+term3) + 1/gamma | |
def main(): | |
parser = argparse.ArgumentParser( | |
description="Calculate metrics for a retroactive airdrop." | |
) | |
parser.add_argument( | |
"--initial_price", type=float, required=True, help="Initial asset price (X0)." | |
) | |
parser.add_argument( | |
"--capital", type=float, required=True, help="Capital committed by the user." | |
) | |
parser.add_argument( | |
"--mu", type=float, required=True, help="Drift of the asset price." | |
) | |
parser.add_argument( | |
"--sigma", type=float, required=True, help="Volatility of the asset price." | |
) | |
parser.add_argument( | |
"--gamma", type=float, required=True, help="Parameter of the exponential distribution for tau_s." | |
) | |
parser.add_argument( | |
"--risk_free_rate", type=float, required=True, help="Risk-free interest rate (r)." | |
) | |
parser.add_argument( | |
"--price_at_airdrop", | |
type=float, | |
required=False, | |
default=None, | |
help="Asset price at the time of the airdrop (Pt). Optional, for payoff calculation.", | |
) | |
parser.add_argument( | |
"--tau_s", | |
type=float, | |
required=False, | |
default=None, | |
help="Stopping Time, when airdrop happens. Optional.", | |
) | |
parser.add_argument( | |
"--simplified", | |
type=bool, | |
required=False, | |
default=True, | |
help="Use O notation formula, true or false.", | |
) | |
args = parser.parse_args() | |
L = hurdle_rate(args.capital, args.risk_free_rate, args.sigma) | |
print(f"Hurdle Rate (Li(gamma^-1)): {L:.4f}") | |
expected_time = expected_exercise_time( | |
args.initial_price, L, args.mu, args.sigma, args.gamma, args.simplified | |
) | |
print(f"Expected Exercise Time (E[T*]): {expected_time:.4f}") | |
if args.price_at_airdrop is not None and args.tau_s is not None: | |
payoff_value = payoff( | |
args.price_at_airdrop, args.capital, args.tau_s, args.risk_free_rate | |
) | |
print(f"Payoff: {payoff_value:.4f}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment