myco-bonding-curve/dashboard/tabs/stress_tests.py

54 lines
1.8 KiB
Python

"""Stress Tests tab — bank run sweep."""
import streamlit as st
from src.composed.simulator import scenario_bank_run
from dashboard.charts import fig_bank_run_sweep
def render():
st.header("Stress Tests")
col1, col2 = st.columns(2)
with col1:
fractions_str = st.text_input(
"Redemption fractions (comma-separated)",
"0.02, 0.05, 0.10, 0.20",
)
with col2:
initial_reserve = st.number_input(
"Initial reserve ($)", 10_000, 1_000_000, 100_000, step=10_000,
)
if st.button("Run Stress Test", key="stress_run"):
fractions = [float(f.strip()) for f in fractions_str.split(",")]
results = {}
progress = st.progress(0)
for i, frac in enumerate(fractions):
with st.spinner(f"Running {frac:.0%} redemption..."):
results[frac] = scenario_bank_run(
initial_reserve=float(initial_reserve),
redemption_fraction=frac,
)
progress.progress((i + 1) / len(fractions))
st.session_state["stress_results"] = results
if "stress_results" in st.session_state:
results = st.session_state["stress_results"]
# Summary table
cols = st.columns(len(results))
for i, (frac, result) in enumerate(results.items()):
final_ratio = result.backing_ratio[-1]
with cols[i]:
st.metric(
f"{frac:.0%} Redemption",
f"Backing: {final_ratio:.4f}",
delta="Survived" if final_ratio > 0.5 else "Failed",
delta_color="normal" if final_ratio > 0.5 else "inverse",
)
st.plotly_chart(fig_bank_run_sweep(results), use_container_width=True)