marcelolabre commited on
Commit
0afdb9d
·
verified ·
1 Parent(s): ce49d84

Uploading app files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/signalpha-banner.png filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # Set up the strict non-root user Hugging Face requires
4
+ RUN useradd -m -u 1000 user
5
+ USER user
6
+ ENV PATH="/home/user/.local/bin:$PATH"
7
+
8
+ WORKDIR /app
9
+
10
+ # Copy requirements and install
11
+ COPY --chown=user requirements.txt .
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ # Copy the rest of your app
15
+ COPY --chown=user . .
16
+
17
+ # Run Gunicorn on port 7860
18
+ CMD ["gunicorn", "app:server", "--bind", "0.0.0.0:7860"]
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: gunicorn app:server
README.md CHANGED
@@ -1,12 +1,52 @@
1
  ---
2
- title: Default Cascade Simulation 2026
3
- emoji: 💻
4
- colorFrom: purple
5
- colorTo: pink
6
  sdk: docker
7
- pinned: false
8
  license: mit
9
  short_description: 'Signalpha: Default Cascade Simulation'
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Signalpha Default Cascade Simulation 2026
3
+ emoji: 🏦
4
+ colorFrom: red
5
+ colorTo: purple
6
  sdk: docker
7
+ app_port: 7860
8
  license: mit
9
  short_description: 'Signalpha: Default Cascade Simulation'
10
  ---
11
 
