# Residual-Income Model

`D18-F02-A04` · Fundamental Analysis and Valuation → Intrinsic Valuation · archetype `record-transform` · difficulty 4/5 · verification **verified**

Full page: https://docs.thefintechbuilder.com/fundamental-analysis-and-valuation/intrinsic-valuation/residual-income-model/
Agent skill: `npx skills add IslamBaraka90/Fintech-Algorithms-Library` — https://docs.thefintechbuilder.com/guides/agent-skill/

## Install and import

```bash
npm install fintech-algorithms
```

```ts
import { residualIncomeModel } from "fintech-algorithms/fundamental-analysis-and-valuation/intrinsic-valuation/residual-income-model";
```

## Signature

```ts
residualIncomeModel(data)
```

Rolls per-share book value forward through a forecast, charges each period's opening book value at the cost of equity, discounts the residual income that remains, and adds opening book value plus a growing-perpetuity continuing value to reach intrinsic value per share.

## Parameters

| Name | Type | Required | Notes |
| --- | --- | --- | --- |
| `data` | `{ opening_book_value_per_share: number; earnings_per_share: number[]; dividends_per_share: number[]; nonowner_equity_adjustments_per_share: number[]; cost_of_equity: number; terminal_residual_income_growth: number }` | yes | `opening_book_value_per_share` starts the roll-forward, which each period adds `earnings_per_share`, subtracts `dividends_per_share` and adds `nonowner_equity_adjustments_per_share`. Those three arrays must be the same length. `cost_of_equity` sets both the equity charge on opening book value and the discount rate, and `terminal_residual_income_growth` grows the last period's residual income into the continuing value. Other keys in the record are not read. |

## Returns

`{ state: string; method: string; schedule: { period: number; opening_book_value_per_share: number; earnings_per_share: number; dividends_per_share: number; nonowner_equity_adjustment_per_share: number; equity_charge_per_share: number; residual_income_per_share: number; discount_factor: number; present_value: number; closing_book_value_per_share: number }[]; pv_explicit_residual_income: number; terminal_residual_income_per_share: number; continuing_value: number; terminal_discount_factor: number; pv_continuing_value: number; continuing_value_share: number; closing_book_value_per_share: number; intrinsic_value_per_share: number }`

A `schedule` row per period showing the book-value roll-forward, its `equity_charge_per_share`, `residual_income_per_share`, `discount_factor` and `present_value`. Then `pv_explicit_residual_income`, the continuing block (`terminal_residual_income_per_share`, `continuing_value`, `terminal_discount_factor`, `pv_continuing_value`), the final `closing_book_value_per_share`, and `intrinsic_value_per_share` — opening book value plus both present values. `continuing_value_share` is the continuing share of that total, emitted as 0 when the total is 0.

## Errors

- When `data` is absent, an array, or not an object — throws Error
- When `opening_book_value_per_share` is not a positive finite number — throws Error
- When any of the three per-share arrays is not an array holding at least one finite number — throws Error
- When `dividends_per_share` or `nonowner_equity_adjustments_per_share` differs in length from `earnings_per_share` — throws Error
- When `cost_of_equity` is not strictly between 0 and 1 — throws Error
- When `terminal_residual_income_growth` is at or below -1, or at or above `cost_of_equity` — throws Error
- When a period's `dividends_per_share` is negative — throws Error
- When the book-value roll-forward reaches a non-positive closing balance — throws Error

## Complexity

Time `O(n)`, space `O(n)`.

## Worked example

Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.

### Input

`data`:

```json
{
  "valuation_date": "2026-08-04",
  "currency": "USD",
  "opening_book_value_per_share": 30,
  "earnings_per_share": [3.6, 4, 4.35, 4.65, 4.9],
  "dividends_per_share": [1.2, 1.35, 1.5, 1.65, 1.8],
  "nonowner_equity_adjustments_per_share": [0, 0, 0, 0, 0],
  "cost_of_equity": 0.1,
  "terminal_residual_income_growth": 0.03
}
```

### Call

```ts
residualIncomeModel(data)
```

### Returns

object with 11 fields: state, method, schedule, pv_explicit_residual_income, terminal_residual_income_per_share, continuing_value, terminal_discount_factor, pv_continuing_value, …

```json
{
  "state": "valued",
  "method": "residual-income",
  "schedule": [
    {
      "period": 1,
      "opening_book_value_per_share": 30,
      "earnings_per_share": 3.6,
      "dividends_per_share": 1.2,
      "nonowner_equity_adjustment_per_share": 0,
      "equity_charge_per_share": 3,
      "residual_income_per_share": 0.6000000000000001,
      "discount_factor": 0.9090909090909091,
      "present_value": 0.5454545454545455,
      "closing_book_value_per_share": 32.4
    },
    {
      "period": 2,
      "opening_book_value_per_share": 32.4,
      "earnings_per_share": 4,
      "dividends_per_share": 1.35,
      "nonowner_equity_adjustment_per_share": 0,
      "equity_charge_per_share": 3.24,
      "residual_income_per_share": 0.7599999999999998,
      "discount_factor": 0.8264462809917354,
      "present_value": 0.6280991735537188,
      "closing_book_value_per_share": 35.05
    },
    {
      "period": 3,
      "opening_book_value_per_share": 35.05,
      "earnings_per_share": 4.35,
      "dividends_per_share": 1.5,
      "nonowner_equity_adjustment_per_share": 0,
      "equity_charge_per_share": 3.505,
      "residual_income_per_share": 0.8449999999999998,
      "discount_factor": 0.7513148009015775,
      "present_value": 0.6348610067618329,
      "closing_book_value_per_share": 37.9
    }
  ],
  "pv_explicit_residual_income": 2.898752569061974,
  "terminal_residual_income_per_share": 0.8343000000000005,
  "continuing_value": 11.918571428571434,
  "terminal_discount_factor": 0.6209213230591549,
  "pv_continuing_value": 7.400495140403617,
  "continuing_value_share": 0.18363854317472458,
  "closing_book_value_per_share": 44,
  "intrinsic_value_per_share": 40.29924770946559
}
```

## Other exports

`calculate`, `freeCashFlowDcf`, `dividendDiscountModel`, `gordonGrowthModel`, `economicValueAdded`. Every module additionally exports `run` as an alias of its primary
function, and a `meta` object carrying its catalog id, domain, family, shape and article URL.

## Verification and provenance

Tier: **verified** (via D).

The worked example below is the figure published in this algorithm's article, replayed and asserted by the test suite on every build. The arithmetic cannot drift without the build failing.

Both tiers guarantee the signature. Full explanation: https://docs.thefintechbuilder.com/guides/verification/

Generated from the docs.json payload shipped inside fintech-algorithms@0.13.0.
The signature and parameter list are checked against the compiled implementation at build time,
so a description that contradicts the code fails the build rather than reaching this file.

## Links

- Article (how it works, step by step): https://thefintechbuilder.com/fundamental-analysis-and-valuation/intrinsic-valuation/residual-income-model/
- Implementation source: https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/fundamental-analysis-and-valuation/intrinsic-valuation/residual-income-model/impl.ts
- Package on npm: https://www.npmjs.com/package/fintech-algorithms
- Domain index for agents: https://docs.thefintechbuilder.com/fundamental-analysis-and-valuation/llms.txt
