61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
|
|
"""
|
||
|
|
Optional Streamlit dashboard for FQBM (Sheet 8 + workbook).
|
||
|
|
|
||
|
|
Run: streamlit run scripts/streamlit_dashboard.py
|
||
|
|
Requires: pip install streamlit
|
||
|
|
"""
|
||
|
|
|
||
|
|
import streamlit as st
|
||
|
|
from fqbm.state import FQBMState
|
||
|
|
from fqbm.workbook.runner import run_workbook
|
||
|
|
from fqbm.scenarios import list_scenarios, get_scenario
|
||
|
|
|
||
|
|
st.set_page_config(page_title="FQBM Dashboard", layout="wide")
|
||
|
|
st.title("Four-Quadrant Balance Sheet Matrix — Dashboard")
|
||
|
|
|
||
|
|
scenario_names = ["(custom)"] + list_scenarios()
|
||
|
|
scenario = st.sidebar.selectbox("Scenario (Part XI)", scenario_names)
|
||
|
|
mc_runs = st.sidebar.slider("Monte Carlo runs", 0, 500, 100)
|
||
|
|
run_btn = st.sidebar.button("Run workbook")
|
||
|
|
if run_btn:
|
||
|
|
with st.spinner("Running workbook..."):
|
||
|
|
if scenario == "(custom)":
|
||
|
|
state = FQBMState(R=200, Deposits=1000, Loans=900, E_b=100)
|
||
|
|
st.session_state["result"] = run_workbook(initial_state=state, mc_runs=mc_runs)
|
||
|
|
else:
|
||
|
|
st.session_state["result"] = run_workbook(scenario=scenario, mc_runs=mc_runs)
|
||
|
|
st.session_state["scenario_used"] = scenario
|
||
|
|
|
||
|
|
result = st.session_state.get("result")
|
||
|
|
if not result:
|
||
|
|
st.info("Select a scenario and click **Run workbook** in the sidebar to run the full FQBM workbook.")
|
||
|
|
st.stop()
|
||
|
|
|
||
|
|
state = result["state"]
|
||
|
|
dashboard = result["dashboard"]
|
||
|
|
|
||
|
|
st.subheader("State snapshot")
|
||
|
|
cols = st.columns(4)
|
||
|
|
names = ["B", "R", "C", "Loans", "Deposits", "E_cb", "E_b", "S", "K", "Spread", "O"]
|
||
|
|
vals = state.to_vector()
|
||
|
|
for i, (n, v) in enumerate(zip(names, vals)):
|
||
|
|
cols[i % 4].metric(n, f"{v:,.1f}")
|
||
|
|
|
||
|
|
st.subheader("Key ratios")
|
||
|
|
ratios = dashboard.get("ratios", {})
|
||
|
|
for k, v in ratios.items():
|
||
|
|
st.write(f"**{k}**: {v:.4f}")
|
||
|
|
|
||
|
|
st.subheader("Stress tables")
|
||
|
|
stress = result["stress"]
|
||
|
|
st.dataframe(stress["liquidity_stress"], use_container_width=True)
|
||
|
|
st.dataframe(stress["capital_stress"], use_container_width=True)
|
||
|
|
|
||
|
|
if dashboard.get("mc_summary"):
|
||
|
|
st.subheader("Monte Carlo summary")
|
||
|
|
ms = dashboard["mc_summary"]
|
||
|
|
st.write(f"P(insolvency): {ms.get('p_insolvency', 0):.2%}")
|
||
|
|
st.write(f"P(reserve breach): {ms.get('p_reserve_breach', 0):.2%}")
|
||
|
|
st.write(f"Inflation (mean ± std): {ms.get('inflation_mean', 0):.4f} ± {ms.get('inflation_std', 0):.4f}")
|
||
|
|
st.write(f"P(debt unsustainable): {ms.get('p_debt_unsustainable', 0):.2%}")
|