Skip to content

CAPM

startup_valuation.capm

CAPM and risk-adjusted return calculations.

Chapter 2: Mathematical Foundations — Risk-Adjusted Discount Rates

Classes

Functions

capm(risk_free_rate, beta, market_return)

Calculate expected return using CAPM.

Formula: E(Rᵢ) = Rf + βᵢ × (E(Rm) - Rf)

Parameters:

Name Type Description Default
risk_free_rate float

Risk-free rate (Rf).

required
beta float

Beta of the asset (βᵢ).

required
market_return float

Expected market return (E(Rm)).

required

Returns:

Type Description
ValuationResult

ValuationResult with expected return.

Example

result = capm(0.03, 1.5, 0.10) round(result.value, 4) 0.135

Source code in src/startup_valuation/capm.py
def capm(
    risk_free_rate: float,
    beta: float,
    market_return: float,
) -> ValuationResult:
    """Calculate expected return using CAPM.

    Formula: E(Rᵢ) = Rf + βᵢ × (E(Rm) - Rf)

    Args:
        risk_free_rate: Risk-free rate (Rf).
        beta: Beta of the asset (βᵢ).
        market_return: Expected market return (E(Rm)).

    Returns:
        ValuationResult with expected return.

    Example:
        >>> result = capm(0.03, 1.5, 0.10)
        >>> round(result.value, 4)
        0.135
    """
    market_risk_premium = market_return - risk_free_rate
    expected_return = risk_free_rate + beta * market_risk_premium

    return ValuationResult(
        value=expected_return,
        method="CAPM",
        inputs={
            "risk_free_rate": risk_free_rate,
            "beta": beta,
            "market_return": market_return,
        },
        assumptions=[
            "Markets are efficient",
            "Beta captures all systematic risk",
            "Risk-free rate is accessible to investors",
        ],
        chapter="2",
    )

portfolio_beta(weights, betas)

Calculate portfolio beta as weighted average.

Formula: βp = Σ wᵢ × βᵢ

Parameters:

Name Type Description Default
weights list[float]

Portfolio weights (wᵢ).

required
betas list[float]

Individual asset betas (βᵢ).

required

Returns:

Type Description
ValuationResult

ValuationResult with portfolio beta.

Example

result = portfolio_beta([0.60, 0.40], [0.8, 1.2]) result.value 0.96

Source code in src/startup_valuation/capm.py
def portfolio_beta(
    weights: list[float],
    betas: list[float],
) -> ValuationResult:
    """Calculate portfolio beta as weighted average.

    Formula: βp = Σ wᵢ × βᵢ

    Args:
        weights: Portfolio weights (wᵢ).
        betas: Individual asset betas (βᵢ).

    Returns:
        ValuationResult with portfolio beta.

    Example:
        >>> result = portfolio_beta([0.60, 0.40], [0.8, 1.2])
        >>> result.value
        0.96
    """
    if len(weights) != len(betas):
        raise ValueError("weights and betas must have the same length")

    pb = sum(w * b for w, b in zip(weights, betas))

    return ValuationResult(
        value=pb,
        method="Portfolio Beta",
        inputs={"weights": weights, "betas": betas},
        assumptions=["Beta is stable and accurately estimated"],
        chapter="2",
    )

startup_adjusted_capm(risk_free_rate, beta, market_risk_premium, size_premium=0.0, startup_premium=0.0)

Calculate startup-adjusted CAPM with additional risk premiums.

Formula: E(R) = Rf + β × MRP + Size Premium + Startup Premium

Parameters:

Name Type Description Default
risk_free_rate float

Risk-free rate.

required
beta float

Beta of the startup.

required
market_risk_premium float

Market risk premium.

required
size_premium float

Additional premium for small company size.

0.0
startup_premium float

Additional premium for startup-specific risks.

0.0

Returns:

Type Description
ValuationResult

ValuationResult with adjusted expected return.

Example

result = startup_adjusted_capm(0.04, 1.3, 0.07, 0.03, 0.10) round(result.value, 4) 0.261

Source code in src/startup_valuation/capm.py
def startup_adjusted_capm(
    risk_free_rate: float,
    beta: float,
    market_risk_premium: float,
    size_premium: float = 0.0,
    startup_premium: float = 0.0,
) -> ValuationResult:
    """Calculate startup-adjusted CAPM with additional risk premiums.

    Formula: E(R) = Rf + β × MRP + Size Premium + Startup Premium

    Args:
        risk_free_rate: Risk-free rate.
        beta: Beta of the startup.
        market_risk_premium: Market risk premium.
        size_premium: Additional premium for small company size.
        startup_premium: Additional premium for startup-specific risks.

    Returns:
        ValuationResult with adjusted expected return.

    Example:
        >>> result = startup_adjusted_capm(0.04, 1.3, 0.07, 0.03, 0.10)
        >>> round(result.value, 4)
        0.261
    """
    expected_return = risk_free_rate + beta * market_risk_premium + size_premium + startup_premium

    return ValuationResult(
        value=expected_return,
        method="Startup-Adjusted CAPM",
        inputs={
            "risk_free_rate": risk_free_rate,
            "beta": beta,
            "market_risk_premium": market_risk_premium,
            "size_premium": size_premium,
            "startup_premium": startup_premium,
        },
        assumptions=[
            "Additional premiums are additive to CAPM",
            "Beta is estimated from comparable companies",
        ],
        chapter="2",
    )

portfolio_variance(weights, covariances)

Calculate portfolio variance.

Formula: Var(Rp) = ΣΣ wᵢ × wⱼ × Cov(Rᵢ, Rⱼ)

Parameters:

Name Type Description Default
weights list[float]

Portfolio weights.

required
covariances list[list[float]]

Covariance matrix.

required

Returns:

Type Description
ValuationResult

ValuationResult with portfolio variance.

Source code in src/startup_valuation/capm.py
def portfolio_variance(
    weights: list[float],
    covariances: list[list[float]],
) -> ValuationResult:
    """Calculate portfolio variance.

    Formula: Var(Rp) = ΣΣ wᵢ × wⱼ × Cov(Rᵢ, Rⱼ)

    Args:
        weights: Portfolio weights.
        covariances: Covariance matrix.

    Returns:
        ValuationResult with portfolio variance.
    """
    n = len(weights)
    if len(covariances) != n or any(len(row) != n for row in covariances):
        raise ValueError("covariances must be an n×n matrix")

    variance = sum(
        weights[i] * weights[j] * covariances[i][j]
        for i in range(n)
        for j in range(n)
    )

    return ValuationResult(
        value=variance,
        method="Portfolio Variance",
        inputs={"weights": weights, "covariances": covariances},
        assumptions=["Covariance matrix is accurate and stable"],
        chapter="2",
    )