Functional Weave
Code in Python

finance.depreciation-reducing-balance@1.0.0

impl/python.py

2,011 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from typing import List

from .finance_depreciation_straight_line_types import DepreciationPeriod
from .money_add import subtract_money  ← from money.add ^1.0.0 · built alongside by fune
from .money_amount import Money  ← from money.amount ^1.0.0 · built alongside by fune
from .money_apply_rate import apply_rate  ← from money.apply-rate ^1.0.0 · built alongside by fune


def reducing_balance_depreciation(
    cost: Money, residual_value: Money, rate_basis_points: int, years: int
) -> List[DepreciationPeriod]:
    """A reducing-balance depreciation schedule, year by year.

    Each charge is the rate applied to the opening value, rounded once. The
    last year writes off down to the residual value, and no year may go below it.
    """
    if isinstance(years, bool) or not isinstance(years, int) or years < 1:
        raise ValueError("years must be at least 1, received %r" % (years,))
    if (
        isinstance(rate_basis_points, bool)
        or not isinstance(rate_basis_points, int)
        or rate_basis_points < 0
        or rate_basis_points > 10000
    ):
        raise ValueError("rate must be 0 to 10000 basis points, received %r" % (rate_basis_points,))
    if cost.minor < 0:
        raise ValueError("cost must not be negative")
    if residual_value.minor < 0:
        raise ValueError("residual value must not be negative")
    # subtract_money also refuses a cost and residual value in different currencies.
    if subtract_money(cost, residual_value).minor < 0:
        raise ValueError("residual value must not exceed cost")

    schedule: List[DepreciationPeriod] = []
    opening_value = cost
    for year in range(1, years + 1):
        headroom = subtract_money(opening_value, residual_value)
        charge = headroom if year == years else apply_rate(opening_value, rate_basis_points, "half-up")
        if charge.minor > headroom.minor:
            charge = headroom
        closing_value = subtract_money(opening_value, charge)
        schedule.append(
            DepreciationPeriod(year=year, opening_value=opening_value, charge=charge, closing_value=closing_value)
        )
        opening_value = closing_value
    return schedule