From fd202178fb410faaa9dd0900f55dd8f7b58cf870 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Wed, 2 Oct 2024 09:19:13 -0700
Subject: [PATCH] Update pages to use backend api"
---
src/lib/api.py | 50 ++++++
src/lib/health_utils.py | 279 -----------------------------
src/lib/page.py | 20 ++-
src/lib/user_metrics.py | 40 ++---
src/main.py | 16 +-
src/sections/asset_liab_matrix.py | 173 ------------------
src/sections/liquidation_curves.py | 90 ++--------
src/sections/scenario.py | 2 +-
8 files changed, 98 insertions(+), 572 deletions(-)
create mode 100644 src/lib/api.py
delete mode 100644 src/lib/health_utils.py
delete mode 100644 src/sections/asset_liab_matrix.py
diff --git a/src/lib/api.py b/src/lib/api.py
new file mode 100644
index 0000000..77fb681
--- /dev/null
+++ b/src/lib/api.py
@@ -0,0 +1,50 @@
+from typing import Optional
+
+import pandas as pd
+import requests
+
+
+BASE_URL = "http://localhost:8000"
+
+
+def api(
+ section: str,
+ path: str,
+ path_extra_1: Optional[str] = None,
+ path_extra_2: Optional[
+ str
+ ] = None, # TODO: this is pretty silly, but it works for now
+ as_json: bool = False,
+ params: Optional[dict] = None,
+):
+ """
+ Fetches data from the backend API. To find the corresponding
+ path, look at the `backend/api/` directory. It should be setup
+ so that the `section` is the name of the file, the `path` is the
+ function inside the file.
+
+ Args:
+ section (str): The section of the API to fetch from.
+ path (str): The path of the API to fetch from.
+ path_extra (Optional[str]): An optional extra path to append to the path.
+ as_json (bool): Whether to return the response as JSON.
+
+ Returns:
+ The response from the API.
+ """
+ if path_extra_1:
+ path = f"{path}/{path_extra_1}"
+ if path_extra_2:
+ path = f"{path}/{path_extra_2}"
+ if params:
+ response = requests.get(f"{BASE_URL}/api/{section}/{path}", params=params)
+ else:
+ response = requests.get(f"{BASE_URL}/api/{section}/{path}")
+
+ if as_json:
+ return response.json()
+
+ try:
+ return pd.DataFrame(response.json())
+ except ValueError:
+ return response.json()
diff --git a/src/lib/health_utils.py b/src/lib/health_utils.py
deleted file mode 100644
index c5cc1bf..0000000
--- a/src/lib/health_utils.py
+++ /dev/null
@@ -1,279 +0,0 @@
-import heapq
-from typing import Any
-
-from driftpy.constants.numeric_constants import BASE_PRECISION
-from driftpy.constants.numeric_constants import PRICE_PRECISION
-from driftpy.constants.numeric_constants import SPOT_BALANCE_PRECISION
-from driftpy.pickle.vat import Vat
-from driftpy.types import is_variant
-import pandas as pd
-import plotly.express as px
-
-from utils import to_financial
-
-
-def get_largest_perp_positions(vat: Vat):
- top_positions: list[Any] = []
-
- for user in vat.users.values():
- for position in user.get_user_account().perp_positions:
- if position.base_asset_amount > 0:
- market_price = vat.perp_oracles.get(position.market_index)
- if market_price is not None:
- market_price_ui = market_price.price / PRICE_PRECISION
- base_asset_value = (
- abs(position.base_asset_amount) / BASE_PRECISION
- ) * market_price_ui
- heap_item = (
- to_financial(base_asset_value),
- user.user_public_key,
- position.market_index,
- position.base_asset_amount / BASE_PRECISION,
- )
-
- if len(top_positions) < 10:
- heapq.heappush(top_positions, heap_item)
- else:
- heapq.heappushpop(top_positions, heap_item)
-
- positions = sorted(
- (value, pubkey, market_idx, amt)
- for value, pubkey, market_idx, amt in top_positions
- )
-
- positions.reverse()
-
- data = {
- "Market Index": [pos[2] for pos in positions],
- "Value": [f"${pos[0]:,.2f}" for pos in positions],
- "Base Asset Amount": [f"{pos[3]:,.2f}" for pos in positions],
- "Public Key": [pos[1] for pos in positions],
- }
-
- return data
-
-
-def get_largest_spot_borrows(vat: Vat):
- top_borrows: list[Any] = []
-
- for user in vat.users.values():
- for position in user.get_user_account().spot_positions:
- if position.scaled_balance > 0 and is_variant(
- position.balance_type, "Borrow"
- ):
- market_price = vat.spot_oracles.get(position.market_index)
- if market_price is not None:
- market_price_ui = market_price.price / PRICE_PRECISION
- borrow_value = (
- position.scaled_balance / SPOT_BALANCE_PRECISION
- ) * market_price_ui
- heap_item = (
- to_financial(borrow_value),
- user.user_public_key,
- position.market_index,
- position.scaled_balance / SPOT_BALANCE_PRECISION,
- )
-
- if len(top_borrows) < 10:
- heapq.heappush(top_borrows, heap_item)
- else:
- heapq.heappushpop(top_borrows, heap_item)
-
- borrows = sorted(
- (value, pubkey, market_idx, amt)
- for value, pubkey, market_idx, amt in top_borrows
- )
-
- borrows.reverse()
-
- data = {
- "Market Index": [pos[2] for pos in borrows],
- "Value": [f"${pos[0]:,.2f}" for pos in borrows],
- "Scaled Balance": [f"{pos[3]:,.2f}" for pos in borrows],
- "Public Key": [pos[1] for pos in borrows],
- }
-
- return data
-
-
-def get_account_health_distribution(vat: Vat):
- health_notional_distributions = {
- "0-10%": 0,
- "10-20%": 0,
- "20-30%": 0,
- "30-40%": 0,
- "40-50%": 0,
- "50-60%": 0,
- "60-70%": 0,
- "70-80%": 0,
- "80-90%": 0,
- "90-100%": 0,
- }
- health_counts = {
- "0-10%": 0,
- "10-20%": 0,
- "20-30%": 0,
- "30-40%": 0,
- "40-50%": 0,
- "50-60%": 0,
- "60-70%": 0,
- "70-80%": 0,
- "80-90%": 0,
- "90-100%": 0,
- }
-
- for user in vat.users.values():
- total_collateral = user.get_total_collateral() / PRICE_PRECISION
- current_health = user.get_health()
- match current_health:
- case _ if current_health < 10:
- health_notional_distributions["0-10%"] += total_collateral
- health_counts["0-10%"] += 1
- case _ if current_health < 20:
- health_notional_distributions["10-20%"] += total_collateral
- health_counts["10-20%"] += 1
- case _ if current_health < 30:
- health_notional_distributions["20-30%"] += total_collateral
- health_counts["20-30%"] += 1
- case _ if current_health < 40:
- health_notional_distributions["30-40%"] += total_collateral
- health_counts["30-40%"] += 1
- case _ if current_health < 50:
- health_notional_distributions["40-50%"] += total_collateral
- health_counts["40-50%"] += 1
- case _ if current_health < 60:
- health_notional_distributions["50-60%"] += total_collateral
- health_counts["50-60%"] += 1
- case _ if current_health < 70:
- health_notional_distributions["60-70%"] += total_collateral
- health_counts["60-70%"] += 1
- case _ if current_health < 80:
- health_notional_distributions["70-80%"] += total_collateral
- health_counts["70-80%"] += 1
- case _ if current_health < 90:
- health_notional_distributions["80-90%"] += total_collateral
- health_counts["80-90%"] += 1
- case _:
- health_notional_distributions["90-100%"] += total_collateral
- health_counts["90-100%"] += 1
- df = pd.DataFrame(
- {
- "Health Range": list(health_counts.keys()),
- "Counts": list(health_counts.values()),
- "Notional Values": list(health_notional_distributions.values()),
- }
- )
-
- fig = px.bar(
- df,
- x="Health Range",
- y="Counts",
- title="Health Distribution",
- hover_data={"Notional Values": ":,"}, # Custom format for notional values
- labels={"Counts": "Num Users", "Notional Values": "Notional Value ($)"},
- )
-
- fig.update_traces(
- hovertemplate="Health Range: %{x}
Count: %{y}
Notional Value: $%{customdata[0]:,.0f}"
- )
-
- return fig
-
-
-def get_most_levered_perp_positions_above_1m(vat: Vat):
- top_positions: list[Any] = []
-
- for user in vat.users.values():
- total_collateral = user.get_total_collateral() / PRICE_PRECISION
- if total_collateral > 0:
- for position in user.get_user_account().perp_positions:
- if position.base_asset_amount > 0:
- market_price = vat.perp_oracles.get(position.market_index)
- if market_price is not None:
- market_price_ui = market_price.price / PRICE_PRECISION
- base_asset_value = (
- abs(position.base_asset_amount) / BASE_PRECISION
- ) * market_price_ui
- leverage = base_asset_value / total_collateral
- if base_asset_value > 1_000_000:
- heap_item = (
- to_financial(base_asset_value),
- user.user_public_key,
- position.market_index,
- position.base_asset_amount / BASE_PRECISION,
- leverage,
- )
-
- if len(top_positions) < 10:
- heapq.heappush(top_positions, heap_item)
- else:
- heapq.heappushpop(top_positions, heap_item)
-
- positions = sorted(
- top_positions, # We can sort directly the heap result
- key=lambda x: x[
- 4
- ], # Sort by leverage, which is the fifth element in your tuple
- )
-
- positions.reverse()
-
- data = {
- "Market Index": [pos[2] for pos in positions],
- "Value": [f"${pos[0]:,.2f}" for pos in positions],
- "Base Asset Amount": [f"{pos[3]:,.2f}" for pos in positions],
- "Leverage": [f"{pos[4]:,.2f}" for pos in positions],
- "Public Key": [pos[1] for pos in positions],
- }
-
- return data
-
-
-def get_most_levered_spot_borrows_above_1m(vat: Vat):
- top_borrows: list[Any] = []
-
- for user in vat.users.values():
- total_collateral = user.get_total_collateral() / PRICE_PRECISION
- if total_collateral > 0:
- for position in user.get_user_account().spot_positions:
- if (
- is_variant(position.balance_type, "Borrow")
- and position.scaled_balance > 0
- ):
- market_price = vat.spot_oracles.get(position.market_index)
- if market_price is not None:
- market_price_ui = market_price.price / PRICE_PRECISION
- borrow_value = (
- position.scaled_balance / SPOT_BALANCE_PRECISION
- ) * market_price_ui
- leverage = borrow_value / total_collateral
- if borrow_value > 750_000:
- heap_item = (
- to_financial(borrow_value),
- user.user_public_key,
- position.market_index,
- position.scaled_balance / SPOT_BALANCE_PRECISION,
- leverage,
- )
-
- if len(top_borrows) < 10:
- heapq.heappush(top_borrows, heap_item)
- else:
- heapq.heappushpop(top_borrows, heap_item)
-
- borrows = sorted(
- top_borrows,
- key=lambda x: x[4],
- )
-
- borrows.reverse()
-
- data = {
- "Market Index": [pos[2] for pos in borrows],
- "Value": [f"${pos[0]:,.2f}" for pos in borrows],
- "Scaled Balance": [f"{pos[3]:,.2f}" for pos in borrows],
- "Leverage": [f"{pos[4]:,.2f}" for pos in borrows],
- "Public Key": [pos[1] for pos in borrows],
- }
-
- return data
diff --git a/src/lib/page.py b/src/lib/page.py
index 6d1420a..def299a 100644
--- a/src/lib/page.py
+++ b/src/lib/page.py
@@ -3,17 +3,22 @@
"""
import asyncio
+from asyncio import AbstractEventLoop
+from datetime import datetime
import os
import time
-from asyncio import AbstractEventLoop
-import streamlit as st
from anchorpy import Wallet
from driftpy.account_subscription_config import AccountSubscriptionConfig
from driftpy.drift_client import DriftClient
+import humanize
+from lib.api import api
from solana.rpc.async_api import AsyncClient
+import streamlit as st
+
+from utils import load_newest_files
+from utils import load_vat
-from utils import load_newest_files, load_vat
RPC_STATE_KEY = "rpc_url"
NETWORK_STATE_KEY = "network"
@@ -43,6 +48,15 @@ def sidebar():
f"Have VAT? {'โ
' if st.session_state[VAT_STATE_KEY] is not None else 'Not Loaded'} "
)
+ metadata = api("metadata", "", as_json=True)
+ pickle_file = metadata["pickle_file"]
+ pickle_file = pickle_file.split("/")[-1]
+ timestamp = pickle_file.split("-")[1:]
+ timestamp = datetime.strptime(" ".join(timestamp), "%Y %m %d %H %M %S")
+ time_ago = datetime.now() - timestamp
+ time_ago_str = humanize.precisedelta(time_ago, minimum_unit="minutes")
+ st.sidebar.write(f"Last snapshot taken at: {timestamp} ({time_ago_str} ago)")
+
def needs_rpc_and_vat(page_callable: callable):
"""
diff --git a/src/lib/user_metrics.py b/src/lib/user_metrics.py
index 7d680e8..f835353 100644
--- a/src/lib/user_metrics.py
+++ b/src/lib/user_metrics.py
@@ -131,7 +131,6 @@ async def get_usermap_df(
user_map: UserMap,
mode: str,
oracle_distortion: float = 0.1,
- only_one_index: Optional[str] = None,
cov_matrix: Optional[str] = None,
n_scenarios: int = 5,
):
@@ -140,22 +139,6 @@ async def get_usermap_df(
skipped_oracles = get_skipped_oracles(cov_matrix)
- if only_one_index is None or len(only_one_index) > 12:
- only_one_index_key = only_one_index
- else:
- only_one_index_key = (
- [
- str(x.oracle)
- for x in mainnet_perp_market_configs
- if x.base_asset_symbol == only_one_index
- ]
- + [
- str(x.oracle)
- for x in mainnet_spot_market_configs
- if x.symbol == only_one_index
- ]
- )[0]
-
if mode == "margins":
leverages_none = calculate_leverages(user_vals, None)
leverages_initial = calculate_leverages(user_vals, MarginCategory.INITIAL)
@@ -185,18 +168,17 @@ async def get_usermap_df(
new_oracles_dat_down[i][key] = copy.deepcopy(val)
if cov_matrix is not None and key in skipped_oracles:
continue
- if only_one_index is None or only_one_index_key == key:
- distorted_oracles.append(key)
- for i in range(num_entrs):
- oracle_distort_up = max(1 + oracle_distortion * (i + 1), 1)
- oracle_distort_down = max(1 - oracle_distortion * (i + 1), 0)
-
- if isinstance(new_oracles_dat_up[i][key], OraclePriceData):
- new_oracles_dat_up[i][key].price *= oracle_distort_up
- new_oracles_dat_down[i][key].price *= oracle_distort_down
- else:
- new_oracles_dat_up[i][key].data.price *= oracle_distort_up
- new_oracles_dat_down[i][key].data.price *= oracle_distort_down
+ distorted_oracles.append(key)
+ for i in range(num_entrs):
+ oracle_distort_up = max(1 + oracle_distortion * (i + 1), 1)
+ oracle_distort_down = max(1 - oracle_distortion * (i + 1), 0)
+
+ if isinstance(new_oracles_dat_up[i][key], OraclePriceData):
+ new_oracles_dat_up[i][key].price *= oracle_distort_up
+ new_oracles_dat_down[i][key].price *= oracle_distort_down
+ else:
+ new_oracles_dat_up[i][key].data.price *= oracle_distort_up
+ new_oracles_dat_down[i][key].data.price *= oracle_distort_down
levs_none = calculate_leverages(user_vals, None)
levs_up = []
diff --git a/src/main.py b/src/main.py
index 5911be0..d710299 100644
--- a/src/main.py
+++ b/src/main.py
@@ -3,10 +3,10 @@
from lib.page import needs_rpc_and_vat
from lib.page import sidebar
from page.asset_liability import asset_liab_matrix_page
+from page.backend import backend_page
from page.health import health_page
from page.orderbook import orderbook_page
from page.price_shock import price_shock_page
-from page.test_backend import test_backend
from sections.liquidation_curves import plot_liquidation_curve
from sections.welcome import welcome_page
import streamlit as st
@@ -34,33 +34,33 @@
icon="๐",
),
st.Page(
- needs_rpc_and_vat(health_page),
+ health_page,
url_path="health",
title="Health",
icon="๐ฅ",
),
st.Page(
- needs_rpc_and_vat(price_shock_page),
+ price_shock_page,
url_path="price-shock",
title="Price Shock",
icon="๐ธ",
),
st.Page(
- needs_rpc_and_vat(asset_liab_matrix_page),
+ asset_liab_matrix_page,
url_path="asset-liab-matrix",
title="Asset-Liab Matrix",
icon="๐",
),
st.Page(
- needs_rpc_and_vat(plot_liquidation_curve),
+ plot_liquidation_curve,
url_path="liquidation-curves",
title="Liquidation Curves",
icon="๐",
),
st.Page(
- test_backend,
- url_path="test-backend",
- title="Test Backend",
+ backend_page,
+ url_path="backend",
+ title="Control Backend",
icon="๐งช",
),
]
diff --git a/src/sections/asset_liab_matrix.py b/src/sections/asset_liab_matrix.py
deleted file mode 100644
index 99feed1..0000000
--- a/src/sections/asset_liab_matrix.py
+++ /dev/null
@@ -1,173 +0,0 @@
-from asyncio import AbstractEventLoop
-
-from driftpy.constants.spot_markets import mainnet_spot_market_configs
-from driftpy.drift_client import DriftClient
-from driftpy.pickle.vat import Vat
-from lib.user_metrics import get_usermap_df
-import pandas as pd
-import streamlit as st
-
-
-def get_matrix(
- loop: AbstractEventLoop,
- vat: Vat,
- drift_client: DriftClient,
- env="mainnet",
- mode=0,
- perp_market_inspect=0,
-):
- NUMBER_OF_SPOT = len(mainnet_spot_market_configs)
-
- oracle_distort = 0
- if "margin" not in st.session_state:
- (levs_none, levs_init, levs_maint), user_keys = loop.run_until_complete(
- get_usermap_df(
- drift_client,
- vat.users,
- "margins",
- oracle_distort,
- None,
- "ignore stables",
- n_scenarios=0,
- all_fields=True,
- )
- )
- levs_maint = [x for x in levs_maint if int(x["health"]) <= 10]
- levs_init = [x for x in levs_init if int(x["health"]) <= 10]
- st.session_state["margin"] = (levs_none, levs_init, levs_maint), user_keys
- else:
- (levs_none, levs_init, levs_maint), user_keys = st.session_state["margin"]
-
- df: pd.DataFrame
- match mode:
- case 0: # nothing
- df = pd.DataFrame(levs_none, index=user_keys)
- case 1: # liq within 50% of oracle
- df = pd.DataFrame(levs_none, index=user_keys)
- case 2: # maint. health < 10%
- user_keys = [x["user_key"] for x in levs_init]
- df = pd.DataFrame(levs_init, index=user_keys)
- case 3: # init. health < 10%
- user_keys = [x["user_key"] for x in levs_maint]
- df = pd.DataFrame(levs_maint, index=user_keys)
-
- def get_rattt(row):
- calculations = [
- (
- "all_assets",
- lambda v: v if v > 0 else 0,
- ), # Simplified from v / row['spot_asset'] * row['spot_asset']
- (
- "all",
- lambda v: (
- v
- / row["spot_asset"]
- * (row["perp_liability"] + row["spot_liability"])
- if v > 0
- else 0
- ),
- ),
- (
- "all_perp",
- lambda v: v / row["spot_asset"] * row["perp_liability"] if v > 0 else 0,
- ),
- (
- "all_spot",
- lambda v: v / row["spot_asset"] * row["spot_liability"] if v > 0 else 0,
- ),
- (
- f"perp_{perp_market_inspect}_long",
- lambda v: (
- v / row["spot_asset"] * row["net_p"][perp_market_inspect]
- if v > 0 and row["net_p"][0] > 0
- else 0
- ),
- ),
- (
- f"perp_{perp_market_inspect}_short",
- lambda v: (
- v / row["spot_asset"] * row["net_p"][perp_market_inspect]
- if v > 0 and row["net_p"][perp_market_inspect] < 0
- else 0
- ),
- ),
- ]
-
- series_list = []
- for suffix, calc_func in calculations:
- series = pd.Series([calc_func(val) for key, val in row["net_v"].items()])
- series.index = [f"spot_{x}_{suffix}" for x in series.index]
- series_list.append(series)
-
- return pd.concat(series_list)
-
- df = pd.concat([df, df.apply(get_rattt, axis=1)], axis=1)
-
- def calculate_effective_leverage(group):
- assets = group["all_assets"]
- liabilities = group["all_liabilities"]
- return liabilities / assets if assets != 0 else 0
-
- def format_with_checkmark(value, condition, mode, financial=False):
- if financial:
- formatted_value = f"{value:,.2f}"
- else:
- formatted_value = f"{value:.2f}"
-
- if condition and mode > 0:
- return f"{formatted_value} โ
"
- return formatted_value
-
- res = pd.DataFrame(
- {
- ("spot" + str(i)): (
- df[f"spot_{i}_all_assets"].sum(),
- format_with_checkmark(
- df[f"spot_{i}_all"].sum(),
- 0 < df[f"spot_{i}_all"].sum() < 1_000_000,
- mode,
- financial=True,
- ),
- format_with_checkmark(
- calculate_effective_leverage(
- {
- "all_assets": df[f"spot_{i}_all_assets"].sum(),
- "all_liabilities": df[f"spot_{i}_all"].sum(),
- }
- ),
- 0
- < calculate_effective_leverage(
- {
- "all_assets": df[f"spot_{i}_all_assets"].sum(),
- "all_liabilities": df[f"spot_{i}_all"].sum(),
- }
- )
- < 2,
- mode,
- ),
- df[f"spot_{i}_all_spot"].sum(),
- df[f"spot_{i}_all_perp"].sum(),
- df[f"spot_{i}_perp_{perp_market_inspect}_long"].sum(),
- df[f"spot_{i}_perp_{perp_market_inspect}_short"].sum(),
- )
- for i in range(NUMBER_OF_SPOT)
- },
- index=[
- "all_assets",
- "all_liabilities",
- "effective_leverage",
- "all_spot",
- "all_perp",
- f"perp_{perp_market_inspect}_long",
- f"perp_{perp_market_inspect}_short",
- ],
- ).T
-
- res["all_liabilities"] = res["all_liabilities"].astype(str)
- res["effective_leverage"] = res["effective_leverage"].astype(str)
-
- # if env == "mainnet": # mainnet_spot_market_configs
- # res.index = [x.symbol for x in mainnet_spot_market_configs]
- # res.index.name = "spot assets" # type: ignore
-
- return res, df
diff --git a/src/sections/liquidation_curves.py b/src/sections/liquidation_curves.py
index 1bc3932..91513b9 100644
--- a/src/sections/liquidation_curves.py
+++ b/src/sections/liquidation_curves.py
@@ -1,71 +1,20 @@
-import asyncio
-from asyncio import AbstractEventLoop
from collections import defaultdict
-import os
-import time
-
-from anchorpy import Wallet
-from driftpy.account_subscription_config import AccountSubscriptionConfig
-from driftpy.constants.numeric_constants import BASE_PRECISION
-from driftpy.constants.numeric_constants import PRICE_PRECISION
-from driftpy.drift_client import DriftClient
-from driftpy.pickle.vat import Vat
-from lib.page import RPC_STATE_KEY
-from lib.page import VAT_STATE_KEY
+
+from lib.api import api
import numpy as np
-import plotly.graph_objects as go # type: ignore
-from solana.rpc.async_api import AsyncClient
+import plotly.graph_objects as go
import streamlit as st
-from utils import load_newest_files
-from utils import load_vat
-
options = [0, 1, 2]
labels = ["SOL-PERP", "BTC-PERP", "ETH-PERP"]
-def get_liquidation_curve(vat: Vat, market_index: int):
- liquidations_long: list[tuple[float, float]] = []
- liquidations_short: list[tuple[float, float]] = []
- market_price = vat.perp_oracles.get(market_index)
- market_price_ui = market_price.price / PRICE_PRECISION # type: ignore
- for user in vat.users.user_map.values():
- perp_position = user.get_perp_position(market_index)
- if perp_position is not None:
- liquidation_price = user.get_perp_liq_price(market_index)
- if liquidation_price is not None:
- liquidation_price_ui = liquidation_price / PRICE_PRECISION
- position_size = abs(perp_position.base_asset_amount) / BASE_PRECISION
- position_notional = position_size * market_price_ui
- is_zero = round(position_notional) == 0
- is_short = perp_position.base_asset_amount < 0
- is_long = perp_position.base_asset_amount > 0
- if is_zero:
- continue
- if is_short and liquidation_price_ui > market_price_ui:
- liquidations_short.append((liquidation_price_ui, position_notional))
- elif is_long and liquidation_price_ui < market_price_ui:
- liquidations_long.append((liquidation_price_ui, position_notional))
- else:
- pass
- # print(f"liquidation price for user {user.user_public_key} is {liquidation_price_ui} and market price is {market_price_ui} - is_short: {is_short} - size {position_size} - notional {position_notional}")
-
- liquidations_long.sort(key=lambda x: x[0])
- liquidations_short.sort(key=lambda x: x[0])
-
- # for (price, size) in liquidations_long:
- # print(f"Long liquidation for {size} @ {price}")
-
- # for (price, size) in liquidations_short:
- # print(f"Short liquidation for {size} @ {price}")
-
- return plot_liquidation_curves(
- liquidations_long, liquidations_short, market_price_ui
- )
-
+def plot_liquidation_curves(liquidation_data):
+ liquidations_long = liquidation_data["liquidations_long"]
+ liquidations_short = liquidation_data["liquidations_short"]
+ market_price_ui = liquidation_data["market_price_ui"]
-def plot_liquidation_curves(liquidations_long, liquidations_short, market_price_ui):
def filter_outliers(
liquidations, upper_bound_multiplier=2.0, lower_bound_multiplier=0.5
):
@@ -91,8 +40,6 @@ def prepare_data_for_plot(aggregated_data, reverse=False):
cumulative_notional = np.cumsum(
[aggregated_data[price] for price in sorted_prices]
)
- # if reverse:
- # cumulative_notional = cumulative_notional[::-1] # Reverse cumulative sum for descending plots
return sorted_prices, cumulative_notional
# Filter outliers based on defined criteria
@@ -112,11 +59,7 @@ def prepare_data_for_plot(aggregated_data, reverse=False):
)
short_prices, short_cum_notional = prepare_data_for_plot(aggregated_short)
- print(sum(long_cum_notional))
- print(sum(short_cum_notional))
-
if not long_prices or not short_prices:
- print("No data available for plotting.")
return None
# Create Plotly figures
@@ -164,20 +107,6 @@ def prepare_data_for_plot(aggregated_data, reverse=False):
def plot_liquidation_curve(): # (vat: Vat):
- rpc = st.session_state[RPC_STATE_KEY]
- loop: AbstractEventLoop = asyncio.new_event_loop()
- drift_client = DriftClient(
- AsyncClient(rpc),
- Wallet.dummy(),
- account_subscription=AccountSubscriptionConfig("cached"),
- )
- loop: AbstractEventLoop = asyncio.new_event_loop()
- newest_snapshot = load_newest_files(os.getcwd() + "/pickles")
- start_load_vat = time.time()
- vat = loop.run_until_complete(load_vat(drift_client, newest_snapshot))
- st.session_state["vat"] = vat
- st.write(f"loaded vat in {time.time() - start_load_vat}")
- st.session_state[VAT_STATE_KEY] = vat
st.write("Liquidation Curves")
market_index = st.selectbox(
@@ -189,7 +118,10 @@ def plot_liquidation_curve(): # (vat: Vat):
if market_index is None:
market_index = 0
- (long_fig, short_fig) = get_liquidation_curve(vat, market_index)
+ liquidation_data = api(
+ "liquidation", "liquidation-curve", str(market_index), as_json=True
+ )
+ (long_fig, short_fig) = plot_liquidation_curves(liquidation_data)
long_col, short_col = st.columns([1, 1])
diff --git a/src/sections/scenario.py b/src/sections/scenario.py
index c653e1d..fe288ad 100644
--- a/src/sections/scenario.py
+++ b/src/sections/scenario.py
@@ -73,7 +73,7 @@ def price_shock_page(loop: AbstractEventLoop, vat: Vat, drift_client: DriftClien
start_time = time.time()
price_scenario_users, user_keys, distorted_oracles = loop.run_until_complete(
- get_usermap_df(drift_client, vat.users, "oracles", oracle_distort, None, cov)
+ get_usermap_df(drift_client, vat.users, "oracles", oracle_distort, cov)
)
# levs[0]
end_time = time.time()