Skip to content

Commit cba92dd

Browse files
authored
Merge pull request #38 from drift-labs:goldhaxx/DATA-73/add-filter-for-each-isolated-pool-on-price-shock-page
Goldhaxx/DATA-73/add-filter-for-each-isolated-pool-on-price-shock-page
2 parents 91b6819 + 8784e9f commit cba92dd

File tree

9 files changed

+280
-17
lines changed

9 files changed

+280
-17
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ which will start a process to generate the cache files and then start the backen
4141
## Deployment
4242

4343
Pushing should automatically build the docker images and deploy to our k8s cluster.
44+
45+
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/drift-labs/driftpy)

backend/api/price_shock.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ async def _get_price_shock(
1515
oracle_distortion: float = 0.1,
1616
asset_group: str = PriceShockAssetGroup.IGNORE_STABLES.value,
1717
n_scenarios: int = 5,
18+
pool_id: int = None,
1819
) -> dict:
1920
asset_group = asset_group.replace("+", " ")
2021
price_shock_asset_group = PriceShockAssetGroup(asset_group)
@@ -26,6 +27,7 @@ async def _get_price_shock(
2627
oracle_distortion=oracle_distortion,
2728
asset_group=price_shock_asset_group,
2829
n_scenarios=n_scenarios,
30+
pool_id=pool_id,
2931
)
3032

3133

@@ -35,6 +37,7 @@ async def get_price_shock(
3537
oracle_distortion: float = 0.1,
3638
asset_group: str = PriceShockAssetGroup.IGNORE_STABLES.value,
3739
n_scenarios: int = 5,
40+
pool_id: int = None,
3841
):
3942
return await _get_price_shock(
4043
request.state.backend_state.last_oracle_slot,
@@ -43,4 +46,5 @@ async def get_price_shock(
4346
oracle_distortion,
4447
asset_group,
4548
n_scenarios,
49+
pool_id,
4650
)

backend/scripts/generate_ucache.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,33 @@ class PriceShockEndpoint(Endpoint):
5050
asset_group: PriceShockAssetGroup
5151
oracle_distortion: float
5252
n_scenarios: int
53+
pool_id: int
5354

5455
def __init__(
5556
self,
5657
asset_group: PriceShockAssetGroup,
5758
oracle_distortion: float,
5859
n_scenarios: int,
60+
pool_id: int = None,
5961
):
6062
self.asset_group = asset_group
6163
self.oracle_distortion = oracle_distortion
6264
self.n_scenarios = n_scenarios
65+
self.pool_id = pool_id
66+
67+
params = {
68+
"asset_group": asset_group,
69+
"oracle_distortion": oracle_distortion,
70+
"n_scenarios": n_scenarios,
71+
}
72+
73+
# Only add pool_id if it's not None
74+
if pool_id is not None:
75+
params["pool_id"] = pool_id
76+
6377
super().__init__(
6478
"price-shock/usermap",
65-
{
66-
"asset_group": asset_group,
67-
"oracle_distortion": oracle_distortion,
68-
"n_scenarios": n_scenarios,
69-
},
79+
params,
7080
)
7181

7282

@@ -99,6 +109,7 @@ async def mock_call_next(request):
99109
oracle_distortion=query_params["oracle_distortion"],
100110
asset_group=query_params["asset_group"],
101111
n_scenarios=query_params["n_scenarios"],
112+
pool_id=query_params.get("pool_id"),
102113
)
103114

104115
if endpoint == "asset-liability/matrix":
@@ -167,6 +178,7 @@ async def main():
167178
ps_parser.add_argument("--asset-group", type=str, required=True)
168179
ps_parser.add_argument("--oracle-distortion", type=float, required=True)
169180
ps_parser.add_argument("--n-scenarios", type=int, required=True)
181+
ps_parser.add_argument("--pool-id", type=int, help="Filter by pool ID (optional)")
170182

171183
args = parser.parse_args()
172184

@@ -191,6 +203,7 @@ async def main():
191203
asset_group=args.asset_group,
192204
oracle_distortion=args.oracle_distortion,
193205
n_scenarios=args.n_scenarios,
206+
pool_id=getattr(args, 'pool_id', None),
194207
)
195208
)
196209

