Last active
January 19, 2023 00:24
-
-
Save darkerego/026d3547d4a3b3b8e5baeb5b35e5c93c to your computer and use it in GitHub Desktop.
Price Calculation From Reserves
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
class Factory(NamedTuple): | |
router: str | |
address: str | |
name: str | |
class TokenPair(NamedTuple): | |
token0: str | |
token1: str | |
address: str | |
decimals_0: int | |
decimals_1: int | |
symbol_0: str | |
symbol_1: str | |
factory: Factory | |
@property | |
def name(self): | |
return '%s_%s' % (self.symbol_0, self.symbol_1) | |
class LiquidityPool(NamedTuple): | |
pair: TokenPair | |
@property | |
def name(self): | |
return '%s_%s' % (self.pair.symbol_0, self.pair.symbol_1) | |
@dataclasses.dataclass | |
class _LiquidityPool: | |
def __init__(self, pool: LiquidityPool, w3: web3.Web3): | |
self.pair = pool.pair | |
self.reserve_0 = pool.reserve_0 | |
self.reserve_1 = pool.reserve_1 | |
self.w3 = w3 | |
self.name = '%s_%s' % (self.pair.symbol_0, self.pair.symbol_1) | |
def update_reserves(self): | |
pair_address = self.pair.address | |
pair_contract = self.w3.eth.contract(to_checksum_address(pair_address), abi=abi_lib.UNI_V2_PAIR) | |
reserves = pair_contract.functions.getReserves().call() | |
self.reserve_0 = int(reserves[0]) | |
self.reserve_1 = int(reserves[1]) | |
def reserves(self): | |
token0_reserve = self.reserve_0 # / (10 ** pair.decimals_0) | |
token1_reserve = self.reserve_1 # / (10 ** pair.decimals_1) | |
return token0_reserve, token1_reserve | |
def quote_price(self): | |
token0_reserve = self.reserve_0 | |
token1_reserve = self.reserve_1 | |
price = (token0_reserve / 10 ** self.pair.decimals_0) / (token1_reserve / self.pair.decimals_1) | |
return price | |
def base_price(self): | |
token0_reserve = self.reserve_0 | |
token1_reserve = self.reserve_1 | |
price = (token1_reserve / self.pair.decimals_1) / (token0_reserve / 10 ** self.pair.decimals_0) | |
return price | |
def calculate_swap(self, qty=0, max_impact=0.01, token=0): | |
""" | |
Calculate amount received and execution price for a swap | |
with price impact. | |
Pool info | |
USDC = 2,000,000 | |
ETH = 1,000 | |
Constant Product = 2,000,000,000 | |
Market Price = 2,000 | |
First example, 10,000 USDC for ETH | |
After swap | |
USDC = 2,010,000 (because we added 10,000 to the pool) | |
Constant Product = 2,000,000,000 (stays the same) | |
ETH = 995.024 (constant product / new usdc amount) | |
ETH recieved = 4.976 (old eth amount - new eth amount) | |
Price paid per ETH = 2009.64 USDC | |
ETH recieved = 4.976 (old eth amount - new eth amount) | |
Price impact = 0.48% | |
:param qty: of sell token | |
:param token: index of sell token | |
:return: amount received, price paid, price impact, qty | |
""" | |
fee = 0.003 | |
r0, r1 = self.reserves() | |
r0 = (r0 / (10 ** self.pair.decimals_0)) | |
r1 = (r1 / (10 ** self.pair.decimals_1)) | |
constant_product = r0 * r1 | |
token0_price = r1 / r0 | |
token1_price = r0 / r1 | |
if qty == 0 and token == 0: | |
qty = r0 * max_impact / ((1 - max_impact) * (1 - fee)) | |
if qty == 0 and token == 1: | |
qty = r1 * max_impact / ((1 - max_impact) * (1 - fee)) | |
if token == 0: | |
old_price = token1_price | |
new_r0 = r0 + (qty * (1 - fee)) | |
new_constant_product = constant_product + (1 - (qty * (1 - fee))) | |
new_r1 = new_constant_product / new_r0 | |
new_price = new_r0 / new_r1 | |
price_impact = ((new_price / old_price) - 1) * 100 | |
received = r1 - new_r1 | |
return received, new_price, price_impact, qty | |
else: | |
old_price = token0_price | |
new_r1 = r1 + (qty * (1 - fee)) | |
new_constant_product = constant_product + (1 - (qty * (1 - fee))) | |
new_r0 = new_constant_product / new_r1 | |
new_price = new_r1 / new_r0 | |
price_impact = ((new_price / old_price) - 1) * 100 | |
received = r0 - new_r0 | |
return received, new_price, price_impact, qty |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment