The Return Decomposition splits the share price return over a window into the growth of the Earnings per Share and the change of the Price-to-Earnings ratio (the multiple), and adds the dividends paid over the window for the total return. It shows whether a share rose because the company earned more or because investors paid more for the same earnings, e.g. a share whose earnings beat expectations but whose price fell because its multiple contracted.

Since the share price equals the Earnings per Share times the P/E ratio, the price relative over a window is the product of the earnings relative and the multiple relative, which is the earnings and valuation split of equity returns used in return attribution (e.g. Bogle, “Common Sense on Mutual Funds”, and the building blocks of Grinold and Kroner, “The Equity Risk Premium”, 2002).

The formula is as follows:

\[1 + \text{Price Return} = (1 + \text{EPS Growth}) \cdot (1 + P / E \;\text{Change})\] \[\text{EPS Growth} = \text{EPS}_{t} / \text{EPS\_t-lag} - 1\] \[P / E \;\text{Change} = (\text{Price}_{t} / \text{EPS}_{t}) / (\text{Price\_t-lag} / \text{EPS\_t-lag}) - 1\] \[\text{Dividend Return} = \text{Dividends per Share paid over the window} / \text{Price\_t-lag}\] \[\text{Total Return} = \text{Price Return} + \text{Dividend Return}\]

With logarithmic=True the parts are log returns that add up: ln(1 + Total Return) = ln(1 + EPS Growth) + ln(1 + P/E Change) + ln(1 + Dividends / Price_t).

Also known as: earnings and multiple decomposition, P/E expansion and contraction, multiple expansion, return attribution by earnings growth and re-rating.

Return Decomposition in Python or via the MCP

Install the Finance Toolkit with:

pip install financetoolkit -U

Then call get_return_decomposition as shown below.

from financetoolkit import Toolkit

toolkit = Toolkit(
    ["AMD", "MSFT"],
    api_key="FINANCIAL_MODELING_PREP_KEY",
    start_date="2021-01-01",
    end_date="2025-12-31",
)

toolkit.models.get_return_decomposition()

Or, after setting up the Finance Toolkit MCP, ask:

How much of the share price returns of AMD and Microsoft from 2022 to 2025 came from earnings growth and how much from a change in their P/E?

Which returns:

  2022 2023 2024 2025
(‘AMD’, ‘Price Return’) -0.5499 1.2759 -0.1806 0.773
(‘AMD’, ‘EPS Growth’) -0.6734 -0.3745 0.9075 1.6433
(‘AMD’, ‘P/E Change’) 0.3782 2.6387 -0.5704 -0.3292
(‘AMD’, ‘Dividend Return’) 0 0 0 0
(‘AMD’, ‘Total Return’) -0.5499 1.2759 -0.1806 0.773
(‘MSFT’, ‘Price Return’) -0.2869 0.568 0.1209 0.1474
(‘MSFT’, ‘EPS Growth’) 0.1979 0.0039 0.2185 0.156
(‘MSFT’, ‘P/E Change’) -0.4047 0.562 -0.0801 -0.0075
(‘MSFT’, ‘Dividend Return’) 0.0076 0.0116 0.0082 0.0081
(‘MSFT’, ‘Total Return’) -0.2794 0.5796 0.1291 0.1554

Parameters

get_return_decomposition accepts the following parameters.

ParameterTypeDescriptionExample
lagint | NoneThe number of periods the window spans. Defaults to None, which compares each period with the same period a year earlier: 1 with annual data and 4 with quarterly data.4
dilutedboolWhether to use the diluted Earnings per Share. Defaults to True.False
trailingint | NoneThe number of periods to sum the Net Income over (and average the shares over). Defaults to None, which uses the trailing twelve months (4 quarters) with quarterly data and single years with annual data, as the P/E ratio does.4
logarithmicboolWhether to return log returns, which add up, instead of simple returns, which multiply. Defaults to False.False
roundingint | NoneThe number of decimals to round the results to. Defaults to None, which uses the rounding of the Toolkit (4 unless set otherwise).2
Share