From a1b1083f64605ff3815dc9a991da99c37018eb50 Mon Sep 17 00:00:00 2001 From: voyz Date: Sat, 18 Mar 2023 19:20:45 -0300 Subject: [PATCH 1/3] feat: added util functions for fee calculations --- uniswap/util.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/uniswap/util.py b/uniswap/util.py index 720f6d6..d627235 100644 --- a/uniswap/util.py +++ b/uniswap/util.py @@ -126,3 +126,20 @@ def nearest_tick(tick: int, fee: int) -> int: def chunks(arr: Sequence[Any], n: int) -> Generator: for i in range(0, len(arr), n): yield arr[i : i + n] + +def fee_to_fraction(fee:int): + return fee / 1000000 + +def fraction_to_fee(fraction:float): + return fraction * 1000000 + +def realised_fee_percentage(fee:int, amount_in:int) -> float: + """ + Calculate realised fee expressed as a percentage of the amount_in. + The realised fee is rounded up as fractional units cannot be used - + this correlates to how the fees are rounded by Uniswap. + """ + + fee_percentage = fee_to_fraction(fee) + fee_realised = math.ceil(amount_in * fee_percentage) + return fee_realised / amount_in \ No newline at end of file From d88362d479f89cec6084dda87ded26321c4efc88 Mon Sep 17 00:00:00 2001 From: voyz Date: Sat, 18 Mar 2023 19:23:14 -0300 Subject: [PATCH 2/3] feat: price impact calculation now excludes fees --- uniswap/uniswap.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/uniswap/uniswap.py b/uniswap/uniswap.py index 3b82b3b..1098571 100644 --- a/uniswap/uniswap.py +++ b/uniswap/uniswap.py @@ -33,6 +33,7 @@ encode_sqrt_ratioX96, is_same_address, nearest_tick, + realised_fee_percentage, ) from .decorators import supports, check_approval from .constants import ( @@ -1917,7 +1918,14 @@ def estimate_price_impact( cost_amount / (amount_in / (10 ** self.get_token(token_in).decimals)) ) / 10 ** self.get_token(token_out).decimals - return float((price_small - price_amount) / price_small) + # calculate and subtract the realised fees from the price impact. See: + # https://github.com/uniswap-python/uniswap-python/issues/310 + # The fee calculation will need to be updated when adding support for the AutoRouter. + price_impact_with_fees = float((price_small - price_amount) / price_small) + fee_realised_percentage = realised_fee_percentage(fee, amount_in) + price_impact_real = price_impact_with_fees - fee_realised_percentage + + return price_impact_real # ------ Exchange ------------------------------------------------------------------ @supports([1, 2]) From 99cef12190b4ccb5b64da37c9c60734864a918f7 Mon Sep 17 00:00:00 2001 From: voyz Date: Fri, 21 Jul 2023 10:06:42 -0500 Subject: [PATCH 3/3] removed unused 'fraction_to_fee' and reformatted with black --- examples/price_impact.py | 8 ++++---- tests/test_uniswap.py | 11 +++++------ uniswap/constants.py | 9 +++++++-- uniswap/util.py | 9 ++++----- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/examples/price_impact.py b/examples/price_impact.py index 15c3a0a..e9c99c9 100644 --- a/examples/price_impact.py +++ b/examples/price_impact.py @@ -27,7 +27,7 @@ def usdt_to_vxv_v2(): # Compare the results with the output of: # https://app.uniswap.org/#/swap?use=v2&inputCurrency=0xdac17f958d2ee523a2206206994597c13d831ec7&outputCurrency=0x7d29a64504629172a429e64183d6673b9dacbfce - qty = 10 * 10 ** 8 + qty = 10 * 10**8 # price = uniswap.get_price_input(usdt, vxv, qty, route=route) / 10 ** 18 # print(price) @@ -38,7 +38,7 @@ def usdt_to_vxv_v2(): # The slippage for v3 (in example below) returns correct results. print(f"Impact for buying VXV on v2 with {qty / 10**8} USDT: {_perc(impact)}") - qty = 13900 * 10 ** 8 + qty = 13900 * 10**8 impact = uniswap.estimate_price_impact(usdt, vxv, qty, route=route) print(f"Impact for buying VXV on v2 with {qty / 10**8} USDT: {_perc(impact)}") @@ -49,11 +49,11 @@ def eth_to_vxv_v3(): # Compare the results with the output of: # https://app.uniswap.org/#/swap?use=v3&inputCurrency=ETH&outputCurrency=0x7d29a64504629172a429e64183d6673b9dacbfce - qty = 1 * 10 ** 18 + qty = 1 * 10**18 impact = uniswap.estimate_price_impact(eth, vxv, qty, fee=10000) print(f"Impact for buying VXV on v3 with {qty / 10**18} ETH: {_perc(impact)}") - qty = 100 * 10 ** 18 + qty = 100 * 10**18 impact = uniswap.estimate_price_impact(eth, vxv, qty, fee=10000) print(f"Impact for buying VXV on v3 with {qty / 10**18} ETH: {_perc(impact)}") diff --git a/tests/test_uniswap.py b/tests/test_uniswap.py index 11a4bc9..79c18e1 100644 --- a/tests/test_uniswap.py +++ b/tests/test_uniswap.py @@ -65,7 +65,7 @@ def test_assets(client: Uniswap): """ tokens = get_tokens(client.netname) - for token_name, amount in [("DAI", 100 * 10 ** 18), ("USDC", 100 * 10 ** 6)]: + for token_name, amount in [("DAI", 100 * 10**18), ("USDC", 100 * 10**6)]: token_addr = tokens[token_name] price = client.get_price_output(_str_to_addr(ETH_ADDRESS), token_addr, amount) logger.info(f"Cost of {amount} {token_name}: {price}") @@ -125,8 +125,8 @@ def does_not_raise(): yield -ONE_ETH = 10 ** 18 -ONE_USDC = 10 ** 6 +ONE_ETH = 10**18 +ONE_USDC = 10**6 ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -134,7 +134,6 @@ def does_not_raise(): # TODO: Change pytest.param(..., mark=pytest.mark.xfail) to the expectation/raises method @pytest.mark.usefixtures("client", "web3") class TestUniswap(object): - # ------ Exchange ------------------------------------------------------------------ def test_get_fee_maker(self, client: Uniswap): if client.version not in [1, 2]: @@ -343,7 +342,7 @@ def test_v3_deploy_pool_with_liquidity( amount1, tick_lower=min_tick, tick_upper=max_tick, - deadline=2 ** 64, + deadline=2**64, ) assert r["status"] @@ -357,7 +356,7 @@ def test_v3_deploy_pool_with_liquidity( @pytest.mark.parametrize( "deadline", - [(2 ** 64)], + [(2**64)], ) def test_close_position(self, client: Uniswap, deadline): if client.version != 3: diff --git a/uniswap/constants.py b/uniswap/constants.py index 12959a7..de6d06a 100644 --- a/uniswap/constants.py +++ b/uniswap/constants.py @@ -78,7 +78,12 @@ MAX_TICK = -MIN_TICK # Source: https://github.com/Uniswap/v3-core/blob/v1.0.0/contracts/UniswapV3Factory.sol#L26-L31 -_tick_spacing = {100:1, 500: 10, 3_000: 60, 10_000: 200} +_tick_spacing = {100: 1, 500: 10, 3_000: 60, 10_000: 200} # Derived from (MIN_TICK//tick_spacing) >> 8 and (MAX_TICK//tick_spacing) >> 8 -_tick_bitmap_range = {100:(-3466, 3465), 500: (-347, 346), 3_000: (-58, 57), 10_000: (-18, 17)} +_tick_bitmap_range = { + 100: (-3466, 3465), + 500: (-347, 346), + 3_000: (-58, 57), + 10_000: (-18, 17), +} diff --git a/uniswap/util.py b/uniswap/util.py index d627235..755cfdd 100644 --- a/uniswap/util.py +++ b/uniswap/util.py @@ -127,13 +127,12 @@ def chunks(arr: Sequence[Any], n: int) -> Generator: for i in range(0, len(arr), n): yield arr[i : i + n] -def fee_to_fraction(fee:int): + +def fee_to_fraction(fee: int): return fee / 1000000 -def fraction_to_fee(fraction:float): - return fraction * 1000000 -def realised_fee_percentage(fee:int, amount_in:int) -> float: +def realised_fee_percentage(fee: int, amount_in: int) -> float: """ Calculate realised fee expressed as a percentage of the amount_in. The realised fee is rounded up as fractional units cannot be used - @@ -142,4 +141,4 @@ def realised_fee_percentage(fee:int, amount_in:int) -> float: fee_percentage = fee_to_fraction(fee) fee_realised = math.ceil(amount_in * fee_percentage) - return fee_realised / amount_in \ No newline at end of file + return fee_realised / amount_in pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy