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}")








