Skip to content

Instantly share code, notes, and snippets.

@darkerego
Last active January 19, 2023 00:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darkerego/026d3547d4a3b3b8e5baeb5b35e5c93c to your computer and use it in GitHub Desktop.
Save darkerego/026d3547d4a3b3b8e5baeb5b35e5c93c to your computer and use it in GitHub Desktop.
Price Calculation From Reserves
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