Coding towards CFA (44) – General Residual Income Model for Equity Valuation

Coding towards CFA (44) – General Residual Income Model for Equity Valuation

The Residual Income Model is one of the equity valuation methods covered in the CFA Level 2 curriculum. This method estimates the intrinsic value of a stock based on the stock’s current book value, plus the present value of expected future residual income. Residual income represents the income generated by the company in excess of the minimum return required by equity investors.

In this blog post, I will first implement Python code for calculating residual income and then create the code for calculating the intrinsic value of a stock using the general residual income model.

Residual Income Calculation

Residual income can be calculated by subtracting the cost of equity from the net income of a given period. One of the advantages of using the Residual Income Model is that the data required for the calculation is accessible from the company’s accounting records, which are typically more readily available and reliable. The residual income measure can be derived from different accounting data. The CFA curriculum introduces three routes to reach residual income. I will implement the code for these three routes.

Net Income Route

For this route, we will first calculate the net income and then subtract the cost of equity to determine the residual income, as shown in the following formulas.

Here is the Python code implementing those formulas. The code is straightforward and self-explanatory.

NOPAT Route

This route calculates the Net Operating Profit After Tax (NOPAT) and subtracts the cost of total capital to determine the economic profit or residual income.

NOPAT can be calculated using the Operating Income (EBIT) from the income statement, adjusted for taxes. It is a key metric for evaluating a company’s efficiency in generating profits from its core operations.

The Weighted Average Cost of Capital (WACC) is used as the cost rate of the total capital, representing the minimum return required by both debt and equity investors. To calculate WACC, we need to calculate the proportion of debt and equity in the capital structure, the cost of debt, and the cost of equity.

ROIC Route

This route uses the ROIC metric to derive residual income by comparing comparing ROIC to WACC.

Residual Income Model

First, let’s revisit the Dividend Discount Model for valuing a stock as the present value of its expected future dividends. According to the clean surplus relation: B(t) = B(t-1) + E(t) – D(t). We can derive that the D(t) = E(t) + B(t-1) – B(t).

After substituting D(t) with the earnings and book values formula, we arrive at the following equation. Through the transformations shown below, we derive a formula that includes residual income (RI) and the current book value (B0​). This formula, which represents the stock value as the current book value plus the present value of all future residual incomes, is the general formula for the residual income model.

To better understand the model, I drew the following diagram to illustrate the residual income calculation and discounting process.

At time 0, we have the current book value (B0)

At time 1, we calculate the cost of equity at time 1 as the book value at time 0 (B0) times required return of equity. The residual return is the earnings after subtracting the cost of equity (E(1) – B(0)*r). The residual return needs to be discounted to it’s value at time 0.

At time 2, We need to calculate the book value at time 1 (B1) first in order to calculate the cost of equity at time 2. The B1 can be calculated as the book value at time 0 plus the earnings during time 1, minus the dividend paid out at time 1, i.e., B1 = B0 + E1 – D1.

At time 3…n, repeat the process for the entire forecast period.

The formula and example provided by the CFA curriculum do not consider the terminal value of the stock, assuming instead an infinite forecast period. In practice, we need to estimate the terminal value and take it into account when calculating the stock value at time 0.

Here is the Python code that implements the process described above.

Full Python Code

Residual Income Calculation

# calculate residual income through net income
def calculate_RI_through_NI(ebit, tax_rate, debt_interest_rate, 
                                        equity_required_return, debt, equity):

    # calculate earning before tax
    ebt = ebit - (debt * debt_interest_rate)

    # calculate net income
    net_income = ebt * (1 - tax_rate)

    # calculate cost of equity
    equity_cost = equity * equity_required_return

    # calculate residual income
    residual_income = net_income - equity_cost

    return residual_income 


# calculate residual income through net of profit after tax
def calculate_RI_through_NOPAT(ebit, tax_rate, debt_interest_rate, 
                                        equity_required_return, debt, equity):
    
    # calculate net operatoin profit after tax
    nopat = ebit * (1 - tax_rate)

    # calculate debt weigth and equity weight
    total_capital = debt + equity
    debt_ratio = debt / total_capital
    equity_ratio = equity / total_capital

    # calculate wacc
    wacc = ((debt_interest_rate * (1-tax_rate) * debt_ratio) 
            + (equity_required_return * equity_ratio))

    # Calculate Residual Income
    residual_income = nopat - (total_capital * wacc)

    return residual_income


# calculate residual income through return on invested capital
def calculate_RI_through_ROIC(ebit, tax_rate, debt_interest_rate, 
                                        equity_required_return, debt, equity):
    
    # calculate net operatoin profit after tax
    nopat = ebit * (1 - tax_rate)

    # calculate total capital 
    total_capital = debt + equity
    debt_ratio = debt / total_capital
    equity_ratio = equity / total_capital

    # calculate wacc
    wacc = ((debt_interest_rate * (1-tax_rate) * debt_ratio) 
                        + (equity_required_return * equity_ratio))

    # calculate ROIC
    roic = nopat / total_capital

    # calculate residual income
    residual_income = (roic - wacc) * total_capital

    return residual_income


ebit = 1000000  
tax_rate = 0.2
debt_interest_rate = 0.05 
equity_required_return = 0.10
debt = 1000000 
equity = 1000000

# Calculate Residual Income with NI approach
residual_income = calculate_RI_through_NI(ebit, tax_rate, debt_interest_rate, equity_required_return, debt, equity)
print(f"Residual Income (NI Approach): ${residual_income:.2f}")

# Calculate Residual Income with NOPAT approach
residual_income = calculate_RI_through_NOPAT(ebit, tax_rate, debt_interest_rate, equity_required_return, debt, equity)
print(f"Residual Income (NOPAT Approach): ${residual_income:.2f}")

# Calculate Residual Income with ROIC approach
residual_income = calculate_RI_through_ROIC(ebit, tax_rate, debt_interest_rate, equity_required_return, debt, equity)
print(f"Residual Income (ROIC Approach): ${residual_income:.2f}")

General Residual Income Model

def calculate_residual_income(B0, expected_earnings, required_return_rate, dividends, terminal_value):

    years = len(expected_earnings)
    bv_prev = B0

    # define a list to store the present values of residual income of each period
    pv_residual_incomes = []

    # calculate residual income for each period.
    # As residual income needs to be calculated based on book value of previous year,
    # loops instead vectorised computations are used here.
    for t in range(years):

        # calculate costs of equity for current period
        cost_of_equity = required_return_rate * bv_prev

        # Calculate residual income for the current period
        residual_income_t = expected_earnings[t] - cost_of_equity
        
        # calculate present value of residual income 
        pv_residual_incomes.append(residual_income_t / ((1 + required_return_rate) ** (t + 1)))
        
        # Update book value for the next period
        bv_prev = bv_prev + (expected_earnings[t] - dividends[t])

    # Add discounted terminal value
    V0 = sum(pv_residual_incomes) + terminal_value / ((1 + required_return_rate) ** (t + 1))

    return V0


B0 = 100
EPS = [20, 25, 30, 33, 35]
dividends = [1, 1.25, 1.5, 1.75, 2]
required_return_rate = 0.10 
terminal_value = 150

V0 = calculate_residual_income(B0, EPS, required_return_rate, dividends, terminal_value)
print(f"Intrinsic Value of Equity: {V0:.2f}")

Leave a comment