A company’s capital structure is fundamental to its operations and strategic planning, dictating the resources available and their origins. This structure is primarily composed of debt and equity, and finding the right balance between these two is crucial for maximizing firm value and profitability.
The groundbreaking work of Modigliani and Miller (MM) provided foundational insights into capital structure.
MM Proposition I (No Taxes): Irrelevance of Capital Structure
In a perfect market with no taxes, no transaction costs, no bankruptcy costs, and where information is freely available to everyone, the value of a company is unaffected by how it is financed. Whether a firm uses debt, equity, or some combination, its total market value remains the same. This value is determined by the earning power of its assets and its investment decisions, not by its financing mix.
The logic is that investors can create their own leverage or undo corporate leverage. If a levered firm were valued more highly than an unlevered firm with identical operating earnings, investors could sell shares in the levered firm, borrow on personal account to replicate the levered firm’s debt/equity ratio, and buy shares in the unlevered firm, thereby earning a higher return with no additional risk. This arbitrage process would drive the values of the two firms to equality.
Similarly, if the unlevered firm had a higher value, investors holding its shares could sell some, lend a portion of the proceeds at the same rate the levered firm pays on its debt, and use the rest to buy shares in the levered firm, again achieving a higher return for the same risk, or the same return for lower risk.
MM Proposition II (No Taxes): Cost of Equity and Leverage
While the overall cost of capital (and thus firm value) is unaffected by leverage in a no-tax world, the cost of equity does increase with leverage. As a firm takes on more debt, its equity becomes riskier because debtholders have a prior claim on earnings. Equityholders, therefore, demand a higher return to compensate for this increased risk.
The increase in the cost of equity precisely offsets the benefit of using cheaper debt (assuming debt is less risky than equity), keeping the Weighted Average Cost of Capital (WACC) constant.
Introducing Corporate Taxes: The Value of Debt
When corporate taxes are introduced, the MM propositions change. Interest paid on debt is typically tax-deductible, creating a “tax shield” that reduces the firm’s tax liability. This tax shield has value, and it increases the total value of the levered firm compared to an unlevered firm.
The value of a levered firm (\(V_L\)) becomes: \(V_L = V_U + T_C \times D\) Where: * \(V_U\) is the value of the unlevered firm * \(T_C\) is the corporate tax rate * \(D\) is the market value of debt
This implies that, in a world with only corporate taxes, a firm can maximize its value by being 100% debt-financed. However, this doesn’t consider other market imperfections like bankruptcy costs.
The WACC is the average rate of return a company needs to earn to satisfy all its investors (both debt and equity holders). It’s a common discount rate used in capital budgeting.
WACC Formula (No Taxes)
\(r_{WACC} = r_E \times \frac{E}{V} + r_D \times \frac{D}{V}\) Where: * \(r_E\) = Cost of equity * \(r_D\) = Cost of debt * \(E\) = Market value of equity * \(D\) = Market value of debt * \(V = E + D\) = Total market value of the firm
WACC Formula (With Corporate Taxes)
The tax deductibility of interest payments reduces the effective cost of debt. \(r_{WACC} = r_E \times \frac{E}{V} + r_D \times (1 - T_C) \times \frac{D}{V}\)
OK, first let’s get the financial statements:
import yfinance as yf
def fetch_financials(ticker):
"""
Returns a dict with:
- info: Ticker.info
- balance_sheet: Ticker.balance_sheet
- financials: Ticker.financials
- cashflow: Ticker.cashflow
"""
= yf.Ticker(ticker)
tk return {
"info": tk.info,
"balance_sheet": tk.balance_sheet,
"financials": tk.financials,
"cashflow": tk.cashflow
}
# Example:
= fetch_financials("AMZN")
data print(data["info"]["marketCap"], data["balance_sheet"].head())
Now, we can do WACC:
import yfinance as yf
import pandas as pd
def calculate_wacc(ticker, risk_free_rate, market_return, corporate_tax_rate, assumed_debt_yield=0.05):
"""
Fetches financials for `ticker` and computes WACC, using fallbacks if any key item is NaN.
Fallback rules:
- marketCap: if NaN, approximate as sharesOutstanding * previousClose
- Debt rows: if missing or NaN, treated as 0
- beta: if NaN or missing, default to 1.0
- interest expense: if missing or NaN, approximate = total_debt * assumed_debt_yield
- cost of debt r_D: if computed interest==0 or debt==0, fallback to risk_free_rate
"""
= yf.Ticker(ticker)
tk = tk.info
info = tk.balance_sheet
bs = tk.financials
fs
# 1) Equity value
= info.get("marketCap", pd.NA)
E if pd.isna(E):
= info.get("sharesOutstanding", pd.NA)
so = info.get("previousClose", pd.NA)
pc if not pd.isna(so) and not pd.isna(pc):
= so * pc
E else:
= 0 # no better proxy
E
# 2) Debt: long + short (treat missing as 0)
= bs.loc["Long Term Debt"][0] if "Long Term Debt" in bs.index else 0
D_lt = bs.loc["Short Term Debt"][0] if "Short Term Debt" in bs.index else 0
D_st = 0 if pd.isna(D_lt) else D_lt
D_lt = 0 if pd.isna(D_st) else D_st
D_st = D_lt + D_st
D
= E + D
V if V == 0:
= 1 # avoid division by zero
V
# 3) Cost of Equity via CAPM (beta fallback to 1.0)
= info.get("beta", pd.NA)
beta if pd.isna(beta):
= 1.0
beta = risk_free_rate + beta * (market_return - risk_free_rate)
r_E
# 4) Cost of Debt
# Try actual interest expense
if "Interest Expense" in fs.index:
= fs.loc["Interest Expense"][0]
interest = abs(interest) if not pd.isna(interest) else pd.NA
interest else:
= pd.NA
interest
# Fallback for interest expense
if pd.isna(interest):
= D * assumed_debt_yield
interest
# Compute r_D, fallback to risk-free if impossible
if D > 0:
= interest / D
r_D if pd.isna(r_D) or r_D <= 0:
= risk_free_rate
r_D else:
= risk_free_rate
r_D
# 5) WACC
= (r_E * E / V) + (r_D * (1 - corporate_tax_rate) * D / V)
wacc
return {
"r_E": r_E,
"r_D": r_D,
"E": E,
"D": D,
"WACC": wacc
}
# Example:
= calculate_wacc("AMZN", risk_free_rate=0.02, market_return=0.07, corporate_tax_rate=0.21)
metrics print(metrics)
Market Values vs. Book Values: When calculating WACC, it’s crucial to use market values for debt and equity, not their book values (historical costs). Market values reflect current investor expectations and the true economic value of the firm’s assets.
Net Debt and Enterprise Value: Sometimes, WACC calculations use net debt, which is total debt minus cash and risk-free securities. The logic is that interest earned on cash can offset interest paid on debt. \(D_{Net} = D - Cash\)
Enterprise Value (\(V_E\)) is the market value of equity plus net debt: \(V_E = E + D_{Net}\)
The weights in the WACC formula can then be \(E/V_E\) and \(D_{Net}/V_E\).
import yfinance as yf
import pandas as pd
def calculate_net_debt(ticker):
"""
Fetches total debt (long + short) and cash & equivalents for `ticker`,
treats any missing/NaN values as zero, and returns net debt.
"""
= yf.Ticker(ticker)
tk = tk.balance_sheet
bs
# Long-term debt
if "Long Term Debt" in bs.index:
= bs.loc["Long Term Debt"][0]
D_lt = 0 if pd.isna(D_lt) else D_lt
D_lt else:
= 0
D_lt
# Short-term debt
if "Short Term Debt" in bs.index:
= bs.loc["Short Term Debt"][0]
D_st = 0 if pd.isna(D_st) else D_st
D_st else:
= 0
D_st
= D_lt + D_st
total_debt
# Cash & equivalents
if "Cash" in bs.index:
= bs.loc["Cash"][0]
cash = 0 if pd.isna(cash) else cash
cash else:
= 0
cash
return total_debt - cash
def calculate_enterprise_value(ticker):
"""
Fetches market equity and net debt for `ticker`,
approximates market equity if missing, then returns enterprise value.
"""
= yf.Ticker(ticker)
tk = tk.info
info
# Market value of equity
= info.get("marketCap", pd.NA)
E if pd.isna(E):
# fallback: sharesOutstanding * previousClose
= info.get("sharesOutstanding", pd.NA)
so = info.get("previousClose", pd.NA)
pc if not pd.isna(so) and not pd.isna(pc):
= so * pc
E else:
= 0
E
# Net debt via our function above
= calculate_net_debt(ticker)
net_debt
return E + net_debt
# Example usage:
= calculate_net_debt("AMZN")
net_debt_val = calculate_enterprise_value("AMZN")
ev_val print(f"Net Debt: {net_debt_val}")
print(f"Enterprise Value: {ev_val}")
Payout policy concerns how a firm returns cash to its shareholders. The main methods are cash dividends and share repurchases.
MM Dividend Irrelevance Proposition: In perfect capital markets (no taxes, no transaction costs), a firm’s dividend policy is irrelevant to its value. Shareholders are indifferent between receiving dividends and having the firm retain earnings (which should lead to capital gains). If a shareholder desires cash, they can sell shares. If they prefer to reinvest, they can use dividends to buy more shares.
Consider a firm with earnings \(I\). Let \(d_t\) be dividends at time \(t\), \(D_t\) be borrowings at time \(t\), \(L\) be investment at time 1, and \(r\) be the risk-free rate. The firm’s sources and uses of funds mean: \(I_1 + D_1 = d_1 + L\) So, borrowings \(D_1 = d_1 + L - I_1\).
Returns at time 2 (\(I_2\)) are used to pay dividends at time 2 (\(d_2\)) and repay debt \(D_1(1+r)\): \(I_2 = d_2 + D_1(1+r)\) Therefore, dividends at time 2 are: \(d_2 = I_2 - (d_1 + L - I_1)(1+r)\)
An investor owning a fraction \(\alpha\) of the equity has a budget constraint across two periods: \(c_1 + \frac{c_2}{(1+r)} = e_1 + \alpha d_1 + \frac{e_2}{(1+r)} + \alpha \frac{d_2}{(1+r)}\) Where \(c_t\) is consumption at time \(t\) and \(e_t\) is other income at time \(t\). Substituting the expression for \(d_2\): \(c_1 + \frac{c_2}{(1+r)} = e_1 + \alpha d_1 + \frac{e_2}{(1+r)} + \alpha \frac{I_2 - (d_1 + L - I_1)(1+r)}{(1+r)}\) \(c_1 + \frac{c_2}{(1+r)} = e_1 + \alpha d_1 + \frac{e_2}{(1+r)} + \frac{\alpha I_2}{(1+r)} - \alpha (d_1 + L - I_1)\) \(c_1 + \frac{c_2}{(1+r)} = e_1 + \frac{e_2}{(1+r)} + \frac{\alpha I_2}{(1+r)} + \alpha I_1 - \alpha L\) The dividend \(d_1\) cancels out, showing the shareholder’s consumption possibilities (and thus wealth) are independent of the dividend policy.
Types of Dividend Policies: * Constant-Payout-Ratio Policy: The firm pays a constant percentage of its earnings as dividends. This leads to fluctuating dividends if earnings fluctuate. * Regular Dividend Policy: The firm pays a fixed dollar dividend in each period. This provides shareholders with stable income. Companies usually increase this regular dividend only when confident that earnings have permanently increased. * Low-Regular-and-Extra Dividend Policy: The firm pays a low regular dividend plus an extra dividend in times of high earnings. This offers some stability while allowing shareholders to benefit from good performance.
Share Repurchases: A firm can buy back its own shares from the market. This reduces the number of outstanding shares, which can: * Increase earnings per share (EPS). * Signal management’s confidence that the stock is undervalued. * Provide a temporary support for the stock price. From a shareholder’s perspective, in a perfect market, receiving a cash dividend or having the firm repurchase shares (leading to a higher stock price) should be equivalent before considering taxes.
Stock Splits: A stock split increases the number of shares outstanding by giving existing shareholders additional shares for each share they own (e.g., a 2-for-1 split means one old share becomes two new shares, each worth half the original). This lowers the per-share price, potentially increasing its trading liquidity. It does not directly affect the firm’s capital structure or total market value.
While MM propositions are powerful, they rely on strict assumptions. Relaxing these assumptions leads to other theories.
1. Static Trade-Off Theory: This theory posits that firms choose a target debt-to-equity ratio by balancing the benefits of debt (primarily the tax shield) against the costs of debt (costs of financial distress and bankruptcy). * Benefit of Debt: Tax savings from interest deductibility. * Costs of Debt: * Direct bankruptcy costs: Legal and administrative costs of bankruptcy. * Indirect bankruptcy costs: Loss of customers, suppliers, employees; difficulty obtaining credit; managers acting overly cautiously. The optimal capital structure is where the marginal benefit of the tax shield from an additional dollar of debt equals the marginal cost of the increased probability of financial distress.
Value of Levered Firm = Value of Unlevered Firm + PV(Tax Shield) - PV(Costs of Financial Distress)
2. Pecking Order Hypothesis: This theory focuses on the information asymmetry between managers (who know more about the firm’s prospects) and outside investors. It suggests a hierarchy of financing choices: 1. Internal Funds (Retained Earnings): Firms prefer to finance investments with internally generated funds first because it avoids the discipline and scrutiny of outside markets and signals nothing negative. 2. Debt: If internal funds are insufficient, firms will issue debt. Debt is preferred over equity because it is generally perceived as less risky by investors and thus less subject to undervaluation due to information asymmetry. Issuing debt is seen as a less negative signal than issuing equity. 3. Equity: Firms issue equity only as a last resort. Issuing equity is often interpreted by the market as a signal that management believes the firm’s shares are overvalued, or that the firm is in trouble, leading to a drop in stock price.
The pecking order theory implies that firms don’t have a specific target debt-equity ratio. Instead, their leverage ratio reflects their cumulative need for external financing over time. Profitable firms with fewer investment opportunities will tend to have lower debt ratios.
3. Adjusted Present Value (APV) The APV method is an alternative valuation approach that separates the value of a project’s operating cash flows from the value of financing side effects.
APV = Base-Case NPV + PV(Financing Side Effects)
The basic Net Present Value (NPV) for a project is: \(NPV = \sum_{t=1}^{N} \frac{C_t}{(1+r_{WACC})^t} + \frac{TV_N}{(1+r_{WACC})^N} - C_0\) Where \(C_t\) is expected after-tax cash flow, \(TV_N\) is terminal value, and \(C_0\) is initial investment.
Incremental cash flow for a period \(t\) (\(C_t\)) can be expressed as: \(C_t = NI_t + Dep_t + I_t(1 - T_C)\) Where \(NI_t\) is net income, \(Dep_t\) is depreciation, and \(I_t\) is interest expense. This can also be written as: \(C_t = C_t^{OP}(1 - T_C) + T_C Dep_t\) Where \(C_t^{OP}\) is operating cash flow (before interest and taxes).
The value of a levered firm (\(V_L\)) in the presence of corporate taxes (from MM) is: \(V_L = V_U + T_C \times DBT_t\) Where \(DBT_t\) is debt at time \(t\).
The APV formula explicitly incorporates these components: \(APV = \left( \sum_{t=1}^{N} \frac{FCF_t}{(1+r_U)^t} + \frac{TV_{U,N}}{(1+r_U)^N} - C_0 \right) + \sum_{t=1}^{N} \frac{T_C \times I_t}{(1+r_D)^t}\) Or more generally: \(APV = \sum_{t=1}^{N} \frac{C_t^{OP}(1-T_C)}{(1+r_E)^t} + \sum_{t=1}^{N} \frac{T_C Dep_t}{(1+r_U)^t} + \sum_{t=1}^{N} \frac{T_C I_t}{(1+r_D)^t} - C_0\) Here, \(FCF_t\) are free cash flows to the unlevered firm. The first term is the value if all-equity financed. The second term is the PV of the interest tax shield, often discounted at the cost of debt (\(r_D\)) or sometimes \(r_U\) if the debt level is fixed. \(C_t^{OP}(1-T_C)\) would be discounted at \(r_U\) (cost of equity for unlevered firm). The tax shield from depreciation is sometimes discounted at \(r_U\) or \(r_D\). The cost of equity \(r_E\) in the provided formula would typically be \(r_U\) for the operating cash flows of an unlevered base case.
import yfinance as yf
import pandas as pd
def calculate_apv(ticker, cost_of_equity_unlevered, cost_of_debt, corporate_tax_rate, initial_investment):
"""
Fetches financials for `ticker` and calculates APV:
1. Unlevered FCF = Operating CF − CapEx
2. PV(Unlevered FCF) @ cost_of_equity_unlevered
3. PV(Terminal Value) @ cost_of_equity_unlevered (assume last FCF × (1+g)/ (r−g), or user-supplied)
4. PV of Interest Tax Shield @ cost_of_debt
5. PV of Depreciation Tax Shield @ cost_of_debt
6. APV = PV(Unlevered FCF) + PV(TV) − initial_investment + PV(Interest shield) + PV(Depreciation shield)
"""
= yf.Ticker(ticker)
tk = tk.cashflow.fillna(0)
cf = tk.financials.fillna(0)
fin
# 1) Unlevered FCFs
= cf.loc["Operating Cash Flow"].values
op_cf = abs(cf.loc["Capital Expenditure"].values)
capex = op_cf - capex
unlevered_fcf = len(unlevered_fcf)
periods
# 2) PV of Unlevered FCF
= sum(
pv_unlevered / (1 + cost_of_equity_unlevered) ** (i + 1)
unlevered_fcf[i] for i in range(periods)
)
# 3) Terminal Value (TV) using perpetual growth g=0 (simplest)
= unlevered_fcf[-1] if periods > 0 else 0
last_fcf = last_fcf / cost_of_equity_unlevered # g=0
tv = tv / (1 + cost_of_equity_unlevered) ** periods
pv_tv
# 4) PV of Interest Tax Shield
= abs(fin.loc["Interest Expense"].values) if "Interest Expense" in fin.index else pd.Series([0]*periods)
interest = sum(
pv_interest_shield * corporate_tax_rate) / (1 + cost_of_debt) ** (i + 1)
(interest[i] for i in range(periods)
)
# 5) PV of Depreciation Tax Shield
= cf.loc["Depreciation"].values if "Depreciation" in cf.index else [0]*periods
depreciation = sum(
pv_depr_shield * corporate_tax_rate) / (1 + cost_of_debt) ** (i + 1)
(depreciation[i] for i in range(periods)
)
# 6) APV
= pv_unlevered + pv_tv - initial_investment + pv_interest_shield + pv_depr_shield
apv return apv
# Example usage:
= calculate_apv("AMZN", cost_of_equity_unlevered=0.10, cost_of_debt=0.05, corporate_tax_rate=0.21, initial_investment=1_000_000)
apv_val print(f"APV: {apv_val:,.2f}")
The APV formula can be represented as: \(APV=\sum_{t=1}^{N}\frac{C_{t}^{OP}(1-\tau_{C})}{(1+r_{E})^{t}}+\sum_{t=1}^{N}\frac{\tau_{C}D_{t}}{(1+r_{D})^{t}}+\sum_{t=1}^{N}\frac{\tau_{C}I_{t}}{(1+r_{D})^{t}}+\frac{TV_{N}}{(1+r_{E})^{N}}-C_{0}\) Where \(r_U\) is the cost of capital for an all-equity firm (unlevered cost of equity).
4. Tax-Based Theories (Considering Personal Taxes) Miller (1977) extended the MM framework to include personal taxes on equity income (\(\tau_E\) - from dividends and capital gains) and debt income (\(\tau_D\) - from interest).
The value of a levered firm (\(V_L\)) relative to an unlevered firm (\(V_U\)) becomes: \(V_L = V_U + \left[1 - \frac{(1 - T_C)(1 - \tau_E)}{(1 - \tau_D)}\right] D\)
Key Implications: * If there are no taxes (\(T_C = \tau_E = \tau_D = 0\)), then \(V_L = V_U\) (MM Proposition I). * If there are only corporate taxes (\(\tau_E = \tau_D = 0\)), then \(V_L = V_U + T_C D\) (MM with corporate taxes). * Debt Advantage Disappears if: \((1 - T_C)(1 - \tau_E) = (1 - \tau_D)\). In this scenario, the after-tax income to investors from equity (routed through the corporation) equals the after-tax income from debt. Capital structure again becomes irrelevant. * Debt is Preferred if: \((1 - \tau_D) > (1 - T_C)(1 - \tau_E)\). This means the net return to investors from debt is higher than from equity. Firms would tend towards all-debt financing. * Equity is Preferred if: \((1 - \tau_D) < (1 - T_C)(1 - \tau_E)\). Firms would tend towards all-equity financing.
Consider an all-debt firm with income \(X\): Net payoff to investors = \(X (1 - \tau_D)\) (since corporate tax is zero due to full interest deductibility).
Consider an all-equity firm with income \(X\): Net income after corporate tax = \(X (1 - T_C)\). Net payoff to investors after personal equity tax = \(X (1 - T_C)(1 - \tau_E)\).
The optimal capital structure depends on the relative magnitudes of these payoffs.
import yfinance as yf
import pandas as pd
def mm_with_personal_taxes_gain_from_leverage(ticker, corporate_tax_rate, personal_tax_rate_equity, personal_tax_rate_debt):
"""
Fetches total debt for `ticker` (long + short, NaNs → 0), then computes:
Gain = [1 - ((1 − Tc)(1 − Te)) / (1 − Td)] × D
Handles the Td=1 case by returning 0 gain.
"""
= yf.Ticker(ticker)
tk = tk.balance_sheet
bs
# long‐term debt
if "Long Term Debt" in bs.index:
= bs.loc["Long Term Debt"][0]
D_lt = 0 if pd.isna(D_lt) else D_lt
D_lt else:
= 0
D_lt
# short‐term debt
if "Short Term Debt" in bs.index:
= bs.loc["Short Term Debt"][0]
D_st = 0 if pd.isna(D_st) else D_st
D_st else:
= 0
D_st
= D_lt + D_st
D
# Avoid division by zero when Td == 1
if personal_tax_rate_debt >= 1:
return 0.0
= 1 - ((1 - corporate_tax_rate) * (1 - personal_tax_rate_equity)) / (1 - personal_tax_rate_debt)
gain_factor return gain_factor * D
# Example usage:
# Gain from leverage for Tesla with Tc=21%, Te=15%, Td=25%:
= mm_with_personal_taxes_gain_from_leverage("AMZN", 0.21, 0.15, 0.25)
gain print(f"Gain from leverage (V_L - V_U): {gain:,.2f}")
RAROC is a risk-adjusted performance measure, particularly used in financial institutions, to evaluate profitability in relation to the economic capital required to support the associated risks.
\(RAROC = \frac{\text{Adjusted Net Income}}{\text{Economic Capital}} = \frac{R - C - E_L}{E_C}\) Where: * \(R\) = Revenues * \(C\) = Costs * \(E_L\) = Expected Losses * \(E_C\) = Economic Capital * Adjusted Net Income (\(A_{NI}\)) = \(R - C - E_L\)
For a bank loan, Adjusted Net Income (\(A_{NI}\)) might be: \(A_{NI} = I - E_L - C_O\) Where: * \(I\) = Financial Income (e.g., interest from the loan) * \(E_L\) = Expected Loss (from default on the loan) * \(C_O\) = Operating Costs (associated with servicing the loan) This can be adjusted for taxes: \(A_{NI, \text{post-tax}} = (I - E_L - C_O)(1 - T_C)\).
Use of NOPAT: By taking
(rev – cogs – opex) × (1–Tc)
, we can approximate a
business’s operating earnings after tax, rather than
starting from interest income minus loan losses, which is more typical
for a bank’s RAROC. (a pragmatic proxy for RAROC, specifically
NOPAT / Economic Capital, used when detailed “Expected Losses”
(EL) are not readily available)
RAROC and CAPM: RAROC can be linked to the Capital Asset Pricing Model (CAPM). The CAPM defines the expected return on an asset (\(R_i\)): \(R_i = R_f + \beta_i (R_m - R_f)\) Where: * \(R_f\) = Risk-free rate * \(R_m\) = Expected return on the market portfolio * \(\beta_i\) = Beta of the asset, a measure of its systematic risk.
Beta (\(\beta_i\)) is calculated as: \(\beta_i = \frac{\text{Cov}(R_i, R_m)}{\text{Var}(R_m)} = \frac{\sigma_{im}}{\sigma_m^2} = \frac{\rho_{im} \sigma_i \sigma_m}{\sigma_m^2} = \frac{\rho_{im} \sigma_i}{\sigma_m}\) Where: * \(\sigma_{im}\) = Covariance between asset \(i\)’s return and market return * \(\sigma_m^2\) = Variance of the market return * \(\rho_{im}\) = Correlation coefficient between asset \(i\) and the market * \(\sigma_i\) = Standard deviation of asset \(i\)’s return * \(\sigma_m\) = Standard deviation of market return
Substituting beta into the CAPM equation: \(R_i = R_f + \frac{\rho_{im} \sigma_i}{\sigma_m} (R_m - R_f)\) Rearranging: \(R_i - R_f = \frac{\rho_{im} \sigma_i}{\sigma_m} (R_m - R_f)\) \(\frac{R_i - R_f}{\rho_{im} \sigma_i} = \frac{R_m - R_f}{\sigma_m}\)
The left-hand side, \(\frac{R_i - R_f}{\rho_{im} \sigma_i}\), represents the risk-adjusted return (excess return per unit of correlated risk) for asset \(i\), which is analogous to RAROC. The right-hand side, \(\frac{R_m - R_f}{\sigma_m}\), is the market Sharpe Ratio or the market price of risk (excess return per unit of market risk). This equation implies that, in equilibrium, the risk-adjusted return for any asset should be proportional to the market price of risk. For a project to be acceptable, its RAROC should typically exceed a hurdle rate, which is often related to the market price of risk or the firm’s overall cost of capital.
import yfinance as yf
import pandas as pd
def calculate_beta(ticker, market_ticker="^GSPC", period="1y", interval="1d"):
"""
Calculates beta of `ticker` relative to `market_ticker`.
"""
= yf.Ticker(ticker)
tk = yf.Ticker(market_ticker)
mk = tk.history(period=period, interval=interval)["Close"].pct_change().dropna()
px_t = mk.history(period=period, interval=interval)["Close"].pct_change().dropna()
px_m = pd.concat([px_t, px_m], axis=1, join="inner").dropna()
df if df.shape[0] < 2:
return 0.0
= df.iloc[:,0].cov(df.iloc[:,1])
cov = df.iloc[:,1].var()
var return cov / var if var else 0.0
def calculate_capm_expected_return(ticker, risk_free_rate, market_return,
="^GSPC", period="1y", interval="1d"):
market_ticker"""
E[R] = Rf + β × (Rm − Rf)
"""
= calculate_beta(ticker, market_ticker, period, interval)
beta return risk_free_rate + beta * (market_return - risk_free_rate)
def calculate_raroc_numerator(ticker, corporate_tax_rate=0.0):
"""
Adjusted Net Income = (Revenue − COGS − Operating Expenses) × (1 − Tc)
"""
= yf.Ticker(ticker).financials.fillna(0)
fin # Total Revenue
= fin.loc["Total Revenue"][0] if "Total Revenue" in fin.index else 0
rev # Cost Of Revenue
= fin.loc["Cost Of Revenue"][0] if "Cost Of Revenue" in fin.index else 0
cogs # Operating Expenses
= fin.loc["Operating Expenses"][0] if "Operating Expenses" in fin.index else 0
opex = (rev - cogs - opex) * (1 - corporate_tax_rate)
adjusted_net_income return adjusted_net_income
def calculate_raroc(ticker, economic_capital, corporate_tax_rate=0.0):
"""
RAROC = Adjusted Net Income / Economic Capital
"""
= calculate_raroc_numerator(ticker, corporate_tax_rate)
ani return ani / economic_capital if economic_capital else 0.0
def calculate_raroc_capm_equivalence(ticker, risk_free_rate, market_return,
=0.0,
economic_capital, corporate_tax_rate="^GSPC", period="1y", interval="1d"):
market_ticker"""
Returns CAPM expected return, beta, RAROC, market Sharpe, and LHS/RHS for equivalence.
"""
# CAPM
= calculate_beta(ticker, market_ticker, period, interval)
beta = risk_free_rate + beta * (market_return - risk_free_rate)
exp_ret # RAROC
= calculate_raroc(ticker, economic_capital, corporate_tax_rate)
raroc # Market Sharpe
= yf.Ticker(market_ticker)
mk = mk.history(period=period, interval=interval)["Close"].pct_change().dropna()
px_m = px_m.std() if not px_m.empty else 0.0
sigma_m = ((market_return - risk_free_rate) / sigma_m) if sigma_m else float('inf')
market_sharpe return {
"beta": beta,
"expected_return_CAPM": exp_ret,
"RAROC": raroc,
"market_sharpe": market_sharpe,
"RAROC-CAPM equilibrium LHS (RAROC)": raroc,
"RAROC-CAPM equilibrium RHS (Market Sharpe)": market_sharpe
}
# Example usage:
= calculate_capm_expected_return("AMZN", 0.02, 0.08)
capm_ret print(f"AAPL CAPM Expected Return: {capm_ret:.4f}")
#
= calculate_raroc("AMZN", economic_capital=500_000_000, corporate_tax_rate=0.21)
raroc_val print(f"AAPL RAROC: {raroc_val:.4f}")
#
= calculate_raroc_capm_equivalence("AMZN", 0.02, 0.08, 500_000_000, 0.21)
eq print(eq)
This tutorial provides a condensed overview of key concepts in capital structure, from the foundational MM theorems to more nuanced theories considering taxes, information asymmetries, and risk-adjusted performance measurement. Understanding these principles is vital for effective corporate financial management.