merton.extensions.geske

Geske (1977) compound-option pricing for multi-tranche debt.

When a firm has a layered debt schedule (e.g. short-term and long-term liabilities maturing at distinct dates t_1 < t_2), equity is no longer a single call on assets — it is a call on a call. At t_1 the equity holders must either roll the short-term debt by paying D_1 (which requires the residual call on the long-term debt to be worth at least D_1) or walk away. Geske (1977) derives the closed-form value of this compound option using the bivariate-normal CDF.

Two-period formula

Let A_t follow geometric Brownian motion with drift r - q and volatility σ_A under the risk-neutral measure. Suppose D_1 is due at t_1 and D_2 at t_2 > t_1. Define A^* as the asset value at t_1 that makes the residual call on the long-term debt exactly worth D_1:

\[C\bigl(A^*; D_2, t_2 - t_1, r, \sigma_A, q\bigr) = D_1.\]

This is a 1-D root-finding problem.

Define the standard BSM helpers

\[\begin{split}d_1^{(i)} &= \frac{\ln(A_0/X_i) + (r - q + \tfrac{1}{2}\sigma_A^2)\,t_i}{\sigma_A \sqrt{t_i}}, \\ d_2^{(i)} &= d_1^{(i)} - \sigma_A \sqrt{t_i}, \\ \rho &= \sqrt{t_1/t_2},\end{split}\]

with X_1 = A^* (for the inner call at t_1) and X_2 = D_2 (for the outer call at t_2). The Geske compound-call value is then

\[E_0 = A_0 e^{-q t_2}\, \Phi_2\!\bigl(d_1^{(1)}, d_1^{(2)};\,\rho\bigr) - D_2 e^{-r t_2}\, \Phi_2\!\bigl(d_2^{(1)}, d_2^{(2)};\,\rho\bigr) - D_1 e^{-r t_1}\, \Phi\!\bigl(d_2^{(1)}\bigr),\]

where Φ_2(·,·; ρ) is the bivariate-normal CDF with correlation ρ.

The risk-neutral default probability at t_2 is Φ_2(-d_2^{(1)}, -d_2^{(2)}; ρ) plus the probability of default at t_1 alone, Φ(-d_2^{(1)}). For a clean PD over [0, t_2] we sum these contributions.

References

Geske, R. (1977). The Valuation of Corporate Liabilities as Compound Options. Journal of Financial and Quantitative Analysis 12 (4), 541-552.

Classes

GeskeModel

Two-period Geske compound-option calibration.

Functions

geske_equity_value(→ float)

Geske two-period equity value.

geske_pd(→ float)

Total risk-neutral PD over [0, t_long] in the Geske 2-period setup.

Module Contents

merton.extensions.geske.geske_equity_value(*, asset_value: float, asset_vol: float, debt_short: float, debt_long: float, t_short: float, t_long: float, rf: float, dividend_yield: float = 0.0) float[source]

Geske two-period equity value.

Parameters:
  • asset_value – Current firm asset value and asset volatility.

  • asset_vol – Current firm asset value and asset volatility.

  • debt_short – Liability tranches due at t_short and t_long respectively.

  • debt_long – Liability tranches due at t_short and t_long respectively.

  • t_short – Maturities (years). Must satisfy 0 < t_short < t_long.

  • t_long – Maturities (years). Must satisfy 0 < t_short < t_long.

  • rf – Risk-free rate and continuous dividend yield.

  • dividend_yield – Risk-free rate and continuous dividend yield.

merton.extensions.geske.geske_pd(*, asset_value: float, asset_vol: float, debt_short: float, debt_long: float, t_short: float, t_long: float, rf: float, dividend_yield: float = 0.0) float[source]

Total risk-neutral PD over [0, t_long] in the Geske 2-period setup.

PD(t_long) = PD(default at t_1)  + PD(default at t_2 | survived t_1)

The first is Φ(-d_2^{(1)}) (single-call PD at the inner strike). The second is Φ_2(-d_2^{(1)}, -d_2^{(2)}; ρ) — survival to t_1 and failure at t_2.

class merton.extensions.geske.GeskeModel(*, t_short: float = 1.0, recovery_rate: float = 0.5, tol: float = 1e-08, max_iter: int = 200)[source]

Bases: merton.extensions.base.StructuralModel

Two-period Geske compound-option calibration.

Equity is treated as a compound call: at t_1 shareholders pay D_1 only if the residual call (on long-term debt due at t_2) is worth more than D_1. We infer (A, σ_A) from observed equity and equity vol by inverting the Geske equity formula numerically.

Inputs

t_short, t_long

Maturity dates (years). The Firm’s horizon is interpreted as t_long by default; pass t_short explicitly to override.

method = 'geske'[source]
t_short[source]
recovery_rate[source]
tol = 1e-08[source]
max_iter = 200[source]
fit(firm: merton.core.firm.Firm) merton.extensions.base.StructuralResult[source]

Return a StructuralResult for firm.