@@ -203,3 +216,4 @@ async def main():
203216
# Usage example:
204217
# python -m backend.scripts.generate_ucache --use-snapshot asset-liability --mode 0 --perp-market-index 0
205218
# python -m backend.scripts.generate_ucache --use-snapshot price-shock --asset-group "ignore+stables" --oracle-distortion 0.05 --n-scenarios 5
219+
# python -m backend.scripts.generate_ucache --use-snapshot price-shock --asset-group "ignore+stables" --oracle-distortion 0.05 --n-scenarios 5 --pool-id 0

backend/utils/price_shock.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ def create_dataframes(leverages):
2121

2222

2323
def calculate_spot_bankruptcies(df):
24+
if df.empty or 'spot_asset' not in df.columns or 'spot_liability' not in df.columns or 'net_usd_value' not in df.columns:
25+
return 0.0
26+
2427
spot_bankrupt = df[
2528
(df["spot_asset"] < df["spot_liability"]) & (df["net_usd_value"] < 0)
2629
]
2730
return (spot_bankrupt["spot_liability"] - spot_bankrupt["spot_asset"]).sum()
2831

2932

3033
def calculate_total_bankruptcies(df):
34+
if df.empty or 'net_usd_value' not in df.columns:
35+
return 0.0
36+
3137
return -df[df["net_usd_value"] < 0]["net_usd_value"].sum()
3238

3339

