forked from atiselsts/uniswap-v3-liquidity-math
-
Notifications
You must be signed in to change notification settings - Fork 0
/
subgraph-liquidity-single-position-example.py
executable file
·125 lines (102 loc) · 3.33 KB
/
subgraph-liquidity-single-position-example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python3
#
# Example that shows a single position in the 0.05% USDC/DAI pool,
# using data from the Uniswap v3 subgraph.
#
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
import math
import sys
POSITION_ID = "2"
# if passed in command line, use an alternative pool ID
if len(sys.argv) > 1:
POSITION_ID = sys.argv[1]
TICK_BASE = 1.0001
position_query = """query get_position($position_id: ID!) {
positions(where: {id: $position_id}) {
liquidity
tickLower { tickIdx }
tickUpper { tickIdx }
pool { id }
token0 {
symbol
decimals
}
token1 {
symbol
decimals
}
}
}"""
# return the tick and the sqrt of the current price
pool_query = """query get_pools($pool_id: ID!) {
pools(where: {id: $pool_id}) {
tick
sqrtPrice
}
}"""
def tick_to_price(tick):
return TICK_BASE ** tick
client = Client(
transport=RequestsHTTPTransport(
url='https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3',
verify=True,
retries=5,
))
# get position info
try:
variables = {"position_id": POSITION_ID}
response = client.execute(gql(position_query), variable_values=variables)
if len(response['positions']) == 0:
print("position not found")
exit(-1)
position = response['positions'][0]
liquidity = int(position["liquidity"])
tick_lower = int(position["tickLower"]["tickIdx"])
tick_upper = int(position["tickUpper"]["tickIdx"])
pool_id = position["pool"]["id"]
token0 = position["token0"]["symbol"]
token1 = position["token1"]["symbol"]
decimals0 = int(position["token0"]["decimals"])
decimals1 = int(position["token1"]["decimals"])
except Exception as ex:
print("got exception while querying position data:", ex)
exit(-1)
#print("pool id=", pool_id)
# get pool info for current price
try:
variables = {"pool_id": pool_id}
response = client.execute(gql(pool_query), variable_values=variables)
if len(response['pools']) == 0:
print("pool not found")
exit(-1)
pool = response['pools'][0]
current_tick = int(pool["tick"])
current_sqrt_price = int(pool["sqrtPrice"]) / (2 ** 96)
except Exception as ex:
print("got exception while querying pool data:", ex)
exit(-1)
# Compute and print the current price
current_price = tick_to_price(current_tick)
adjusted_current_price = current_price / (10 ** (decimals1 - decimals0))
print("Current price={:.6f} {} for {} at tick {}".format(adjusted_current_price, token1, token0, current_tick))
sa = tick_to_price(tick_lower / 2)
sb = tick_to_price(tick_upper / 2)
if tick_upper <= current_tick:
# Only token1 locked
amount0 = 0
amount1 = liquidity * (sb - sa)
elif tick_lower < current_tick < tick_upper:
# Both tokens present
amount0 = liquidity * (sb - current_sqrt_price) / (current_sqrt_price * sb)
amount1 = liquidity * (current_sqrt_price - sa)
else:
# Only token0 locked
amount0 = liquidity * (sb - sa) / (sa * sb)
amount1 = 0
# print info about the position
adjusted_amount0 = amount0 / (10 ** decimals0)
adjusted_amount1 = amount1 / (10 ** decimals1)
print(" position {: 7d} in range [{},{}]: {:.2f} {} and {:.2f} {} at the current price".format(
int(POSITION_ID), tick_lower, tick_upper,
adjusted_amount0, token0, adjusted_amount1, token1))