Functional Weave
Code in Rust

property.rental-yield@1.0.1

impl/python.py

1,647 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 .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, money  ← from money.amount ^1.0.0 · built alongside by fune
from .property_rental_yield_types import RentalYield

# Above this, amount * 10000 is no longer exact as a JavaScript number; the
# same limit applies here so every language refuses the same inputs.
_MAX_MINOR = 90_000_000_000


def rental_yield(annual_rent: Money, annual_costs: Money, property_value: Money) -> RentalYield:
    """Gross and net rental yield in basis points. Each is rounded once,
    half-up, from the exact ratio, never from a rounded percentage."""
    currency = property_value.currency
    for other in (annual_rent, annual_costs):
        if other.currency != currency:
            raise ValueError("currency mismatch: %s and %s" % (other.currency, currency))
    if property_value.minor <= 0:
        raise ValueError("propertyValue must be greater than zero, received %r" % (property_value.minor,))
    if annual_rent.minor < 0:
        raise ValueError("annualRent must not be negative, received %r" % (annual_rent.minor,))
    if annual_costs.minor < 0:
        raise ValueError("annualCosts must not be negative, received %r" % (annual_costs.minor,))
    for m in (annual_rent.minor, annual_costs.minor, property_value.minor):
        if m > _MAX_MINOR:
            raise ValueError("amounts must be at most %d minor units" % (_MAX_MINOR,))
    net = annual_rent.minor - annual_costs.minor
    return RentalYield(
        gross_basis_points=round_div(annual_rent.minor * 10000, property_value.minor, "half-up"),
        net_basis_points=round_div(net * 10000, property_value.minor, "half-up"),
        net_income=money(net, currency),
    )