Skip to content
Learni
View all tutorials
Finance Technique

How to Calculate WACC with Python in 2026

Lire en français

Introduction

The WACC (Weighted Average Cost of Capital) is a company's weighted average cost of capital, essential for DCF valuations, investment decisions, and financial analysis. It combines the cost of equity (via CAPM) and the cost of debt, weighted by their proportions in the balance sheet.

Why automate it in Python? Spreadsheets like Excel fall short on real-time data (beta, risk-free rates). With yfinance to fetch stock data and Streamlit for a web interface, you get a scalable, accurate, shareable tool. This intermediate tutorial guides you step by step: from the theoretical formula to deploying a full app. By the end, calculate WACC for any listed stock in 30 seconds. Time savings: up to 80% vs. manual methods. (128 words)

Prerequisites

  • Python 3.10+
  • pip install streamlit yfinance pandas numpy
  • Basic finance knowledge (CAPM, balance sheet)
  • Free Yahoo Finance account (optional for API)
  • VS Code or PyCharm for editing

Installing Dependencies

terminal
pip install streamlit yfinance pandas numpy

streamlit hello

Install the essential libraries: Streamlit for the interface, yfinance for stock data, Pandas/NumPy for calculations. Test with streamlit hello to verify installation. Use a virtualenv to avoid conflicts.

Breaking Down the WACC Formula

WACC = (E/V) × Re + (D/V) × Rd × (1 - Tc)

  • E: Equity value (market cap)
  • D: Net debt (enter manually)
  • V: E + D
  • Re: Cost of equity = Rf + β × (Rm - Rf) (CAPM)
  • Rd: Cost of debt (interest rate)
  • Tc: Effective tax rate
Think of it like a weighted basket of ingredients. We'll fetch β, Rf (10Y Treasury), Rm (S&P 500 historical ~10%).

CAPM Function for Cost of Equity

capm.py
import yfinance as yf
import numpy as np

def capm_cost_equity(ticker, risk_free_rate=0.043, market_premium=0.06):
    stock = yf.Ticker(ticker)
    beta = stock.info.get('beta', 1.0)
    re = risk_free_rate + beta * market_premium
    return re, beta

# Exemple
re, beta = capm_cost_equity('AAPL')
print(f"Beta: {beta:.2f}, Re: {re:.2%}")

This function fetches beta via yfinance and calculates Re using Rf=4.3% (US 10Y 2026) and market premium=6%. Pitfall: missing beta → fallback to 1.0. Test with AAPL to validate (beta ~1.2, Re ~11%).

Cost of Debt and WACC Functions

wacc_functions.py
def cost_debt(rating='BBB'):
    rates = {'AAA': 0.035, 'AA': 0.038, 'A': 0.042, 'BBB': 0.048}
    return rates.get(rating, 0.05)

def calculate_wacc(equity_value, debt_value, re, rd, tax_rate=0.21):
    total_value = equity_value + debt_value
    weight_equity = equity_value / total_value
    weight_debt = debt_value / total_value
    wacc = (weight_equity * re) + (weight_debt * rd * (1 - tax_rate))
    return wacc

# Exemple statique
re = 0.11
rd = cost_debt('A')
wacc = calculate_wacc(1000, 400, re, rd)
print(f"WACC: {wacc:.2%}")

cost_debt uses a rating-based lookup (Moody's approx 2026). WACC weights precisely. Pitfall: debt=0 → avoids div/0 implicitly, but validate V>0. Example: E=1000B$, D=400B$ → WACC ~8.5%.

Integrating yfinance Data

Combine CAPM with market cap. Debt: enter from 10-K (not always in API). Dynamic Rf via '^TNX' (10Y Treasury), fixed or historical Rm-Rf.

Main Script with Market Cap Fetch

fetch_wacc.py
import yfinance as yf

from capm import capm_cost_equity  # Import des fonctions précédentes
from wacc_functions import cost_debt, calculate_wacc

def full_wacc(ticker, debt_value, rating='BBB', tax_rate=0.21):
    stock = yf.Ticker(ticker)
    equity_value = stock.info.get('marketCap', 0) / 1e9  # En milliards
    rf = yf.download('^TNX', period='1d')['Close'].iloc[-1] / 100
    re, beta = capm_cost_equity(ticker, rf)
    rd = cost_debt(rating)
    wacc = calculate_wacc(equity_value, debt_value, re, rd, tax_rate)
    return {
        'ticker': ticker,
        'equity': equity_value,
        'debt': debt_value,
        're': re,
        'rd': rd,
        'wacc': wacc
    }

# Usage
result = full_wacc('MSFT', debt_value=800)
print(result)

Full script: fetches marketCap, live Rf, computes everything. Pitfall: marketCap in USD, divide by 1e9 for billions; handle NaN with .get(). Example MSFT: equity ~3T$, debt~800B$, WACC ~7-9%.

Complete Streamlit App

app.py
import streamlit as st
import yfinance as yf
import numpy as np
from capm import capm_cost_equity
from wacc_functions import cost_debt, calculate_wacc

def full_wacc(ticker, debt_value, rating, tax_rate):
    stock = yf.Ticker(ticker)
    equity_value = stock.info.get('marketCap', 0) / 1e9
    rf = yf.download('^TNX', period='1d')['Close'].iloc[-1] / 100
    re, beta = capm_cost_equity(ticker, rf)
    rd = cost_debt(rating)
    wacc = calculate_wacc(equity_value, debt_value, re, rd, tax_rate)
    return {
        'Equity (B$)': equity_value,
        'Debt (B$)': debt_value,
        'Beta': beta,
        'Re (%)': re * 100,
        'Rd (%)': rd * 100,
        'Tax Rate (%)': tax_rate * 100,
        'WACC (%)': wacc * 100
    }

st.title('Calculateur WACC 2026')

col1, col2 = st.columns(2)
with col1:
    ticker = st.text_input('Ticker (ex: AAPL)', 'AAPL')
    debt = st.number_input('Dette nette (B$)', min_value=0.0, value=500.0)
with col2:
    rating = st.selectbox('Rating dette', ['AAA', 'AA', 'A', 'BBB'])
    tax = st.number_input('Taux impôt (%)', min_value=0.0, max_value=0.5, value=0.21)

if st.button('Calculer WACC'):
    with st.spinner('Fetch données...'):
        result = full_wacc(ticker, debt, rating, tax)
    st.success('WACC calculé !')
    st.metric('WACC', f"{result['WACC (%)']:.2f}%")
    st.table(result)

st.caption('Données live via yfinance. Mise à jour 2026.')

Full-stack Streamlit app: interactive inputs, live fetches, results table, visual metric. Run with streamlit run app.py. Pitfall: yfinance timeouts → add try/except in production; use localtunnel to share.

Best Practices

  • Validate data: Always cross-check beta/marketCap manually vs. Yahoo (discrepancies ~5%).
  • Dynamic Rf: Use '^TNX' or ECB for Europe.
  • Sensitivity: Add Monte Carlo sliders for ±1% beta.
  • Cache API calls: Use @st.cache_data on full_wacc for performance.
  • Deploy on Streamlit Cloud: Free, auto HTTPS.

Common Errors to Avoid

  • Ignoring debt: Without D, WACC=Re (overvalues). Always estimate from balance sheets.
  • Static Rf: Ignores 2026 inflation (~3%) → underestimates Re.
  • Unadjusted beta: Raw from Yahoo; adjust for levered/unlevered.
  • Inconsistent units: MarketCap in shares*price, debt absolute → unify to billions.

Next Steps

Integrate Black-Scholes for warrants/options or full DCF. Resources:

Check out our Learni quantitative finance courses.