-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwacc_automation.py
More file actions
109 lines (94 loc) · 4.48 KB
/
Copy pathwacc_automation.py
File metadata and controls
109 lines (94 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import yfinance as yf
import numpy as np
def fetch_live_wacc_inputs(ticker_symbol: str, erp_assumption: float = 0.055) -> dict:
"""
Fetches real-time market risk parameters via yfinance and calculates WACC.
Applies strict institutional fallbacks if API data points return NaN or None.
"""
print(f"[WACC Automation] Scanning live market risk profile for {ticker_symbol.upper()}...")
ticker = yf.Ticker(ticker_symbol)
# ---------------------------------------------------------
# 1. Risk-Free Rate (Rf) Fetching & Fallback
# ---------------------------------------------------------
try:
tnx = yf.Ticker("^TNX")
# Pull latest close for 10-Yr US Treasury Yield
rf = tnx.history(period="1d")['Close'].iloc[-1] / 100
if np.isnan(rf) or rf <= 0:
rf = 0.0425 # Fallback to historical baseline (4.25%)
except Exception:
rf = 0.0425
# ---------------------------------------------------------
# 2. Beta (β) Fetching & Fallback
# ---------------------------------------------------------
try:
beta = ticker.info.get('beta')
if beta is None or np.isnan(beta) or beta <= 0:
beta = 1.10 # Fallback to mature large-cap tech average
except Exception:
beta = 1.10
# ---------------------------------------------------------
# 3. Capital Structure Metrics
# ---------------------------------------------------------
try:
market_cap = ticker.info.get('marketCap')
if market_cap is None or np.isnan(market_cap):
market_cap = 2_500_000_000_000 # Proxy baseline if missing
except Exception:
market_cap = 2_500_000_000_000
# Total Debt extraction from balance sheet
try:
bs = ticker.balance_sheet
if 'Long Term Debt' in bs.index:
total_debt = bs.loc['Long Term Debt'].iloc[0]
else:
total_debt = market_cap * 0.05 # Standard conservative debt proxy
if np.isnan(total_debt):
total_debt = market_cap * 0.05
except Exception:
total_debt = market_cap * 0.05
# ---------------------------------------------------------
# 4. Cost of Debt & Effective Tax Rate
# ---------------------------------------------------------
try:
inc_stmt = ticker.financials
ebit = inc_stmt.loc['EBIT'].iloc[0] if 'EBIT' in inc_stmt.index else 1.0
tax_prov = inc_stmt.loc['Tax Provision'].iloc[0] if 'Tax Provision' in inc_stmt.index else 0.0
tax_rate = tax_prov / ebit if ebit > 0 else 0.21
if np.isnan(tax_rate) or tax_rate < 0 or tax_rate > 0.5:
tax_rate = 0.21 # Standard US Corporate Tax baseline fallback
except Exception:
tax_rate = 0.21
cost_of_debt = rf + 0.015 # Institutional assumption: Risk-Free + 150 bps credit spread
# ---------------------------------------------------------
# 5. Core WACC Mathematical Blend
# ---------------------------------------------------------
cost_of_equity = rf + (beta * erp_assumption)
total_capital = market_cap + total_debt
weight_of_equity = market_cap / total_capital
weight_of_debt = total_debt / total_capital
# Blended After-Tax WACC formula
calculated_wacc = (weight_of_equity * cost_of_equity) + (weight_of_debt * cost_of_debt * (1 - tax_rate))
# Ultimate sanity check gatekeeper
if np.isnan(calculated_wacc):
calculated_wacc = 0.090 # 9.0% standard discount anchor to keep pipeline alive
# ---------------------------------------------------------
# 6. Comprehensive Return Dictionary
# ---------------------------------------------------------
return {
'Calculated WACC': float(calculated_wacc),
'Cost of Equity': float(cost_of_equity),
'Cost of Debt': float(cost_of_debt),
'Tax Rate': float(tax_rate),
'Total Debt': float(total_debt),
'Market Cap (Equity Value)': float(market_cap),
# Extended keys required by Phase 3B and Phase 4
'Risk Free Rate': float(rf),
'Risk-Free Rate': float(rf),
'Beta': float(beta),
'ERP': float(erp_assumption),
'Equity Risk Premium': float(erp_assumption),
# Capital structure weights explicitly required by dcf_valuation.py
'Weight of Equity': float(weight_of_equity),
'Weight of Debt': float(weight_of_debt)
}