Skip to content

Commit 061075b

Browse files
committed
Enhance user retention explorer API and page with new volume metrics
- Added new fields to the `RetentionExplorerItem` model in `user_retention_explorer_api.py` to track total initial selected and other market volumes over 7 days, as well as total volumes over 14 and 28 days. - Updated the `calculate_retention_for_market` function to compute and return these new volume metrics, ensuring they are included in the response. - Enhanced the user retention explorer page to display the new high-level volume metrics, providing users with better insights into market performance. These changes improve the analytical capabilities of the user retention explorer, allowing for a more comprehensive understanding of trader behavior and market dynamics.
1 parent fba1ace commit 061075b

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

backend/api/user_retention_explorer_api.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ class RetentionExplorerItem(BaseModel):
8484
retention_ratio_14d: float
8585
retention_ratio_28d: float
8686
user_data: List[UserVolumeDetails]
87+
total_initial_selected_market_volume_7d: float
88+
total_initial_other_market_volume_7d: float
89+
total_volume_14d: float
90+
total_volume_28d: float
8791

8892
UTC = tz.tzutc()
8993

@@ -219,7 +223,11 @@ async def calculate_retention_for_market(market_name: str, start_date_str: str)
219223
return {
220224
"market": market_name, "category": market_config.get("category", []), "start_date": start_date_str,
221225
"new_traders_count": 0, "retained_14d_count": 0, "retained_28d_count": 0,
222-
"retention_ratio_14d": 0.0, "retention_ratio_28d": 0.0, "user_data": []
226+
"retention_ratio_14d": 0.0, "retention_ratio_28d": 0.0, "user_data": [],
227+
"total_initial_selected_market_volume_7d": 0.0,
228+
"total_initial_other_market_volume_7d": 0.0,
229+
"total_volume_14d": 0.0,
230+
"total_volume_28d": 0.0,
223231
}
224232

225233
# --- Volume Calculation ---
@@ -240,6 +248,9 @@ def get_and_merge_volume(
240248

241249
vol_df = pd.read_sql(vol_sql, conn)
242250
merged_df = base_df.merge(vol_df, on='user', how='left')
251+
252+
# Explicitly convert to numeric to avoid FutureWarning on downcasting
253+
merged_df['total_volume'] = pd.to_numeric(merged_df['total_volume'], errors='coerce')
243254
merged_df['total_volume'] = merged_df['total_volume'].fillna(0)
244255
return merged_df.rename(columns={'total_volume': column_name})
245256

@@ -253,6 +264,12 @@ def get_and_merge_volume(
253264

254265
traders_df = traders_df.rename(columns={'user': 'user_address'})
255266

267+
# --- Summary Volume Metrics ---
268+
total_initial_selected_market_volume_7d = traders_df['initial_selected_market_volume'].sum()
269+
total_initial_other_market_volume_7d = traders_df['initial_other_market_volume'].sum()
270+
total_volume_14d = (traders_df['selected_market_volume_14d'] + traders_df['other_market_volume_14d']).sum()
271+
total_volume_28d = (traders_df['selected_market_volume_28d'] + traders_df['other_market_volume_28d']).sum()
272+
256273
# --- Summary Statistics ---
257274
retained_14d_count = int((traders_df['other_market_volume_14d'] > 0).sum())
258275
retained_28d_count = int((traders_df['other_market_volume_28d'] > 0).sum())
@@ -268,7 +285,11 @@ def get_and_merge_volume(
268285
"retained_28d_count": retained_28d_count,
269286
"retention_ratio_14d": round(retention_ratio_14d, 4),
270287
"retention_ratio_28d": round(retention_ratio_28d, 4),
271-
"user_data": traders_df.to_dict('records')
288+
"user_data": traders_df.to_dict('records'),
289+
"total_initial_selected_market_volume_7d": float(total_initial_selected_market_volume_7d),
290+
"total_initial_other_market_volume_7d": float(total_initial_other_market_volume_7d),
291+
"total_volume_14d": float(total_volume_14d),
292+
"total_volume_28d": float(total_volume_28d),
272293
}
273294

274295
logger.info(f"Successfully calculated consolidated retention for {market_name}.")

src/page/user_retention_explorer_page.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,31 @@ def user_retention_explorer_page():
121121
elif isinstance(result, dict) and "user_data" in result:
122122
st.header("Analysis Results")
123123

124+
# --- Display Summary Metrics ---
125+
st.subheader("High-Level Volume Metrics")
126+
metric_cols = st.columns(4)
127+
metric_cols[0].metric(
128+
"ISMV7d",
129+
f"${result.get('total_initial_selected_market_volume_7d', 0):,.0f}",
130+
help="Initial Selected Market Volume (7d): Total volume in the selected market from new traders during their first 7 days."
131+
)
132+
metric_cols[1].metric(
133+
"IOMV7d",
134+
f"${result.get('total_initial_other_market_volume_7d', 0):,.0f}",
135+
help="Initial Other Market Volume (7d): Total volume in all other markets from new traders during their first 7 days."
136+
)
137+
metric_cols[2].metric(
138+
"TV14d",
139+
f"${result.get('total_volume_14d', 0):,.0f}",
140+
help="Total Volume (14d): Total volume from the cohort during the 14-day retention period (Days 8-21)."
141+
)
142+
metric_cols[3].metric(
143+
"TV28d",
144+
f"${result.get('total_volume_28d', 0):,.0f}",
145+
help="Total Volume (28d): Total volume from the cohort during the 28-day retention period (Days 8-35)."
146+
)
147+
148+
st.subheader("Retention Summary")
124149
df_data = {
125150
'Metric': [
126151
"Market", "Category", "Analysis Start Date", "New Traders (Count)",

0 commit comments

Comments
 (0)