Single-file Flask web app for structural (Merton/BSM) equity analysis.
Given observable equity inputs, it calibrates firm assets ((V_A,\sigma_A)), computes deep risk/credit metrics, and produces scenario charts and a Monte-Carlo distribution for the per-share price at the analysis horizon (T).
- Calibrates asset value and asset volatility from ((E,\sigma_E)) via a robust outer/inner bisection (no SciPy).
- Computes:
- (d_1,d_2), distance-to-default ( \mathrm{DD}=d_2 ), PD (=\Phi(-d_2))
- Delta and equity elasticity ( \Delta \cdot V/E )
- Risky debt (D_0=V_A-E), credit spread (s) from (D_0=K e^{-(r+s)T})
- Hazard proxy ( \lambda \approx \phi(d_2)/(\sqrt{T},\Phi(-d_2)) )
- Monte-Carlo under ( \mathbb{Q} ) for the terminal per-share price (P_T) with configurable paths.
- Dark UI with PD dial, scenario bars (5/50/95) and distribution histogram.
Security-conscious by default: strict CSP with per-request nonce, safe headers, no debug mode, and zero third-party Python deps beyond Flask and numpy (Chart.js is loaded from a CDN).
- Stock Price (P_0) and Shares Outstanding (N_{\mathrm{sh}}) → equity value (E = P_0 N_{\mathrm{sh}})
- Total Debt Face (K) (millions), Cash (display only)
- Equity Volatility (\sigma_E) (%)
- Risk-free rate (r) (%) and Asset payout (q=\delta) (%)
- Horizon (T) (years)
- Monte Carlo Paths (1k–200k)
- Calibrated (V_A) (firm assets), (\sigma_A)
- DD (d_2), PD (\Phi(-d_2)), status bucket (weak/moderate/strong)
- Elasticity ( \Delta \cdot V/E )
- Risky debt (D_0) and credit spread (s)
- Hazard proxy (\lambda)
- Per-share now (E/N_{\mathrm{sh}})
Charts
- Scenarios: 5% (“terrible”), 50% (baseline), 95% (“all goes well”) for (P_T)
- Histogram: empirical distribution of (P_T)
Requires Python 3.9+ (tested with 3.10/3.11).
# clone your repo / copy these files into a folder
python -m venv env
source env/bin/activate # Windows: env\Scripts\activate
pip install -r requirements.txtpython StockAssessor.py
# opens http://127.0.0.1:5000To run on a different port:
PORT=8000 python StockAssessor.pyProduction (optional) behind a reverse proxy:
# inside the venv
gunicorn -w 2 -b 127.0.0.1:5000 StockAssessor:app-
Equity as call on assets with carry
$q$ :$$ E = V e^{-qT}\Phi(d_1) - K e^{-rT}\Phi(d_2),\quad d_1=\frac{\ln(V/K)+(r-q+\tfrac12\sigma_A^2)T}{\sigma_A\sqrt{T}},; d_2=d_1-\sigma_A\sqrt{T}. $$
-
Mapping $ \sigma_E = (\partial E/\partial V),(V/E),\sigma_A$.
-
Calibration: bisection on
$\sigma_A$ (outer), with a bisection on$V$ (inner) to match$E_{\text{obs}}$ . -
Monte-Carlo (risk-neutral):
$$ V_T = V_0 \exp!\big((r-q-\tfrac12\sigma_A^2)T + \sigma_A\sqrt{T}Z\big),; Z\sim\mathcal N(0,1),; P_T = \max(V_T-K,0)/N_{\mathrm{sh}}. $$
- The app sends no data off-box; Chart.js is fetched from JSDelivr. For offline use, vendor the JS file and change the
<script>tag. - Keep any Internet-facing deployment behind TLS and a reverse proxy. Add CSRF/auth if you enable stateful features.
-
“Could not bracket sigma_A for calibration”
Inputs imply contradictory
$E,\sigma_E$ . Check$K$ ,$T$ , or$\sigma_E$ . - “… out of bounds …” A field is outside allowed ranges; adjust the value.
- Blank charts You haven’t run Calibrate & Analyze yet, or the request failed validation.
MertonPredictor/
├── ReadMePic.png
├── StockAssessor.py
└── requirements.txt
This tool is for research/education. It is not investment advice.
---
# `requirements.txt`
```txt
# minimal, reproducible
Flask==3.0.0
numpy==1.26.4
# optional: for production serving (not used when running python StockAssessor.py)
gunicorn==21.2.0
If you prefer unpinned deps, swap the first two lines for:
Flask>=3.0,<4
numpy>=1.24,<3
Want a “Download report (CSV/PNG)” button next? I can add it without touching your calibration logic.
