Skip to content

Commit 26b9e06

Browse files
authored
Merge pull request #395 from InjectiveLabs/feat/add_liquidable_positions_example_script
Feat/add liquidable positions example script
2 parents 8c6b3f5 + 1c7fb55 commit 26b9e06

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import asyncio
2+
from decimal import Decimal
3+
4+
from pyinjective.async_client_v2 import AsyncClient
5+
from pyinjective.core.network import Network
6+
7+
8+
def adjusted_margin(
9+
quantity: Decimal, margin: Decimal, is_long: bool, cumulative_funding_entry: Decimal, cumulative_funding: Decimal
10+
) -> Decimal:
11+
unrealized_funding_payment = (cumulative_funding - cumulative_funding_entry) * quantity * (-1 if is_long else 1)
12+
return margin + unrealized_funding_payment
13+
14+
15+
async def main() -> None:
16+
# select network: local, testnet, mainnet
17+
network = Network.mainnet()
18+
19+
# initialize grpc client
20+
client = AsyncClient(network)
21+
22+
positions_per_market = dict()
23+
24+
positions_dict = await client.fetch_chain_positions()
25+
liquidable_positions = []
26+
27+
for position in positions_dict["state"]:
28+
if position["marketId"] not in positions_per_market:
29+
positions_per_market[position["marketId"]] = []
30+
positions_per_market[position["marketId"]].append(position)
31+
32+
derivative_markets = await client.fetch_chain_derivative_markets(
33+
status="Active",
34+
market_ids=list(positions_per_market.keys()),
35+
)
36+
37+
for market in derivative_markets["markets"]:
38+
client_market = (await client.all_derivative_markets())[market["market"]["marketId"]]
39+
market_mark_price = client_market._from_extended_chain_format(Decimal(market["markPrice"]))
40+
for position in positions_per_market[client_market.id]:
41+
is_long = position["position"]["isLong"]
42+
quantity = client_market._from_extended_chain_format(Decimal(position["position"]["quantity"]))
43+
entry_price = client_market._from_extended_chain_format(Decimal(position["position"]["entryPrice"]))
44+
margin = client_market._from_extended_chain_format(Decimal(position["position"]["margin"]))
45+
cumulative_funding_entry = client_market._from_extended_chain_format(
46+
Decimal(position["position"]["cumulativeFundingEntry"])
47+
)
48+
market_cumulative_funding = client_market._from_extended_chain_format(
49+
Decimal(market["perpetualInfo"]["fundingInfo"]["cumulativeFunding"])
50+
)
51+
52+
adj_margin = adjusted_margin(quantity, margin, is_long, cumulative_funding_entry, market_cumulative_funding)
53+
adjusted_unit_margin = (adj_margin / quantity) * (-1 if is_long else 1)
54+
maintenance_margin_ratio = client_market.maintenance_margin_ratio * (-1 if is_long else 1)
55+
56+
liquidation_price = (entry_price + adjusted_unit_margin) / (Decimal(1) + maintenance_margin_ratio)
57+
58+
should_be_liquidated = (is_long and market_mark_price <= liquidation_price) or (
59+
not is_long and market_mark_price >= liquidation_price
60+
)
61+
62+
if should_be_liquidated:
63+
position_side = "Long" if is_long else "Short"
64+
print(
65+
f"{position_side} position for market {client_market.id} and subaccount "
66+
f"{position['subaccountId']} should be liquidated (liquidation price: "
67+
f"{liquidation_price.normalize()} / mark price: {market_mark_price.normalize()})"
68+
)
69+
liquidable_positions.append(position)
70+
71+
# print(f"\n\n\n")
72+
# print(json.dumps(liquidable_positions, indent=4))
73+
74+
75+
if __name__ == "__main__":
76+
asyncio.get_event_loop().run_until_complete(main())

0 commit comments

Comments
 (0)