12
+ # Default Cascade Simulation of Banks 2026
13
+
14
+ Interactive simulation modeling how commercial real estate (CRE) defaults cascade through U.S. bank balance sheets, with optional unrealized securities losses. Built for the [Signalpha](https://signalpha.substack.com) Substack publication.
15
+
16
+ ## What it does
17
+
18
+ Uses Q3 2025 FFIEC Call Report data for 147 U.S. banks (over $10 billion in assets, $20.2 trillion in combined assets) to simulate the impact of CRE losses on bank capitalization. Displays two horizontal stacked bar charts:
19
+
20
+ 1. **Tangible Equity Ratio** — Banks categorized by Prompt Corrective Action (PCA) thresholds: Well Capitalized (>=8%), Adequately Capitalized (>=4%), Undercapitalized (>=2%), Critically Undercapitalized (>=0%), Insolvent (<0%)
21
+ 2. **Estimated CET1 Ratio** — Banks categorized by Basel III thresholds: Well Capitalized (>=6.5%), Undercapitalized (>=4.5%), Below Basel III Minimum (>=0%), Insolvent (<0%)
22
+
23
+ Losses are calculated as: `CRE Losses = CRE Total x Default Rate x LGD`. When unrealized losses are toggled on, they are added to CRE losses before adjusting equity.
24
+
25
+ ## Controls
26
+
27
+ - **CRE Default Rate** (0-50%): Percentage of CRE portfolio that defaults
28
+ - **Loss Given Default** (0-100%): Recovery shortfall on defaulted loans
29
+ - **Average RWA Ratio** (50-75%): Risk-weighted assets as percentage of total assets (for CET1 calculation)
30
+ - **Unrealized Losses**: Toggle to include unrealized losses on investment securities
31
+
32
+ ## Features
33
+
34
+ - Download figure as PNG (via html2canvas)
35
+ - Download underlying data as CSV
36
+ - In-app documentation panel
37
+
38
+ ## Run locally
39
+
40
+ ```bash
41
+ pip install -r requirements.txt
42
+ python app.py
43
+ # Open http://localhost:8050
44
+ ```
45
+
46
+ ## Deploy to Hugging Face Spaces
47
+
48
+ Uses Docker SDK. See `Dockerfile` for build configuration.
49
+
50
+ ## Data source
51
+
52
+ [The Banking Initiative at Florida Atlantic University](https://business.fau.edu/departments/finance/banking-initiative/), based on Dr. Rebel Cole's analysis of Bank Call Report data for Q3 2025 from the U.S. Federal Financial Institutions Examination Council.
__pycache__/app.cpython-314.pyc ADDED
Binary file (27.9 kB). View file
 
app.py ADDED
@@ -0,0 +1,804 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CRE Default Cascade Simulation
3
+ Interactive visualization of how CRE defaults affect U.S. bank capitalization.
4
+
5
+ Run locally:
6
+ pip install dash plotly pandas
7
+ python app.py
8
+ Open http://localhost:8050
9
+
10
+ Deploy to Hugging Face Spaces:
11
+ Uses Docker SDK — see Dockerfile and README.md
12
+ """
13
+
14
+ import io
15
+ import os
16
+ import pandas as pd
17
+ import dash
18
+ from dash import dcc, html, Input, Output, State, callback, clientside_callback
19
+ import plotly.graph_objects as go
20
+
21
+ # ── App init ──────────────────────────────────────────────────────────────────
22
+ app = dash.Dash(__name__, title="Default Cascade Simulation of Banks 2026 — Signalpha")
23
+ server = app.server
24
+
25
+ # ── Load data ─────────────────────────────────────────────────────────────────
26
+ DATA_PATH = os.path.join(os.path.dirname(__file__), "data.csv")
27
+ df = pd.read_csv(DATA_PATH)
28
+
29
+ # Clean numeric columns
30
+ for col in ["Total Assets ($M)", "Total Equity ($M)", "CRE Total ($M)", "CET1 Capital ($M)", "Total Unrealized Loss ($M)"]:
31
+ df[col] = pd.to_numeric(df[col].astype(str).str.replace(",", ""), errors="coerce")
32
+ df["Total Unrealized Loss ($M)"] = df["Total Unrealized Loss ($M)"].fillna(0)
33
+ df["_has_ticker"] = df["Ticker"].notna() & (df["Ticker"].astype(str).str.strip() != "")
34
+
35
+ N_BANKS = len(df)
36
+
37
+ # ── Colour palette (light theme) ─────────────────────────────────────────────
38
+ CLR_BG = "#F3F4F6"
39
+ CLR_CARD_BG = "#FFFFFF"
40
+ CLR_TEXT = "#111827"
41
+ CLR_MUTED = "#6B7280"
42
+ CLR_BORDER = "rgba(0,0,0,0.10)"
43
+ CLR_LINK = "#2563EB"
44
+
45
+ # Red shades for PCA (Viz 1) — lightest to darkest
46
+ RED_WELL_CAP = "#FDCECE"
47
+ RED_ADEQ_CAP = "#F87171"
48
+ RED_UNDERCAP = "#DC2626"
49
+ RED_CRIT_UNDCAP = "#991B1B"
50
+ RED_INSOLVENT = "#450A0A"
51
+
52
+ # Bar dimensions (explicit width keeps thickness stable across renders)
53
+ BAR_WIDTH = 1.0 # fraction of y-axis category width
54
+ BAR_HEIGHT = 48 # px — total chart height
55
+
56
+ # Purple shades for CET1 (Viz 2) — lightest to darkest
57
+ PUR_WELL_CAP = "#E9D5FF"
58
+ PUR_UNDERCAP = "#A855F7"
59
+ PUR_BELOW_MIN = "#7E22CE"
60
+ PUR_INSOLVENT = "#3B0764"
61
+
62
+ # ── Helpers ───────────────────────────────────────────────────────────────────
63
+ def classify_pca(equity_to_assets):
64
+ """Classify banks by Prompt Corrective Action category based on equity-to-assets ratio."""
65
+ well = adequately = under = critical = insolvent = 0
66
+ for ratio in equity_to_assets:
67
+ if ratio >= 0.08:
68
+ well += 1
69
+ elif ratio >= 0.04:
70
+ adequately += 1
71
+ elif ratio >= 0.02:
72
+ under += 1
73
+ elif ratio >= 0:
74
+ critical += 1
75
+ else:
76
+ insolvent += 1
77
+ return well, adequately, under, critical, insolvent
78
+
79
+
80
+ def classify_cet1(cet1_ratios):
81
+ """Classify banks by Basel III CET1 thresholds."""
82
+ well = under = below = insolvent = 0
83
+ for ratio in cet1_ratios:
84
+ if ratio >= 0.065:
85
+ well += 1
86
+ elif ratio >= 0.045:
87
+ under += 1
88
+ elif ratio >= 0:
89
+ below += 1
90
+ else:
91
+ insolvent += 1
92
+ return well, under, below, insolvent
93
+
94
+
95
+ def compute_scenario(default_rate, lgd, rwa_ratio, include_unrealized=False, data=None):
96
+ """Compute adjusted ratios for all banks given scenario parameters."""
97
+ d = data if data is not None else df
98
+ cre = d["CRE Total ($M)"].values
99
+ equity = d["Total Equity ($M)"].values
100
+ assets = d["Total Assets ($M)"].values
101
+ cet1 = d["CET1 Capital ($M)"].values
102
+ unrealized = d["Total Unrealized Loss ($M)"].values if include_unrealized else 0
103
+
104
+ cre_losses = cre * default_rate * lgd
105
+
106
+ adj_equity_to_assets = (equity - cre_losses - unrealized) / assets
107
+
108
+ estimated_rwa = assets * rwa_ratio
109
+ adj_cet1_ratio = (cet1 - cre_losses - unrealized) / estimated_rwa
110
+
111
+ total_cre_losses = cre_losses.sum()
112
+
113
+ # PCA-based metrics (use adjusted ratios so masks match classify_pca)
114
+ insolvent_mask_pca = adj_equity_to_assets < 0
115
+ insolvent_assets_pca = assets[insolvent_mask_pca].sum()
116
+ undercap_mask_pca = adj_equity_to_assets < 0.04
117
+ undercap_assets_pca = assets[undercap_mask_pca].sum()
118
+
119
+ # CET1-based metrics (use adjusted ratios so masks match classify_cet1)
120
+ # Insolvent: ratio < 0
121
+ insolvent_mask_cet1 = adj_cet1_ratio < 0
122
+ insolvent_assets_cet1 = assets[insolvent_mask_cet1].sum()
123
+ # Below Basel III Minimum: ratio < 4.5% (matches c_below + c_insolvent)
124
+ undercap_mask_cet1 = adj_cet1_ratio < 0.045
125
+ undercap_assets_cet1 = assets[undercap_mask_cet1].sum()
126
+
127
+ return (adj_equity_to_assets, adj_cet1_ratio, total_cre_losses,
128
+ insolvent_assets_pca, undercap_assets_pca,
129
+ insolvent_assets_cet1, undercap_assets_cet1)
130
+
131
+
132
+ # ── Slider factory ────────────────────────────────────────────────────────────
133
+ def make_slider(slider_id, label, min_, max_, step, value, suffix="%"):
134
+ return html.Div([
135
+ html.Div([
136
+ html.Label(label, style={
137
+ "fontSize": "13px", "color": CLR_MUTED,
138
+ "minWidth": "155px", "marginRight": "12px",
139
+ "fontWeight": "500",
140
+ }),
141
+ dcc.Slider(
142
+ id=slider_id, min=min_, max=max_, step=step, value=value,
143
+ marks=None, tooltip={"always_visible": False},
144
+ className="cre-slider",
145
+ ),
146
+ html.Span(id=f"{slider_id}-out", style={
147
+ "fontSize": "14px", "fontWeight": "600",
148
+ "minWidth": "70px", "textAlign": "right",
149
+ "color": CLR_TEXT,
150
+ }),
151
+ ], style={"display": "flex", "alignItems": "center", "gap": "12px"}),
152
+ ], style={"marginBottom": "14px"})
153
+
154
+
155
+ # ── Metric card ───────────────────────────────────────────────────────────────
156
+ def metric_card(card_id, label, sub_id=None):
157
+ children = [
158
+ html.Div(label, style={"fontSize": "11px", "color": CLR_MUTED, "marginBottom": "4px", "textTransform": "uppercase", "letterSpacing": "0.5px"}),
159
+ html.Div(id=card_id, style={"fontSize": "20px", "fontWeight": "600", "color": CLR_TEXT}),
160
+ ]
161
+ if sub_id:
162
+ children.append(html.Div(id=sub_id, style={"fontSize": "11px", "color": CLR_MUTED, "marginTop": "2px"}))
163
+ return html.Div(children, style={
164
+ "background": CLR_CARD_BG,
165
+ "borderRadius": "8px",
166
+ "padding": "14px 16px",
167
+ "flex": "1",
168
+ "minWidth": "140px",
169
+ "border": f"1px solid {CLR_BORDER}",
170
+ })
171
+
172
+
173
+ def fmt_assets(value):
174
+ """Format asset values in $B or $T."""
175
+ if value > 1e6:
176
+ return f"${value / 1e6:.2f}T in assets"
177
+ return f"${value / 1000:.1f}B in assets"
178
+
179
+
180
+ # ── Layout ────────────────────────────────────────────────────────────────────
181
+ app.layout = html.Div([
182
+
183
+ # Capturable content area with clear boundary
184
+ html.Div([
185
+
186
+ # Header + Banner
187
+ html.Div([
188
+ html.Div([
189
+ html.H1("Default Cascade Simulation of Banks 2026", style={
190
+ "fontSize": "24px", "fontWeight": "600",
191
+ "margin": "0 0 6px", "color": CLR_TEXT,
192
+ }),
193
+ html.P(
194
+ f"Impact of CRE defaults and unrealized losses on {N_BANKS} U.S. largest banks (more than $10 billion in assets)",
195
+ style={"fontSize": "14px", "color": CLR_MUTED, "margin": "0 0 4px"},
196
+ ),
197
+ html.P([
198
+ "Source: ",
199
+ html.A("Signalpha", href="https://signalpha.substack.com/", target="_blank",
200
+ style={"color": CLR_LINK, "textDecoration": "none"}),
201
+ ], style={"fontSize": "12px", "margin": "0 0 2px", "color": CLR_MUTED}),
202
+ html.P([
203
+ "Data: ",
204
+ html.A("The Banking Initiative at Florida Atlantic University",
205
+ href="https://business.fau.edu/departments/finance/banking-initiative/",
206
+ target="_blank",
207
+ style={"color": CLR_LINK, "textDecoration": "none"}),
208
+ ], style={"fontSize": "12px", "margin": 0, "color": CLR_MUTED}),
209
+ ], style={"flex": "1"}),
210
+ html.Img(src="/assets/signalpha-banner.png", style={
211
+ "height": "80px", "borderRadius": "6px", "alignSelf": "center",
212
+ }),
213
+ ], style={"display": "flex", "alignItems": "flex-start", "gap": "20px", "marginBottom": "28px"}),
214
+
215
+ # Controls
216
+ html.Div([
217
+ html.Div("Scenario Parameters", style={
218
+ "fontSize": "13px", "fontWeight": "600", "color": CLR_TEXT,
219
+ "marginBottom": "14px", "textTransform": "uppercase", "letterSpacing": "0.5px",
220
+ }),
221
+ make_slider("default-rate", "CRE Default Rate", 0, 50, 0.5, 10, "%"),
222
+ make_slider("lgd", "Loss Given Default", 0, 100, 1, 50, "%"),
223
+ make_slider("rwa-ratio", "Average RWA Ratio", 50, 75, 0.5, 65, "%"),
224
+ make_slider("min-assets", "Total Assets", 10, 100, 1, 10, "$B"),
225
+ # Unrealized losses toggle
226
+ html.Div([
227
+ html.Label("Unrealized Losses", style={
228
+ "fontSize": "13px", "color": CLR_MUTED,
229
+ "minWidth": "155px", "marginRight": "12px",
230
+ "fontWeight": "500",
231
+ }),
232
+ dcc.Checklist(
233
+ id="unrealized-toggle",
234
+ options=[{"label": " Include Total Unrealized Losses on Investment Securities", "value": "on"}],
235
+ value=[],
236
+ style={"fontSize": "13px", "color": CLR_TEXT},
237
+ inputStyle={"marginRight": "6px"},
238
+ ),
239
+ ], style={"display": "flex", "alignItems": "center", "gap": "12px",
240
+ "marginTop": "4px"}),
241
+ # Has CRE Losses toggle
242
+ html.Div([
243
+ html.Label("Has CRE Losses", style={
244
+ "fontSize": "13px", "color": CLR_MUTED,
245
+ "minWidth": "155px", "marginRight": "12px",
246
+ "fontWeight": "500",
247
+ }),
248
+ dcc.Checklist(
249
+ id="cre-losses-toggle",
250
+ options=[{"label": " Exclude Banks Without CRE Losses", "value": "on"}],
251
+ value=[],
252
+ style={"fontSize": "13px", "color": CLR_TEXT},
253
+ inputStyle={"marginRight": "6px"},
254
+ ),
255
+ ], style={"display": "flex", "alignItems": "center", "gap": "12px",
256
+ "marginTop": "8px"}),
257
+ # Publicly traded only toggle
258
+ html.Div([
259
+ html.Label("Publicly Traded Only", style={
260
+ "fontSize": "13px", "color": CLR_MUTED,
261
+ "minWidth": "155px", "marginRight": "12px",
262
+ "fontWeight": "500",
263
+ }),
264
+ dcc.Checklist(
265
+ id="public-toggle",
266
+ options=[{"label": " Exclude Non-Publicly Traded Banks", "value": "on"}],
267
+ value=[],
268
+ style={"fontSize": "13px", "color": CLR_TEXT},
269
+ inputStyle={"marginRight": "6px"},
270
+ ),
271
+ ], style={"display": "flex", "alignItems": "center", "gap": "12px",
272
+ "marginTop": "8px"}),
273
+ ], style={
274
+ "background": CLR_CARD_BG,
275
+ "borderRadius": "10px",
276
+ "padding": "20px 24px",
277
+ "marginBottom": "20px",
278
+ "border": f"1px solid {CLR_BORDER}",
279
+ }),
280
+
281
+ # ── Visualization 1: Tangible Equity Ratio ────────────────────────
282
+ html.Div([
283
+ html.Div([
284
+ html.Span("Tangible Equity Ratio", style={
285
+ "fontSize": "15px", "fontWeight": "600", "color": CLR_TEXT,
286
+ }),
287
+ html.Span(" — Prompt Corrective Action Categories", style={
288
+ "fontSize": "13px", "color": CLR_MUTED,
289
+ }),
290
+ ], style={"marginBottom": "4px"}),
291
+ html.P(id="formula-pca", style={
292
+ "fontSize": "11px", "color": CLR_MUTED, "margin": "0 0 8px",
293
+ "fontFamily": "monospace",
294
+ }),
295
+ # Legend
296
+ html.Div([
297
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
298
+ "background": RED_WELL_CAP, "display": "inline-block", "marginRight": "4px"}),
299
+ "Well Capitalized (\u22658%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
300
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
301
+ "background": RED_ADEQ_CAP, "display": "inline-block", "marginRight": "4px"}),
302
+ "Adequately Capitalized (\u22654%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
303
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
304
+ "background": RED_UNDERCAP, "display": "inline-block", "marginRight": "4px"}),
305
+ "Undercapitalized (\u22652%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
306
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
307
+ "background": RED_CRIT_UNDCAP, "display": "inline-block", "marginRight": "4px"}),
308
+ "Critically Undercapitalized (<2%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
309
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
310
+ "background": RED_INSOLVENT, "display": "inline-block", "marginRight": "4px"}),
311
+ "Insolvent (<0%)"], style={"fontSize": "11px", "color": CLR_MUTED}),
312
+ ], style={"marginBottom": "8px", "display": "flex", "flexWrap": "wrap", "gap": "4px"}),
313
+ dcc.Graph(id="chart-pca", config={"displayModeBar": False}, style={"height": "48px"}),
314
+ # PCA metric cards
315
+ html.Div([
316
+ metric_card("pca-total-losses", "Total Losses"),
317
+ metric_card("pca-banks-undercap", "Banks Undercapitalized", sub_id="pca-undercap-assets"),
318
+ metric_card("pca-banks-insolvent", "Banks Insolvent", sub_id="pca-insolvent-assets"),
319
+ ], style={
320
+ "display": "flex", "gap": "10px",
321
+ "flexWrap": "wrap", "marginTop": "12px",
322
+ }),
323
+ ], style={
324
+ "background": CLR_CARD_BG, "borderRadius": "10px",
325
+ "padding": "18px 24px", "marginBottom": "16px",
326
+ "border": f"1px solid {CLR_BORDER}",
327
+ }),
328
+
329
+ # ── Visualization 2: Estimated CET1 Ratio ────────────────────────
330
+ html.Div([
331
+ html.Div([
332
+ html.Span("Estimated CET1 Ratio", style={
333
+ "fontSize": "15px", "fontWeight": "600", "color": CLR_TEXT,
334
+ }),
335
+ html.Span(" — Basel III Capital Thresholds", style={
336
+ "fontSize": "13px", "color": CLR_MUTED,
337
+ }),
338
+ ], style={"marginBottom": "4px"}),
339
+ html.P(id="formula-cet1", style={
340
+ "fontSize": "11px", "color": CLR_MUTED, "margin": "0 0 8px",
341
+ "fontFamily": "monospace",
342
+ }),
343
+ # Legend
344
+ html.Div([
345
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
346
+ "background": PUR_WELL_CAP, "display": "inline-block", "marginRight": "4px"}),
347
+ "Well Capitalized (\u22656.5%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
348
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
349
+ "background": PUR_UNDERCAP, "display": "inline-block", "marginRight": "4px"}),
350
+ "Undercapitalized (\u22654.5%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
351
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
352
+ "background": PUR_BELOW_MIN, "display": "inline-block", "marginRight": "4px"}),
353
+ "Below Basel III Minimum (<4.5%)"], style={"fontSize": "11px", "color": CLR_MUTED, "marginRight": "12px"}),
354
+ html.Span([html.Span(style={"width": "10px", "height": "10px", "borderRadius": "2px",
355
+ "background": PUR_INSOLVENT, "display": "inline-block", "marginRight": "4px"}),
356
+ "Insolvent (<0%)"], style={"fontSize": "11px", "color": CLR_MUTED}),
357
+ ], style={"marginBottom": "8px", "display": "flex", "flexWrap": "wrap", "gap": "4px"}),
358
+ dcc.Graph(id="chart-cet1", config={"displayModeBar": False}, style={"height": "48px"}),
359
+ # CET1 metric cards
360
+ html.Div([
361
+ metric_card("cet1-total-losses", "Total Losses"),
362
+ metric_card("cet1-banks-undercap", "Banks Below Minimum", sub_id="cet1-undercap-assets"),
363
+ metric_card("cet1-banks-insolvent", "Banks Insolvent", sub_id="cet1-insolvent-assets"),
364
+ ], style={
365
+ "display": "flex", "gap": "10px",
366
+ "flexWrap": "wrap", "marginTop": "12px",
367
+ }),
368
+ ], style={
369
+ "background": CLR_CARD_BG, "borderRadius": "10px",
370
+ "padding": "18px 24px", "marginBottom": "16px",
371
+ "border": f"1px solid {CLR_BORDER}",
372
+ }),
373
+
374
+ ], id="capture-area", style={
375
+ "maxWidth": "860px",
376
+ "margin": "0 auto",
377
+ "padding": "40px 28px",
378
+ "background": "#FFFFFF",
379
+ "border": f"1px solid {CLR_BORDER}",
380
+ "borderRadius": "12px",
381
+ }),
382
+
383
+ # Download buttons (outside capture area)
384
+ html.Div([
385
+ html.Button(
386
+ "Download Figure",
387
+ id="btn-download",
388
+ style={
389
+ "fontSize": "13px",
390
+ "fontWeight": "500",
391
+ "padding": "10px 24px",
392
+ "borderRadius": "8px",
393
+ "border": f"1px solid {CLR_BORDER}",
394
+ "background": CLR_CARD_BG,
395
+ "color": CLR_TEXT,
396
+ "cursor": "pointer",
397
+ "marginRight": "10px",
398
+ },
399
+ ),
400
+ html.Button(
401
+ "Download Data (CSV)",
402
+ id="btn-download-csv",
403
+ style={
404
+ "fontSize": "13px",
405
+ "fontWeight": "500",
406
+ "padding": "10px 24px",
407
+ "borderRadius": "8px",
408
+ "border": f"1px solid {CLR_BORDER}",
409
+ "background": CLR_CARD_BG,
410
+ "color": CLR_TEXT,
411
+ "cursor": "pointer",
412
+ "marginRight": "10px",
413
+ },
414
+ ),
415
+ html.A(
416
+ html.Button(
417
+ "Signalpha on Substack",
418
+ style={
419
+ "fontSize": "13px",
420
+ "fontWeight": "500",
421
+ "padding": "10px 24px",
422
+ "borderRadius": "8px",
423
+ "border": "none",
424
+ "background": "#7C3AED",
425
+ "color": "#FFFFFF",
426
+ "cursor": "pointer",
427
+ },
428
+ ),
429
+ href="https://signalpha.substack.com/",
430
+ target="_blank",
431
+ style={"textDecoration": "none"},
432
+ ),
433
+ ], style={"maxWidth": "860px", "margin": "0 auto", "textAlign": "center",
434
+ "padding": "16px 28px 0"}),
435
+
436
+ # Disclaimer
437
+ html.Div([
438
+ html.P(
439
+ "Disclaimer: The information provided in this application is for educational and informational purposes only and does not constitute financial, investment, legal, or tax advice. While every effort is made to ensure the accuracy of the data and analysis presented, all content is provided \"as is\" and without warranty of any kind. Investing in financial markets involves significant risk, including the potential loss of principal. The author is not a registered investment advisor or broker-dealer, and the views expressed are personal opinions that may change without notice. You should consult with a qualified professional before making any financial decisions, and you agree that the author shall not be held liable for any losses or damages resulting from the use of this information.",
440
+ style={"fontSize": "11px", "lineHeight": "1.6", "color": CLR_MUTED, "margin": "0"},
441
+ ),
442
+ ], style={
443
+ "maxWidth": "860px", "margin": "20px auto 0",
444
+ "padding": "16px 28px",
445
+ "background": CLR_CARD_BG, "borderRadius": "10px",
446
+ "border": f"1px solid {CLR_BORDER}",
447
+ }),
448
+
449
+ # Hidden download components
450
+ dcc.Download(id="download-csv"),
451
+
452
+ # Documentation
453
+ html.Div([
454
+ html.Details([
455
+ html.Summary("Documentation", style={
456
+ "fontSize": "15px", "fontWeight": "600", "color": CLR_TEXT,
457
+ "cursor": "pointer", "padding": "12px 0",
458
+ }),
459
+ dcc.Markdown(
460
+ open(os.path.join(os.path.dirname(__file__), "documentation.md")).read(),
461
+ style={"fontSize": "13px", "lineHeight": "1.7", "color": CLR_TEXT},
462
+ ),
463
+ ], open=False),
464
+ ], style={
465
+ "maxWidth": "860px", "margin": "24px auto 0",
466
+ "background": CLR_CARD_BG, "borderRadius": "10px",
467
+ "padding": "8px 28px 20px",
468
+ "border": f"1px solid {CLR_BORDER}",
469
+ }),
470
+
471
+ ], style={
472
+ "padding": "40px 20px",
473
+ "fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', sans-serif",
474
+ "background": CLR_BG,
475
+ "minHeight": "100vh",
476
+ "color": CLR_TEXT,
477
+ })
478
+
479
+ # ── Client-side callback for image download via html2canvas ───────────────────
480
+ app.index_string = '''
481
+ <!DOCTYPE html>
482
+ <html>
483
+ <head>
484
+ {%metas%}
485
+ <title>{%title%}</title>
486
+ {%favicon%}
487
+ {%css%}
488
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
489
+ </head>
490
+ <body>
491
+ {%app_entry%}
492
+ <footer>
493
+ {%config%}
494
+ {%scripts%}
495
+ {%renderer%}
496
+ </footer>
497
+ </body>
498
+ </html>
499
+ '''
500
+
501
+ clientside_callback(
502
+ """
503
+ function(n_clicks) {
504
+ if (!n_clicks) return window.dash_clientside.no_update;
505
+ var el = document.getElementById('capture-area');
506
+ if (!el) return window.dash_clientside.no_update;
507
+ html2canvas(el, {
508
+ backgroundColor: '#FFFFFF',
509
+ scale: 2,
510
+ useCORS: true,
511
+ logging: false,
512
+ }).then(function(canvas) {
513
+ var link = document.createElement('a');
514
+ link.download = 'default-cascade-simulation.png';
515
+ link.href = canvas.toDataURL('image/png');
516
+ link.click();
517
+ });
518
+ return window.dash_clientside.no_update;
519
+ }
520
+ """,
521
+ Output("btn-download", "n_clicks"),
522
+ Input("btn-download", "n_clicks"),
523
+ prevent_initial_call=True,
524
+ )
525
+
526
+
527
+ # ── Callbacks ─────────────────────────────────────────────────────────────────
528
+ @callback(
529
+ Output("default-rate-out", "children"),
530
+ Output("lgd-out", "children"),
531
+ Output("rwa-ratio-out", "children"),
532
+ Output("min-assets-out", "children"),
533
+ # Formulas
534
+ Output("formula-pca", "children"),
535
+ Output("formula-cet1", "children"),
536
+ # PCA metrics
537
+ Output("pca-total-losses", "children"),
538
+ Output("pca-banks-undercap", "children"),
539
+ Output("pca-undercap-assets", "children"),
540
+ Output("pca-banks-insolvent", "children"),
541
+ Output("pca-insolvent-assets", "children"),
542
+ # CET1 metrics
543
+ Output("cet1-total-losses", "children"),
544
+ Output("cet1-banks-undercap", "children"),
545
+ Output("cet1-undercap-assets", "children"),
546
+ Output("cet1-banks-insolvent", "children"),
547
+ Output("cet1-insolvent-assets", "children"),
548
+ # Charts
549
+ Output("chart-pca", "figure"),
550
+ Output("chart-cet1", "figure"),
551
+ Input("default-rate", "value"),
552
+ Input("lgd", "value"),
553
+ Input("rwa-ratio", "value"),
554
+ Input("min-assets", "value"),
555
+ Input("unrealized-toggle", "value"),
556
+ Input("cre-losses-toggle", "value"),
557
+ Input("public-toggle", "value"),
558
+ )
559
+ def update(default_rate, lgd, rwa_ratio, min_assets, unrealized_toggle, cre_losses_toggle, public_toggle):
560
+ default_rate = (default_rate or 10) / 100
561
+ lgd = (lgd or 50) / 100
562
+ rwa_ratio = (rwa_ratio or 65) / 100
563
+ min_assets_b = min_assets or 10 # in $B
564
+ include_unrealized = "on" in (unrealized_toggle or [])
565
+ has_cre_only = "on" in (cre_losses_toggle or [])
566
+ public_only = "on" in (public_toggle or [])
567
+
568
+ # Filter data
569
+ data = df.copy()
570
+ data = data[data["Total Assets ($M)"] >= min_assets_b * 1000]
571
+ if public_only:
572
+ data = data[data["_has_ticker"]]
573
+ if has_cre_only:
574
+ data = data[data["CRE Total ($M)"] > 0]
575
+
576
+ n_banks = len(data)
577
+
578
+ (adj_eq, adj_cet1, total_losses,
579
+ insolv_assets_pca, undercap_assets_pca,
580
+ insolv_assets_cet1, undercap_assets_cet1) = compute_scenario(
581
+ default_rate, lgd, rwa_ratio, include_unrealized, data=data
582
+ )
583
+
584
+ # Total losses displayed in metric cards (CRE losses + unrealized if toggled)
585
+ if include_unrealized:
586
+ display_total_losses = total_losses + data["Total Unrealized Loss ($M)"].values.sum()
587
+ else:
588
+ display_total_losses = total_losses
589
+
590
+ # Dynamic formula labels
591
+ if include_unrealized:
592
+ formula_pca = "Adjusted Equity-to-Assets = (Total Equity \u2212 CRE Losses \u2212 Unrealized Losses) / Total Assets"
593
+ formula_cet1 = "Adjusted CET1 = (CET1 Capital \u2212 CRE Losses \u2212 Unrealized Losses) / (Total Assets \u00d7 RWA Ratio)"
594
+ else:
595
+ formula_pca = "Adjusted Equity-to-Assets = (Total Equity \u2212 CRE Losses) / Total Assets"
596
+ formula_cet1 = "Adjusted CET1 = (CET1 Capital \u2212 CRE Losses) / (Total Assets \u00d7 RWA Ratio)"
597
+
598
+ # PCA classification
599
+ well, adequately, under, critical, insolvent = classify_pca(adj_eq)
600
+
601
+ # CET1 classification
602
+ c_well, c_under, c_below, c_insolvent = classify_cet1(adj_cet1)
603
+
604
+ # PCA counts
605
+ n_undercap_pca = under + critical + insolvent
606
+ n_insolvent_pca = insolvent
607
+
608
+ # CET1 counts
609
+ n_undercap_cet1 = c_below + c_insolvent
610
+ n_insolvent_cet1 = c_insolvent
611
+
612
+ # ── PCA bar chart ─────────────────────────────────────────────────────
613
+ fig_pca = go.Figure()
614
+
615
+ pca_data = [
616
+ ("Well Capitalized", well, RED_WELL_CAP, "#1A1A1A"),
617
+ ("Adequately Capitalized", adequately, RED_ADEQ_CAP, "#1A1A1A"),
618
+ ("Undercapitalized", under, RED_UNDERCAP, "#FFFFFF"),
619
+ ("Critically Undercapitalized", critical, RED_CRIT_UNDCAP, "#FFFFFF"),
620
+ ("Insolvent", insolvent, RED_INSOLVENT, "#FFFFFF"),
621
+ ]
622
+
623
+ for name, count, color, text_color in pca_data:
624
+ fig_pca.add_trace(go.Bar(
625
+ name=name,
626
+ y=["Banks"],
627
+ x=[count],
628
+ width=[BAR_WIDTH],
629
+ orientation="h",
630
+ marker_color=color,
631
+ text=[str(count) if count > 0 else ""],
632
+ textposition="inside",
633
+ textfont={"size": 13, "color": text_color, "family": "Inter, sans-serif"},
634
+ insidetextanchor="middle",
635
+ hovertemplate=f"{name}: %{{x}} banks<extra></extra>",
636
+ showlegend=False,
637
+ ))
638
+
639
+ fig_pca.update_layout(
640
+ barmode="stack",
641
+ paper_bgcolor="rgba(0,0,0,0)",
642
+ plot_bgcolor="rgba(0,0,0,0)",
643
+ margin={"l": 0, "r": 0, "t": 0, "b": 0},
644
+ xaxis={"visible": False, "range": [0, n_banks]},
645
+ yaxis={"visible": False, "range": [-0.5, 0.5]},
646
+ height=BAR_HEIGHT,
647
+ hoverlabel={"bgcolor": "#FFFFFF", "bordercolor": CLR_BORDER, "font": {"color": CLR_TEXT}},
648
+ )
649
+
650
+ # ── CET1 bar chart ────────────────────────────────────────────────────
651
+ fig_cet1 = go.Figure()
652
+
653
+ cet1_data = [
654
+ ("Well Capitalized", c_well, PUR_WELL_CAP, "#1A1A1A"),
655
+ ("Undercapitalized", c_under, PUR_UNDERCAP, "#FFFFFF"),
656
+ ("Below Basel III Minimum", c_below, PUR_BELOW_MIN, "#FFFFFF"),
657
+ ("Insolvent", c_insolvent, PUR_INSOLVENT, "#FFFFFF"),
658
+ ]
659
+
660
+ for name, count, color, text_color in cet1_data:
661
+ fig_cet1.add_trace(go.Bar(
662
+ name=name,
663
+ y=["Banks"],
664
+ x=[count],
665
+ width=[BAR_WIDTH],
666
+ orientation="h",
667
+ marker_color=color,
668
+ text=[str(count) if count > 0 else ""],
669
+ textposition="inside",
670
+ textfont={"size": 13, "color": text_color, "family": "Inter, sans-serif"},
671
+ insidetextanchor="middle",
672
+ hovertemplate=f"{name}: %{{x}} banks<extra></extra>",
673
+ showlegend=False,
674
+ ))
675
+
676
+ fig_cet1.update_layout(
677
+ barmode="stack",
678
+ paper_bgcolor="rgba(0,0,0,0)",
679
+ plot_bgcolor="rgba(0,0,0,0)",
680
+ margin={"l": 0, "r": 0, "t": 0, "b": 0},
681
+ xaxis={"visible": False, "range": [0, n_banks]},
682
+ yaxis={"visible": False, "range": [-0.5, 0.5]},
683
+ height=BAR_HEIGHT,
684
+ hoverlabel={"bgcolor": "#FFFFFF", "bordercolor": CLR_BORDER, "font": {"color": CLR_TEXT}},
685
+ )
686
+
687
+ return (
688
+ f"{default_rate * 100:.1f}%",
689
+ f"{lgd * 100:.1f}%",
690
+ f"{rwa_ratio * 100:.1f}%",
691
+ f"${min_assets_b:.0f}B",
692
+ # Formulas
693
+ formula_pca,
694
+ formula_cet1,
695
+ # PCA metrics
696
+ f"${display_total_losses / 1000:.1f}B",
697
+ str(n_undercap_pca),
698
+ fmt_assets(undercap_assets_pca),
699
+ str(n_insolvent_pca),
700
+ fmt_assets(insolv_assets_pca),
701
+ # CET1 metrics
702
+ f"${display_total_losses / 1000:.1f}B",
703
+ str(n_undercap_cet1),
704
+ fmt_assets(undercap_assets_cet1),
705
+ str(n_insolvent_cet1),
706
+ fmt_assets(insolv_assets_cet1),
707
+ # Charts
708
+ fig_pca,
709
+ fig_cet1,
710
+ )
711
+
712
+
713
+ # ── CSV download callback ─────────────────────────────────────────────────────
714
+ def classify_pca_label(ratio):
715
+ if ratio >= 0.08:
716
+ return "Well Capitalized"
717
+ elif ratio >= 0.04:
718
+ return "Adequately Capitalized"
719
+ elif ratio >= 0.02:
720
+ return "Undercapitalized"
721
+ elif ratio >= 0:
722
+ return "Critically Undercapitalized"
723
+ return "Insolvent"
724
+
725
+
726
+ def classify_cet1_label(ratio):
727
+ if ratio >= 0.065:
728
+ return "Well Capitalized"
729
+ elif ratio >= 0.045:
730
+ return "Undercapitalized"
731
+ elif ratio >= 0:
732
+ return "Below Basel III Minimum"
733
+ return "Insolvent"
734
+
735
+
736
+ @callback(
737
+ Output("download-csv", "data"),
738
+ Input("btn-download-csv", "n_clicks"),
739
+ State("default-rate", "value"),
740
+ State("lgd", "value"),
741
+ State("rwa-ratio", "value"),
742
+ State("min-assets", "value"),
743
+ State("unrealized-toggle", "value"),
744
+ State("cre-losses-toggle", "value"),
745
+ State("public-toggle", "value"),
746
+ prevent_initial_call=True,
747
+ )
748
+ def download_csv(n_clicks, default_rate, lgd_val, rwa_ratio, min_assets, unrealized_toggle, cre_losses_toggle, public_toggle):
749
+ if not n_clicks:
750
+ return dash.no_update
751
+
752
+ dr = (default_rate or 10) / 100
753
+ lgd_v = (lgd_val or 50) / 100
754
+ rwa_r = (rwa_ratio or 65) / 100
755
+ min_assets_b = min_assets or 10
756
+ include_unrealized = "on" in (unrealized_toggle or [])
757
+ has_cre_only = "on" in (cre_losses_toggle or [])
758
+ public_only = "on" in (public_toggle or [])
759
+
760
+ data = df.copy()
761
+ data = data[data["Total Assets ($M)"] >= min_assets_b * 1000]
762
+ if public_only:
763
+ data = data[data["_has_ticker"]]
764
+ if has_cre_only:
765
+ data = data[data["CRE Total ($M)"] > 0]
766
+
767
+ cre = data["CRE Total ($M)"].values
768
+ equity = data["Total Equity ($M)"].values
769
+ assets = data["Total Assets ($M)"].values
770
+ cet1 = data["CET1 Capital ($M)"].values
771
+ unrealized = data["Total Unrealized Loss ($M)"].values if include_unrealized else 0
772
+
773
+ cre_losses = cre * dr * lgd_v
774
+ adj_eq = (equity - cre_losses - unrealized) / assets
775
+ estimated_rwa = assets * rwa_r
776
+ adj_cet1 = (cet1 - cre_losses - unrealized) / estimated_rwa
777
+
778
+ out = pd.DataFrame({
779
+ "Bank Name": data["Name"].values,
780
+ "State": data["ST"].values,
781
+ "Total Assets ($M)": assets,
782
+ "Total Equity ($M)": equity,
783
+ "CRE Total ($M)": cre,
784
+ "CET1 Capital ($M)": cet1,
785
+ "Total Unrealized Loss ($M)": data["Total Unrealized Loss ($M)"].values,
786
+ "CRE Losses ($M)": cre_losses.round(1),
787
+ "Adjusted Equity-to-Assets (%)": (adj_eq * 100).round(2),
788
+ "PCA Classification": [classify_pca_label(r) for r in adj_eq],
789
+ "Adjusted CET1 Ratio (%)": (adj_cet1 * 100).round(2),
790
+ "CET1 Classification": [classify_cet1_label(r) for r in adj_cet1],
791
+ })
792
+
793
+ buf = io.StringIO()
794
+ out.to_csv(buf, index=False)
795
+
796
+ unr_tag = "_UL" if include_unrealized else ""
797
+ pub_tag = "_PUB" if public_only else ""
798
+ filename = f"cre-simulation_DR{default_rate:.0f}_LGD{lgd_val:.0f}_RWA{rwa_ratio:.0f}{unr_tag}{pub_tag}.csv"
799
+ return dcc.send_string(buf.getvalue(), filename=filename)
800
+
801
+
802
+ # ── Entry point ───────────────────────────────────────────────────────────────
803
+ if __name__ == "__main__":
804
+ app.run(debug=False, host="0.0.0.0", port=8050)
assets/custom.css ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Force all slider input/handle boxes to uniform width */
2
+ .dash-slider input,
3
+ .rc-slider input,
4
+ [class*="slider"] input[type="number"],
5
+ [class*="Slider"] input[type="number"] {
6
+ min-width: 64px !important;
7
+ width: 64px !important;
8
+ text-align: center !important;
9
+ box-sizing: border-box !important;
10
+ }
11
+
12
+ .rc-slider-tooltip-inner {
13
+ min-width: 64px !important;
14
+ text-align: center !important;
15
+ }
assets/signalpha-banner.png ADDED

Git LFS Details

  • SHA256: 7d2d2bfcb05af247d9d726ebf39b1381719fc8a1db2fbf77ac96a1060f504337
  • Pointer size: 131 Bytes
  • Size of remote file: 512 kB
data.csv ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Ticker,Name,ST,Total Assets ($M),Total Equity ($M),Equity to Assets,CRE Total ($M),CRE Total to Equity,Total Unrealized Loss ($M),CET1 Capital ($M),HTM Loss ($M),AFS Loss ($M),HTM+AFS Loss to CET1 Capital,Total Domestic Deposits ($M),Liquid Assets ($M),Uninsured Deposits ($M),Percent Uninsured,Uninsured Deposits Rank,Uninsured Deposits % of Liquid Assets
2
+ LOB,LIVE OAK BANKING COMPANY,NC,12856,970,7.5%,5634,580.6%,69.0,1100,0.0,69.0,6.2%,13427,2332,2190,16.3,135,93.9
3
+ DCOM,DIME COMMUNITY BANK,NY,14337,1579,11.0%,8982,569.0%,86.0,1520,63.0,24.0,5.7%,12152,3020,6211,51.1,32,205.6
4
+ EAGL,EAGLEBANK,MD,11080,1231,11.1%,6852,556.7%,173.0,1236,84.0,88.0,14.0%,9473,2834,2310,24.4,122,81.5
5
+ FLG,"FLAGSTAR BANK, NATIONAL ASSOCI",NY,100102,8579,8.6%,46444,541.4%,648.0,8832,0.0,648.0,7.3%,69628,24183,18450,26.5,119,76.3
6
+ OZK,BANK OZK,AR,38259,5706,14.9%,30619,536.6%,48.0,5124,0.0,48.0,0.9%,33985,5928,12012,35.3,95,202.6
7
+ SFBS,SERVISFIRST BANK,AL,17351,1676,9.7%,8830,526.9%,57.0,1831,49.0,8.0,3.1%,14131,3193,9459,66.9,8,296.2
8
+ ,MERCHANTS BANK OF INDIANA,IN,18622,2074,11.1%,10592,510.7%,1.0,2171,0.0,-0.0,-0.0%,13998,2563,3736,26.7,118,145.8
9
+ PFS,PROVIDENT BANK,NJ,24008,2893,12.1%,14620,505.3%,126.0,2453,8.0,119.0,5.1%,19153,3855,10368,54.1,21,268.9
10
+ FFWM,FIRST FOUNDATION BANK,CA,12612,1189,9.4%,5627,473.4%,52.0,1066,50.0,2.0,4.9%,9321,3931,1901,20.4,129,48.3
11
+ ,APPLE BANK,NY,17460,1503,8.6%,6867,457.0%,202.0,1478,50.0,152.0,13.6%,15406,4643,3562,23.1,125,76.7
12
+ ,FIRST UNITED BANK AND TRUST CO,OK,16260,1427,8.8%,6465,453.2%,77.0,1479,0.0,77.0,5.2%,12808,1979,4194,32.7,103,211.9
13
+ FMBL,FARMERS AND MERCHANTS BANK OF,CA,11690,1369,11.7%,6186,451.9%,263.0,1397,261.0,2.0,18.8%,8872,5181,4823,54.4,20,93.1
14
+ ,FIRSTBANK,CO,27247,1554,5.7%,7015,451.6%,767.0,2443,33.0,734.0,31.4%,23275,10180,7087,30.4,109,69.6
15
+ COLB,COLUMBIA BANK,NJ,10472,1045,10.0%,4622,442.1%,115.0,1039,31.0,84.0,11.1%,8331,1817,3180,38.2,83,175.0
16
+ BCI.SN,CITY NATIONAL BANK OF FLORIDA,FL,26507,2522,9.5%,11090,439.7%,692.0,3031,244.0,447.0,22.8%,21955,7198,10611,48.3,40,147.4
17
+ DSCT.TA,ISRAEL DISCOUNT BANK OF NEW YO,NY,13856,1311,9.5%,5655,431.4%,203.0,1488,97.0,105.0,13.6%,12409,3590,6221,50.1,36,173.3
18
+ ZION,"ZIONS BANCORPORATION, NATIONAL",UT,88775,6124,6.9%,25423,415.2%,1208.0,7734,0.0,1208.0,15.6%,75105,22400,34582,46.0,48,154.4
19
+ HOPE,BANK OF HOPE,CA,17049,2213,13.0%,9069,409.8%,207.0,1945,14.0,193.0,10.7%,15849,2914,6226,39.3,79,213.6
20
+ PNFP,SYNOVUS BANK,GA,60120,5178,8.6%,21211,409.7%,287.0,5957,0.0,287.0,4.8%,50536,12501,25737,50.9,35,205.9
21
+ BANR,BANNER BANK,WA,16211,1813,11.2%,7233,398.9%,430.0,1770,156.0,274.0,24.3%,14076,3938,4490,31.9,105,114.0
22
+ ,WASHINGTON TRUST BANK,WA,10728,905,8.4%,3572,394.9%,262.0,984,242.0,20.0,26.6%,8872,2987,5047,56.9,16,169.0
23
+ VLY,VALLEY NATIONAL BANK,NJ,62447,7884,12.6%,31133,394.9%,496.0,6202,391.0,105.0,8.0%,51320,9119,19897,38.8,81,218.2
24
+ BPOP,POPULAR BANK,NY,14332,1985,13.8%,7786,392.3%,47.0,1590,0.0,47.0,2.9%,12162,2669,3674,30.2,111,137.6
25
+ ,BELL BANK,ND,14534,1350,9.3%,5235,387.9%,6.0,1412,0.0,6.0,0.4%,12046,1176,2980,24.7,121,253.3
26
+ BANC,BANC OF CALIFORNIA,CA,33458,3919,11.7%,15123,385.9%,288.0,3485,80.0,208.0,8.3%,27339,7333,8081,29.6,113,110.2
27
+ OCFC,"OCEANFIRST BANK, NATIONAL ASSO",NJ,13332,1697,12.7%,6332,373.2%,75.0,1172,64.0,11.0,6.4%,10560,2459,6367,60.3,13,259.0
28
+ EFSC,ENTERPRISE BANK & TRUST,MO,15568,1825,11.7%,6775,371.3%,152.0,1658,50.0,102.0,9.2%,13714,4006,4233,30.9,108,105.7
29
+ ,ARVEST BANK,AR,26895,1981,7.4%,7342,370.7%,913.0,2462,0.0,913.0,37.1%,24028,6878,6220,25.9,120,90.4
30
+ WAFD,WASHINGTON FEDERAL BANK,WA,27671,3007,10.9%,11118,369.7%,58.0,2506,33.0,25.0,2.3%,21585,4861,6454,29.9,112,132.8
31
+ UMBF,"UMB BANK, NATIONAL ASSOCIATION",MO,50150,3463,6.9%,12210,352.6%,903.0,5399,535.0,369.0,16.7%,60458,28343,39998,66.2,9,141.1
32
+ AX,AXOS BANK,CA,22841,2390,10.5%,8262,345.7%,0.0,2353,0.0,-0.0,-0.0%,22618,3765,3644,16.1,136,96.8
33
+ TOWN,TOWNEBANK,VA,17248,2139,12.4%,7338,343.0%,93.0,1769,3.0,89.0,5.2%,16627,4170,7695,46.3,44,184.5
34
+ FULT,"FULTON BANK, NATIONAL ASSOCIAT",PA,31916,3309,10.4%,11341,342.7%,419.0,3086,166.0,253.0,13.6%,26576,6087,10813,40.7,71,177.6
35
+ RNST,FIRST BANK,NC,12148,1521,12.5%,5200,341.8%,323.0,1385,72.0,252.0,23.4%,10901,3532,4387,40.2,73,124.2
36
+ CADE,STELLAR BANK,TX,10891,1608,14.8%,5429,337.6%,99.0,1143,0.0,99.0,8.6%,8887,2666,5021,56.5,17,188.3
37
+ AUB,ATLANTIC UNION BANK,VA,24469,3475,14.2%,11728,337.5%,363.0,3882,36.0,328.0,9.4%,30708,6265,10946,35.6,92,174.7
38
+ CMA,COMERICA BANK,TX,79332,6133,7.7%,20648,336.7%,2187.0,8366,0.0,2187.0,26.1%,63812,22051,34857,54.6,19,158.1
39
+ CATY,CATHAY BANK,CA,23036,2899,12.6%,9644,332.7%,85.0,2650,0.0,85.0,3.2%,20288,3036,9959,49.1,37,328.0
40
+ GBCI,GLACIER BANK,MT,27886,3178,11.4%,10567,332.5%,526.0,2638,266.0,260.0,19.9%,22062,8186,7134,32.3,104,87.2
41
+ ,FIRSTBANK,TN,13119,1527,11.6%,5011,328.1%,56.0,1688,0.0,56.0,3.3%,13836,2479,5756,41.6,67,232.2
42
+ ,"CENTRAL TRUST BANK, THE",MO,19230,1728,9.0%,5669,328.1%,71.0,1652,0.0,71.0,4.3%,15165,7068,5310,35.0,96,75.1
43
+ FIBK,FIRST INTERSTATE BANK,MT,29066,3264,11.2%,10661,326.6%,490.0,2498,226.0,264.0,19.6%,22914,9020,7887,34.4,97,87.4
44
+ VBTX,VERITEX COMMUNITY BANK,TX,12718,1756,13.8%,5714,325.5%,61.0,1368,20.0,41.0,4.4%,10815,2341,4927,45.6,50,210.5
45
+ HTH,PLAINSCAPITAL BANK,TX,13329,1469,11.0%,4745,322.9%,130.0,1323,58.0,71.0,9.8%,10747,3410,5726,53.3,24,167.9
46
+ SFNC,SIMMONS BANK,AR,26843,3570,13.3%,11504,322.2%,469.0,2030,0.0,469.0,23.1%,20742,4432,9566,46.1,46,215.8
47
+ CUBI,CUSTOMERS BANK,PA,22296,1826,8.2%,5757,315.2%,110.0,2122,44.0,65.0,5.2%,20622,7052,8700,42.2,64,123.4
48
+ CVBF,CITIZENS BUSINESS BANK,CA,15161,2163,14.3%,6742,311.7%,685.0,1743,362.0,323.0,39.3%,12175,5996,7417,60.9,11,123.7
49
+ ONB,OLD NATIONAL BANK,IN,53245,6159,11.6%,18637,302.6%,1118.0,5898,392.0,726.0,19.0%,55525,16720,26765,48.2,41,160.1
50
+ WSFS,WILMINGTON SAVINGS FUND SOCIET,DE,20722,2517,12.1%,7585,301.4%,621.0,2180,94.0,527.0,28.5%,17586,6575,6966,39.6,76,106.0
51
+ SSB,"SOUTHSTATE BANK, N.A.",FL,46370,6161,13.3%,18497,300.2%,757.0,6422,331.0,426.0,11.8%,54186,11695,20915,38.6,82,178.8
52
+ EWBC,EAST WEST BANK,CA,75842,7251,9.6%,21750,300.0%,861.0,7908,413.0,448.0,10.9%,62886,20372,33373,53.1,26,163.8
53
+ BOH,BANK OF HAWAII,HI,23568,1540,6.5%,4604,298.9%,809.0,1952,622.0,187.0,41.4%,19784,8790,10092,51.0,34,114.8
54
+ FHN,FIRST HORIZON BANK,TN,81866,8782,10.7%,26013,296.2%,886.0,8093,150.0,736.0,10.9%,66112,12208,27225,41.2,69,223.0
55
+ CFR,FROST BANK,Tx,52581,3822,7.3%,11224,293.7%,1311.0,4634,166.0,1144.0,28.3%,42943,29389,22028,51.3,31,75.0
56
+ UCB,UNITED COMMUNITY BANK,SC,27657,3282,11.9%,9615,293.0%,492.0,2583,337.0,155.0,19.0%,24413,6923,9853,40.4,72,142.3
57
+ INDB,ROCKLAND TRUST COMPANY,MA,19379,2966,15.3%,8619,290.6%,154.0,2683,97.0,57.0,5.7%,20418,4268,6740,33.0,101,157.9
58
+ PNFP,PINNACLE BANK,TN,52489,6517,12.4%,18840,289.1%,402.0,5246,214.0,188.0,7.7%,45988,12502,19559,42.5,61,156.4
59
+ RNST,RENASANT BANK,MS,18037,2695,14.9%,7783,288.8%,162.0,2526,75.0,87.0,6.4%,21791,4712,10024,46.0,49,212.7
60
+ WSBC,"WESBANCO BANK, INC.",WV,18649,2729,14.6%,7861,288.1%,310.0,2507,108.0,202.0,12.4%,21631,5626,7093,32.8,102,126.1
61
+ ABCB,AMERIS BANK,GA,26175,3790,14.5%,10821,285.5%,15.0,3001,15.0,0.0,0.5%,22432,3366,10371,46.2,45,308.1
62
+ FCF,FIRST COMMONWEALTH BANK,PA,11554,1370,11.9%,3909,285.3%,138.0,1187,52.0,87.0,11.7%,10317,1780,2988,29.0,115,167.8
63
+ RJF,TRISTATE CAPITAL BANK,PA,20969,1396,6.7%,3913,280.2%,138.0,1661,0.0,138.0,8.3%,20515,5417,7724,37.6,85,142.6
64
+ UBSI,UNITED BANK,VA,29925,5025,16.8%,14005,278.7%,224.0,3600,0.0,224.0,6.2%,27082,5757,10602,39.1,80,184.2
65
+ NBTB,"NBT BANK, NATIONAL ASSOCIATION",NY,13683,1488,10.9%,4116,276.6%,174.0,1429,65.0,109.0,12.2%,13791,3330,5959,43.2,59,178.9
66
+ WAL,WESTERN ALLIANCE BANK,AZ,80862,6903,8.5%,19011,275.4%,638.0,7319,165.0,473.0,8.7%,77520,24964,24392,31.5,107,97.7
67
+ CADE,CADENCE BANK,MS,47019,5570,11.8%,15327,275.2%,593.0,4772,0.0,593.0,12.4%,43921,12097,16397,37.3,86,135.5
68
+ CBU,"COMMUNITY BANK, NATIONAL ASSOC",NY,16130,1365,8.5%,3687,270.1%,380.0,1305,81.0,298.0,29.1%,14216,4817,4743,33.4,100,98.5
69
+ BKU,"BANKUNITED, NATIONAL ASSOCIATI",FL,35207,3233,9.2%,8720,269.7%,290.0,3324,0.0,290.0,8.7%,28878,10308,14940,51.7,28,144.9
70
+ BANF,BANCFIRST,OK,11405,1208,10.6%,3223,266.7%,15.0,1239,0.0,15.0,1.2%,10366,4399,2881,27.8,116,65.5
71
+ ASB,"ASSOCIATED BANK, NATIONAL ASSO",WI,42966,4453,10.4%,11698,262.7%,454.0,3602,454.0,0.0,12.6%,34945,10123,16098,46.1,47,159.0
72
+ BOKF,"BOKF, NATIONAL ASSOCIATION",OK,49466,5130,10.4%,13455,262.3%,339.0,4728,136.0,204.0,7.2%,38775,16986,20781,53.6,23,122.3
73
+ ,MIDFIRST BANK,OK,39087,3849,9.8%,10077,261.8%,163.0,3628,12.0,152.0,4.5%,25291,6806,5782,22.9,126,84.9
74
+ EBC,EASTERN BANK,MA,25552,3418,13.4%,8838,258.6%,372.0,2768,28.0,345.0,13.5%,21387,5073,8911,41.7,66,175.6
75
+ BUSE,BUSEY BANK,IL,12011,1584,13.2%,4080,257.6%,278.0,2118,125.0,152.0,13.1%,15173,3422,6452,42.5,62,188.5
76
+ WBS,"WEBSTER BANK, NATIONAL ASSOCIA",CT,78957,9378,11.9%,24068,256.7%,1334.0,7162,837.0,497.0,18.6%,68697,21534,24485,35.6,93,113.7
77
+ SBCF,SEACOAST NATIONAL BANK,FL,15167,2181,14.4%,5583,255.9%,220.0,1649,100.0,120.0,13.4%,13097,4263,4969,37.9,84,116.6
78
+ ,"DOLLAR BANK, FEDERAL SAVINGS B",PA,11640,1150,9.9%,2937,255.3%,154.0,1332,0.0,154.0,11.6%,10068,2235,3049,30.3,110,136.4
79
+ HOMB,CENTENNIAL BANK,AR,22418,3779,16.9%,9581,253.5%,346.0,2705,107.0,239.0,12.8%,17701,5225,8526,48.2,42,163.2
80
+ FHB,FIRST HAWAIIAN BANK,HI,23831,2604,10.9%,5969,229.2%,576.0,2113,384.0,191.0,27.2%,18607,7628,10429,56.0,18,136.7
81
+ CBSH,COMMERCE BANK,MO,31808,2698,8.5%,6151,228.0%,688.0,3554,0.0,688.0,19.4%,25833,12646,10220,39.6,77,80.8
82
+ ,FIRST NATIONAL BANK OF OMAHA,NE,31986,3116,9.7%,7086,227.4%,196.0,3584,12.0,183.0,5.5%,26119,7582,8912,34.1,98,117.5
83
+ HWC,HANCOCK WHITNEY BANK,MS,35068,3995,11.4%,9046,226.4%,543.0,3803,133.0,410.0,14.3%,28930,9763,14200,49.1,38,145.4
84
+ UNH,"OPTUM BANK, INC.",UT,18649,2159,11.6%,4861,225.2%,472.0,2318,0.0,472.0,20.4%,15800,10497,319,2.0,151,3.0
85
+ FNB,FIRST NATIONAL BANK OF PENNSYL,PA,48447,6191,12.8%,13565,219.1%,281.0,4149,211.0,70.0,6.8%,38921,10149,15852,40.7,70,156.2
86
+ ,MECHANICS BANK,CA,16494,2302,14.0%,5041,219.0%,183.0,2027,177.0,5.0,9.0%,19460,6304,6631,34.1,99,105.2
87
+ FFBC,FIRST FINANCIAL BANK,OH,18486,2413,13.1%,5023,208.2%,253.0,1791,6.0,247.0,14.1%,14610,4481,6073,41.6,68,135.5
88
+ FBP,FIRSTBANK PUERTO RICO,PR,19286,1694,8.8%,3511,207.3%,390.0,2070,4.0,386.0,18.8%,16660,6157,8830,53.0,27,143.4
89
+ FFIN,FIRST FINANCIAL BANK,TX,13925,1468,10.5%,3029,206.3%,389.0,1680,0.0,389.0,23.2%,12990,6242,5683,43.7,57,91.0
90
+ FRME,FIRST MERCHANTS BANK,IN,18299,2316,12.7%,4757,205.4%,486.0,1835,289.0,197.0,26.5%,14923,3836,6626,44.4,56,172.7
91
+ TCBI,TEXAS CAPITAL BANK,TX,30622,3599,11.8%,7271,202.0%,151.0,3510,81.0,70.0,4.3%,27943,7476,11821,42.3,63,158.1
92
+ ,"EVERBANK, NATIONAL ASSOCIATION",FL,40802,3695,9.1%,7441,201.4%,178.0,3985,2.0,176.0,4.5%,35744,10732,4784,13.4,137,44.6
93
+ NWBI,NORTHWEST BANK,PA,14463,1591,11.0%,3159,198.5%,219.0,1526,84.0,135.0,14.3%,13934,2412,3747,26.9,117,155.3
94
+ FCNCA,FIRST-CITIZENS BANK & TRUST CO,NC,223543,21932,9.8%,43278,197.3%,1436.0,21876,1212.0,224.0,6.6%,163581,70619,59746,36.5,91,84.6
95
+ SF,STIFEL BANK AND TRUST,MO,19510,1364,7.0%,2560,187.7%,57.0,827,0.0,57.0,6.9%,11126,4477,2011,18.1,132,44.9
96
+ CM,CIBC BANK USA,IL,61517,10123,16.5%,18840,186.1%,66.0,8082,63.0,3.0,0.8%,48303,19680,31753,65.7,10,161.4
97
+ BPOP,BANCO POPULAR DE PUERTO RICO,PR,58456,3178,5.4%,5820,183.1%,883.0,4528,0.0,883.0,19.5%,54539,31554,31561,57.9,14,100.0
98
+ SAN,"SANTANDER BANK, NATIONAL ASSOC",DE,102701,12645,12.3%,22267,176.1%,1973.0,12678,1282.0,691.0,15.6%,74411,34167,26398,35.5,94,77.3
99
+ RY,CITY NATIONAL BANK,CA,92193,11372,12.3%,16504,145.1%,485.0,10683,485.0,0.0,4.5%,80218,26024,48538,60.5,12,186.5
100
+ RJF,RAYMOND JAMES BANK,FL,41241,2940,7.1%,4129,140.4%,456.0,3434,0.0,456.0,13.3%,38898,7512,3292,8.5,142,43.8
101
+ MTB,MANUFACTURERS AND TRADERS TRUS,NY,207556,27568,13.3%,38010,137.9%,789.0,19464,789.0,0.0,4.1%,167627,54332,81823,48.8,39,150.6
102
+ ,NEXBANK,TX,13943,1328,9.5%,1826,137.4%,133.0,1299,0.0,133.0,10.2%,11256,4160,1278,11.4,139,30.7
103
+ CFG,"CITIZENS BANK, NATIONAL ASSOCI",RI,217179,24389,11.2%,32376,132.7%,2235.0,20823,829.0,1406.0,10.7%,183739,57084,82117,44.7,52,143.9
104
+ PB,PROSPERITY BANK,TX,39595,7419,18.7%,9173,123.6%,920.0,3881,918.0,2.0,23.7%,28161,12025,11309,40.2,74,94.0
105
+ OFG,ORIENTAL BANK,PR,11416,1189,10.4%,1413,118.9%,78.0,1239,47.0,31.0,6.3%,10015,3567,5321,53.1,25,149.2
106
+ KEY,KEYBANK NATIONAL ASSOCIATION,OH,184461,16770,9.1%,19627,117.0%,2894.0,18240,345.0,2549.0,15.9%,156170,65750,79754,51.1,33,121.3
107
+ HBAN,"HUNTINGTON NATIONAL BANK, THE",OH,203428,19701,9.7%,20400,103.5%,4084.0,17546,1727.0,2357.0,23.3%,169742,57728,53686,31.6,106,93.0
108
+ RF,REGIONS BANK,AL,155918,16174,10.4%,16085,99.5%,817.0,14575,53.0,764.0,5.6%,131484,45864,51982,39.5,78,113.3
109
+ FITB,"FIFTH THIRD BANK, NATIONAL ASS",OH,212197,22064,10.4%,20046,90.9%,3155.0,21470,0.0,3155.0,14.7%,169563,70310,75520,44.5,54,107.4
110
+ TFC,TRUIST BANK,NC,523132,60832,11.6%,54957,90.3%,13069.0,51130,8355.0,4714.0,25.6%,404056,154730,172826,42.8,60,111.7
111
+ PNC,"PNC BANK, NATIONAL ASSOCIATION",DE,556139,53455,9.6%,46773,87.5%,4737.0,51050,2552.0,2185.0,9.3%,439115,182489,198026,45.1,51,108.5
112
+ BMO,BMO BANK NATIONAL ASSOCIATION,IL,263653,34698,13.2%,30108,86.8%,1947.0,26463,77.0,1869.0,7.4%,194762,87537,100702,51.7,30,115.0
113
+ ,SAFRA NATIONAL BANK OF NEW YOR,NY,11305,1254,11.1%,1017,81.1%,144.0,1078,0.0,144.0,13.4%,10549,8139,4211,39.9,75,51.7
114
+ WFC,"WELLS FARGO BANK, NATIONAL ASS",SD,1705538,166189,9.7%,133676,80.4%,36886.0,150610,33819.0,3067.0,24.5%,1418394,589946,663483,46.8,43,112.5
115
+ USB,U.S. BANK NATIONAL ASSOCIATION,OH,662906,63537,9.6%,49057,77.2%,14588.0,61013,9585.0,5003.0,23.9%,530919,236169,274656,51.7,29,116.3
116
+ TD,"TD BANK, N.A.",DE,372778,46599,12.5%,34490,74.0%,1160.0,37770,0.0,1160.0,3.1%,287103,159622,105014,36.6,90,65.8
117
+ NTRS,"NORTHERN TRUST COMPANY, THE",IL,154948,10798,7.0%,6791,62.9%,1221.0,10438,1136.0,85.0,11.7%,50955,112653,39699,77.9,5,35.2
118
+ JPM,"JPMORGAN CHASE BANK, NATIONAL",OH,3459261,312794,9.0%,174381,55.7%,20414.0,291288,18610.0,1804.0,7.0%,2116593,1092333,1223904,57.8,15,112.0
119
+ COF,"CAPITAL ONE, NATIONAL ASSOCIAT",VA,487193,55895,11.5%,28617,51.2%,7235.0,67633,0.0,7235.0,10.7%,498827,145919,107420,21.5,128,73.6
120
+ DB,DEUTSCHE BANK TRUST COMPANY AM,NY,39780,9671,24.3%,4632,47.9%,24.0,9665,0.0,24.0,0.2%,28141,16381,26328,93.6,3,160.7
121
+ ALLY,ALLY BANK,UT,181409,13776,7.6%,6577,47.7%,2773.0,17773,0.0,2773.0,15.6%,152626,35014,16930,11.1,141,48.4
122
+ MS,"MORGAN STANLEY BANK, N.A.",UT,230712,22090,9.6%,10192,46.1%,4275.0,25948,2704.0,1571.0,16.5%,201602,102287,40231,20.0,130,39.3
123
+ ,BEAL BANK USA,NV,16216,3326,20.5%,1405,42.2%,0.0,3072,0.0,-0.0,-0.0%,5075,12104,3707,73.0,6,30.6
124
+ MS,"MORGAN STANLEY PRIVATE BANK, N",NY,221306,17084,7.7%,7165,41.9%,4853.0,17613,4342.0,511.0,27.6%,213792,69951,52133,24.4,123,74.5
125
+ LC,"LENDINGCLUB BANK, NATIONAL ASS",UT,10469,1175,11.2%,467,39.7%,28.0,1136,0.0,28.0,2.4%,9518,4577,1156,12.1,138,25.3
126
+ BAC,"BANK OF AMERICA, NATIONAL ASSO",NC,2589060,245482,9.5%,82102,33.4%,87273.0,196596,84904.0,2369.0,44.4%,1956667,1137275,869263,44.4,55,76.4
127
+ HSBC,"HSBC BANK USA, NATIONAL ASSOCI",VA,164820,15734,9.5%,4194,26.7%,2048.0,16020,235.0,1813.0,12.8%,129353,75108,87392,67.6,7,116.4
128
+ UBS,UBS BANK USA,UT,119112,9539,8.0%,2268,23.8%,295.0,9976,295.0,0.0,3.0%,99606,26642,29245,29.4,114,109.8
129
+ GS,GOLDMAN SACHS BANK USA,NY,558235,63033,11.3%,14019,22.2%,0.0,64251,0.0,-0.0,-0.0%,405207,205281,169605,41.9,65,82.6
130
+ BK,"BANK OF NEW YORK MELLON, THE",NY,335955,27960,8.3%,5806,20.8%,3699.0,22269,3025.0,674.0,16.6%,206711,267243,193864,93.8,2,72.5
131
+ BK,"BNY MELLON, NATIONAL ASSOCIATI",PA,30536,3593,11.8%,724,20.2%,11.0,1837,0.0,11.0,0.6%,26503,8177,14237,53.7,22,174.1
132
+ C,"CITIBANK, N.A.",SD,1696818,170939,10.1%,29115,17.0%,12214.0,158744,11586.0,628.0,7.7%,798104,742961,653192,81.8,4,87.9
133
+ STT,STATE STREET BANK AND TRUST CO,MA,348989,27504,7.9%,2869,10.4%,4280.0,20352,4280.0,0.0,21.0%,207154,236610,203205,98.1,1,85.9
134
+ SF,STIFEL BANK,MO,10790,704,6.5%,57,8.0%,57.0,827,0.0,57.0,6.9%,11126,4477,2011,18.1,132,44.9
135
+ TD,"TD BANK USA, NATIONAL ASSOCIAT",DE,35511,4303,12.1%,216,5.0%,0.0,4436,0.0,-0.0,-0.0%,28465,24462,336,1.2,154,1.4
136
+ SOFI,"SOFI BANK, NATIONAL ASSOCIATIO",UT,31088,4535,14.6%,143,3.2%,0.0,5575,0.0,-0.0,-0.0%,33768,5896,1546,4.6,148,26.2
137
+ BMWKY,BMW BANK OF NORTH AMERICA,UT,12243,1839,15.0%,42,2.3%,28.0,1833,0.0,28.0,1.5%,8069,3018,325,4.0,149,10.8
138
+ SLM,SALLIE MAE BANK,UT,30036,2682,8.9%,50,1.9%,65.0,3063,0.0,65.0,2.1%,20228,5558,1200,5.9,145,21.6
139
+ SYF,SYNCHRONY BANK,UT,111939,13983,12.5%,43,0.3%,8.0,13932,0.0,8.0,0.1%,82569,18289,9235,11.2,140,50.5
140
+ ,THIRD FEDERAL SAVINGS & LOAN A,OH,17047,1719,10.1%,3,0.1%,21.0,1760,0.0,21.0,1.2%,10580,966,387,3.7,150,40.1
141
+ BCS,BARCLAYS BANK DELAWARE,DE,44672,5900,13.2%,8,0.1%,17.0,5242,0.0,17.0,0.3%,37033,9173,2176,5.9,146,23.7
142
+ ,USAA FEDERAL SAVINGS BANK,AZ,109221,3918,3.6%,1,0.0%,3995.0,9166,2778.0,1217.0,43.6%,90797,60313,5481,6.0,144,9.1
143
+ AXP,AMERICAN EXPRESS NATIONAL BANK,UT,193062,18550,9.6%,0,0.0%,8.0,18166,0.0,8.0,-0.0%,168152,47971,37573,22.3,127,78.3
144
+ BAC,"BANK OF AMERICA CALIFORNIA, NA",CA,15691,1802,11.5%,0,0.0%,0.0,1862,0.0,-0.0,-0.0%,12625,4968,728,5.8,147,14.7
145
+ SCHW,"CHARLES SCHWAB PREMIER BANK, S",TX,26472,2159,8.2%,0,0.0%,675.0,3293,516.0,159.0,20.5%,22742,21138,371,1.6,152,1.8
146
+ SCHW,"CHARLES SCHWAB BANK, SSB",TX,275425,19700,7.2%,0,0.0%,11852.0,31514,7772.0,4080.0,37.6%,214260,189160,36451,17.0,134,19.3
147
+ BFH,COMENITY CAPITAL BANK,UT,13263,1855,14.0%,0,0.0%,10.0,1749,0.0,10.0,0.6%,9978,2255,621,6.2,143,27.5
148
+ AMP,"AMERIPRISE BANK, FSB",MN,23605,1137,4.8%,0,0.0%,376.0,1872,0.0,376.0,20.1%,22595,22714,326,1.4,153,1.4
documentation.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Default Cascade Simulation of Banks 2026
2
+
3
+ ## Overview
4
+
5
+ Interactive Dash application that simulates the impact of commercial real estate (CRE) defaults on U.S. bank capitalization. The app classifies banks into regulatory categories under two frameworks — Prompt Corrective Action (PCA) based on Tangible Equity Ratio, and Basel III based on Estimated CET1 Ratio — and displays the results as stacked bar charts with summary metric cards.
6
+
7
+ ## How It Works
8
+
9
+ ### CRE Loss Calculation
10
+
11
+ Each bank's CRE losses are computed as:
12
+
13
+ - `CRE Losses = CRE Total x Default Rate x LGD`
14
+
15
+ When the Unrealized Losses toggle is ON, total losses also incorporate unrealized securities losses (positive values in the data, representing the magnitude of losses).
16
+
17
+ ### Tangible Equity Ratio (PCA Framework)
18
+
19
+ Banks are classified by Adjusted Equity-to-Assets:
20
+
21
+ - `Adjusted Equity-to-Assets = (Total Equity - CRE Losses - Unrealized Losses) / Total Assets`
22
+
23
+ PCA categories:
24
+
25
+ | Category | Threshold |
26
+ |----------|-----------|
27
+ | Well Capitalized | >= 8% |
28
+ | Adequately Capitalized | >= 4% |
29
+ | Undercapitalized | >= 2% |
30
+ | Critically Undercapitalized | >= 0% |
31
+ | Insolvent | < 0% |
32
+
33
+ ### Estimated CET1 Ratio (Basel III Framework)
34
+
35
+ Banks are also classified by Adjusted CET1 Ratio using an estimated Risk-Weighted Assets figure:
36
+
37
+ - `Estimated RWA = Total Assets x RWA Ratio`
38
+ - `Adjusted CET1 = (CET1 Capital - CRE Losses - Unrealized Losses) / Estimated RWA`
39
+
40
+ Basel III categories:
41
+
42
+ | Category | Threshold |
43
+ |----------|-----------|
44
+ | Well Capitalized | >= 6.5% |
45
+ | Undercapitalized | >= 4.5% |
46
+ | Below Basel III Minimum | >= 0% |
47
+ | Insolvent | < 0% |
48
+
49
+ ## Controls
50
+
51
+ | Control | Range | Default | Description |
52
+ |---------|-------|---------|-------------|
53
+ | CRE Default Rate | 0-50% | 10% | Percentage of CRE portfolio that defaults |
54
+ | Loss Given Default | 0-100% | 50% | Loss severity on defaulted loans |
55
+ | Average RWA Ratio | 50-75% | 65% | Assumed ratio of risk-weighted assets to total assets |
56
+ | Total Assets | $10-100B | $10B | Minimum bank size filter |
57
+ | Unrealized Losses | ON/OFF | OFF | Include unrealized securities losses in stress calculation |
58
+ | Has CRE Losses | ON/OFF | OFF | Exclude banks with zero CRE exposure |
59
+ | Publicly Traded Only | ON/OFF | OFF | Exclude non-publicly traded banks |
60
+
61
+ ## Display
62
+
63
+ ### Stacked Bar Charts
64
+
65
+ Two horizontal stacked bar charts show the count of banks in each capitalization category:
66
+
67
+ - **Tangible Equity Ratio** — Five-shade red bar (PCA categories)
68
+ - **Estimated CET1 Ratio** — Four-shade purple bar (Basel III categories)
69
+
70
+ ### Metric Cards
71
+
72
+ Each framework displays three summary cards:
73
+
74
+ | Metric | Description |
75
+ |--------|-------------|
76
+ | Total Losses | Aggregate CRE losses (plus unrealized if toggled) across all filtered banks, in $B |
77
+ | Banks Undercapitalized / Below Minimum | Count of banks falling below the adequately capitalized threshold, with their combined total assets |
78
+ | Banks Insolvent | Count of banks with negative adjusted ratios, with their combined total assets |
79
+
80
+ ## Data Source
81
+
82
+ [The Banking Initiative at Florida Atlantic University](https://business.fau.edu/departments/finance/banking-initiative/) — Q3 2025 FFIEC Call Reports.
83
+
84
+ ## Run Locally
85
+
86
+ ```bash
87
+ pip install -r requirements.txt
88
+ python app.py
89
+ # Open http://localhost:8050
90
+ ```
91
+
92
+ ## Customization
93
+
94
+ You can use this app with your own data by replacing the `data.csv` file. Your CSV must include the following columns in the same format:
95
+
96
+ | Column | Description | Example |
97
+ |--------|-------------|---------|
98
+ | `Ticker` | Stock ticker symbol (blank for non-public banks) | `JPM` |
99
+ | `Name` | Bank name | `JPMORGAN CHASE BANK` |
100
+ | `ST` | State abbreviation | `NY` |
101
+ | `Total Assets ($M)` | Total assets in millions | `3459261` |
102
+ | `Total Equity ($M)` | Total equity in millions | `312794` |
103
+ | `CRE Total ($M)` | Commercial real estate exposure in millions | `174381` |
104
+ | `CET1 Capital ($M)` | Common Equity Tier 1 capital in millions | `291288` |
105
+ | `Total Unrealized Loss ($M)` | Unrealized loss on investment securities in millions (positive values) | `1842` |
106
+ | `Price` | Latest stock closing price in dollars | `293.70` |
107
+ | `Volume` | Average 30-day trading volume | `44276127` |
108
+ | `Volatility` | 30-day annualized volatility as percentage | `26.0` |
109
+
110
+ Only banks with a non-blank `Ticker` and valid `Price` and `Volatility` values will be included in the simulation. All other columns in the CSV are ignored by this app but may be used by companion apps in the Signalpha suite.
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ dash>=2.17
2
+ plotly>=5.22
3
+ pandas>=2.0
4
+ gunicorn>=22.0