@@ -46,6 +52,7 @@ def get_price_shock_df(
4652
oracle_distortion: float,
4753
asset_group: PriceShockAssetGroup,
4854
n_scenarios: int,
55+
pool_id: int = None,
4956
):
5057
user_leverages = get_user_leverages_for_price_shock(
5158
slot,
@@ -54,8 +61,35 @@ def get_price_shock_df(
5461
oracle_distortion,
5562
asset_group,
5663
n_scenarios,
64+
pool_id,
5765
)
5866
levs = user_leverages
67+
68+
# Handle case where no users are found after filtering
69+
if not levs["user_keys"] or len(levs["leverages_none"]) == 0:
70+
print(f"No users found for the specified filters. Returning empty result.")
71+
oracle_moves = generate_oracle_moves(n_scenarios, oracle_distortion)
72+
73+
# Create empty DataFrame with all zeros
74+
df_plot = pd.DataFrame(
75+
{
76+
"Oracle Move (%)": oracle_moves,
77+
"Total Bankruptcy ($)": [0.0] * len(oracle_moves),
78+
"Spot Bankruptcy ($)": [0.0] * len(oracle_moves),
79+
"Perpetual Bankruptcy ($)": [0.0] * len(oracle_moves),
80+
}
81+
)
82+
83+
df_plot = df_plot.sort_values("Oracle Move (%)")
84+
85+
return {
86+
"slot": slot,
87+
"result": df_plot.to_json(),
88+
"distorted_oracles": levs["distorted_oracles"],
89+
"oracle_down_max": pd.DataFrame().to_json(),
90+
"oracle_up_max": pd.DataFrame().to_json(),
91+
}
92+
5993
dfs = (
6094
create_dataframes(levs["leverages_down"])
6195
+ [pd.DataFrame(levs["leverages_none"])]

backend/utils/user_metrics.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,39 @@ def get_user_leverages_for_price_shock(
260260
oracle_distortion: float = 0.1,
261261
asset_group: PriceShockAssetGroup = PriceShockAssetGroup.IGNORE_STABLES,
262262
scenarios: int = 5,
263+
pool_id: int = None,
263264
):
264265
user_keys = list(user_map.user_map.keys())
265266
user_vals = list(user_map.values())
267+
268+
# Filter users by pool_id if specified
269+
if pool_id is not None:
270+
filtered_user_vals = []
271+
filtered_user_keys = []
272+
pool_id_counts = {} # Track distribution of pool_ids
273+
274+
for user_key, user in zip(user_keys, user_vals):
275+
try:
276+
user_account = user.get_user_account()
277+
actual_pool_id = user_account.pool_id
278+
279+
# Track pool_id distribution for debugging
280+
pool_id_counts[actual_pool_id] = pool_id_counts.get(actual_pool_id, 0) + 1
281+
282+
if actual_pool_id == pool_id:
283+
filtered_user_vals.append(user)
284+
filtered_user_keys.append(user_key)
285+
except Exception as e:
286+
print(f"Error checking pool_id for user {user_key}: {e}")
287+
continue
288+
289+
print(f"Pool ID distribution: {dict(sorted(pool_id_counts.items()))}")
290+
print(f"Requested pool_id: {pool_id}")
291+
print(f"Filtered to {len(filtered_user_vals)} users with pool_id {pool_id} (out of {len(user_vals)} total users)")
292+
293+
user_vals = filtered_user_vals
294+
user_keys = filtered_user_keys
295+
266296
all_configs = mainnet_spot_market_configs + mainnet_perp_market_configs
267297

268298
print(f"User keys : {len(user_keys)}")

gen.sh

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,184 @@
11
#!/bin/bash
22
set -e
33

4-
54
# Run the first one sync, this will generate a fresh pickle
65
python -m backend.scripts.generate_ucache \
76
asset-liability \
87
--mode 0 \
98
--perp-market-index 0
109

11-
1210
# The next ones will use the --use-snapshot flag, so they will reuse the pickle
1311
# We can run all commands in parallel by adding & at the end
12+
13+
echo "Generating comprehensive price shock cache matrix..."
14+
echo "Asset groups: ignore+stables, jlp+only"
15+
echo "Scenarios: 5 (0.05 distortion), 10 (0.1 distortion)"
16+
echo "Pool IDs: all, 0, 1, 3"
17+
echo "Total combinations: 16"
18+
19+
# =============================================================================
20+
# ALL POOLS (no pool filter) - 4 combinations
21+
# =============================================================================
22+
23+
# ignore+stables, 5 scenarios, 0.05 distortion, all pools
1424
python -m backend.scripts.generate_ucache \
1525
--use-snapshot \
1626
price-shock \
1727
--asset-group "ignore+stables" \
1828
--oracle-distortion 0.05 \
1929
--n-scenarios 5 &
2030

31+
# ignore+stables, 10 scenarios, 0.1 distortion, all pools
32+
python -m backend.scripts.generate_ucache \
33+
--use-snapshot \
34+
price-shock \
35+
--asset-group "ignore+stables" \
36+
--oracle-distortion 0.1 \
37+
--n-scenarios 10 &
38+
39+
# jlp+only, 5 scenarios, 0.05 distortion, all pools
2140
python -m backend.scripts.generate_ucache \
2241
--use-snapshot \
2342
price-shock \
2443
--asset-group "jlp+only" \
2544
--oracle-distortion 0.05 \
2645
--n-scenarios 5 &
2746

47+
# jlp+only, 10 scenarios, 0.1 distortion, all pools
2848
python -m backend.scripts.generate_ucache \
2949
--use-snapshot \
3050
price-shock \
3151
--asset-group "jlp+only" \
3252
--oracle-distortion 0.1 \
3353
--n-scenarios 10 &
3454

55+
# =============================================================================
56+
# MAIN POOL (pool_id = 0) - 4 combinations
57+
# =============================================================================
58+
59+
# ignore+stables, 5 scenarios, 0.05 distortion, pool 0
60+
python -m backend.scripts.generate_ucache \
61+
--use-snapshot \
62+
price-shock \
63+
--asset-group "ignore+stables" \
64+
--oracle-distortion 0.05 \
65+
--n-scenarios 5 \
66+
--pool-id 0 &
3567

68+
# ignore+stables, 10 scenarios, 0.1 distortion, pool 0
3669
python -m backend.scripts.generate_ucache \
3770
--use-snapshot \
3871
price-shock \
3972
--asset-group "ignore+stables" \
4073
--oracle-distortion 0.1 \
41-
--n-scenarios 10 &
74+
--n-scenarios 10 \
75+
--pool-id 0 &
76+
77+
# jlp+only, 5 scenarios, 0.05 distortion, pool 0
78+
python -m backend.scripts.generate_ucache \
79+
--use-snapshot \
80+
price-shock \
81+
--asset-group "jlp+only" \
82+
--oracle-distortion 0.05 \
83+
--n-scenarios 5 \
84+
--pool-id 0 &
85+
86+
# jlp+only, 10 scenarios, 0.1 distortion, pool 0
87+
python -m backend.scripts.generate_ucache \
88+
--use-snapshot \
89+
price-shock \
90+
--asset-group "jlp+only" \
91+
--oracle-distortion 0.1 \
92+
--n-scenarios 10 \
93+
--pool-id 0 &
94+
95+
# =============================================================================
96+
# ISOLATED POOL 1 (pool_id = 1) - 4 combinations
97+
# =============================================================================
98+
99+
# ignore+stables, 5 scenarios, 0.05 distortion, pool 1
100+
python -m backend.scripts.generate_ucache \
101+
--use-snapshot \
102+
price-shock \
103+
--asset-group "ignore+stables" \
104+
--oracle-distortion 0.05 \
105+
--n-scenarios 5 \
106+
--pool-id 1 &
107+
108+
# ignore+stables, 10 scenarios, 0.1 distortion, pool 1
109+
python -m backend.scripts.generate_ucache \
110+
--use-snapshot \
111+
price-shock \
112+
--asset-group "ignore+stables" \
113+
--oracle-distortion 0.1 \
114+
--n-scenarios 10 \
115+
--pool-id 1 &
42116

117+
# jlp+only, 5 scenarios, 0.05 distortion, pool 1
118+
python -m backend.scripts.generate_ucache \
119+
--use-snapshot \
120+
price-shock \
121+
--asset-group "jlp+only" \
122+
--oracle-distortion 0.05 \
123+
--n-scenarios 5 \
124+
--pool-id 1 &
125+
126+
# jlp+only, 10 scenarios, 0.1 distortion, pool 1
127+
python -m backend.scripts.generate_ucache \
128+
--use-snapshot \
129+
price-shock \
130+
--asset-group "jlp+only" \
131+
--oracle-distortion 0.1 \
132+
--n-scenarios 10 \
133+
--pool-id 1 &
134+
135+
# =============================================================================
136+
# ISOLATED POOL 3 (pool_id = 3) - 4 combinations
137+
# =============================================================================
138+
139+
# ignore+stables, 5 scenarios, 0.05 distortion, pool 3
140+
python -m backend.scripts.generate_ucache \
141+
--use-snapshot \
142+
price-shock \
143+
--asset-group "ignore+stables" \
144+
--oracle-distortion 0.05 \
145+
--n-scenarios 5 \
146+
--pool-id 3 &
147+
148+
# ignore+stables, 10 scenarios, 0.1 distortion, pool 3
149+
python -m backend.scripts.generate_ucache \
150+
--use-snapshot \
151+
price-shock \
152+
--asset-group "ignore+stables" \
153+
--oracle-distortion 0.1 \
154+
--n-scenarios 10 \
155+
--pool-id 3 &
156+
157+
# jlp+only, 5 scenarios, 0.05 distortion, pool 3
158+
python -m backend.scripts.generate_ucache \
159+
--use-snapshot \
160+
price-shock \
161+
--asset-group "jlp+only" \
162+
--oracle-distortion 0.05 \
163+
--n-scenarios 5 \
164+
--pool-id 3 &
165+
166+
# jlp+only, 10 scenarios, 0.1 distortion, pool 3
167+
python -m backend.scripts.generate_ucache \
168+
--use-snapshot \
169+
price-shock \
170+
--asset-group "jlp+only" \
171+
--oracle-distortion 0.1 \
172+
--n-scenarios 10 \
173+
--pool-id 3 &
174+
175+
# =============================================================================
43176
# Wait for all background processes to complete
177+
# =============================================================================
178+
echo "Waiting for all 16 price shock cache generation processes to complete..."
44179
wait
45180

181+
echo "✅ All cache generation completed successfully!"
182+
46183
# Delete old pickles
47184
cd pickles && ls -t | tail -n +4 | xargs rm -rf

0 commit comments

Comments
 (0)