TheAlgorithms/Python · error · ValueError

days_between_payments must be > 0

Error message

days_between_payments must be > 0

What it means

Raised by simple_interest() in financial/interest.py when days_between_payments <= 0. Interest here is principal * daily_rate * days, and a non-positive day count is meaningless; this is the first of three ordered checks (days, then rate, then principal), so it fires even if the other arguments are also invalid.

Source

Thrown at financial/interest.py:34

    >>> simple_interest(18000.0, 0.0, 3)
    0.0
    >>> simple_interest(5500.0, 0.01, 100)
    5500.0
    >>> simple_interest(10000.0, -0.06, 3)
    Traceback (most recent call last):
        ...
    ValueError: daily_interest_rate must be >= 0
    >>> simple_interest(-10000.0, 0.06, 3)
    Traceback (most recent call last):
        ...
    ValueError: principal must be > 0
    >>> simple_interest(5500.0, 0.01, -5)
    Traceback (most recent call last):
        ...
    ValueError: days_between_payments must be > 0
    """
    if days_between_payments <= 0:
        raise ValueError("days_between_payments must be > 0")
    if daily_interest_rate < 0:
        raise ValueError("daily_interest_rate must be >= 0")
    if principal <= 0:
        raise ValueError("principal must be > 0")
    return principal * daily_interest_rate * days_between_payments


def compound_interest(
    principal: float,
    nominal_annual_interest_rate_percentage: float,
    number_of_compounding_periods: float,
) -> float:
    """
    >>> compound_interest(10000.0, 0.05, 3)
    1576.2500000000014
    >>> compound_interest(10000.0, 0.05, 1)
    500.00000000000045
    >>> compound_interest(0.5, 0.05, 3)

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass a strictly positive integer day count between payments.
  2. When deriving from dates, assert end >= start and use max(1, (end - start).days) only if same-day accrual rules permit.
  3. Validate all three simple_interest arguments together before calling (see defense snippet).

Example fix

# before
si = simple_interest(5500.0, 0.01, -5)  # ValueError

# after
from datetime import date
days = (date(2024, 2, 1) - date(2024, 1, 1)).days  # 31
si = simple_interest(5500.0, 0.01, days)
Defensive patterns

Strategy: validation

Validate before calling

if days_between_payments <= 0:
    raise ScheduleError("days_between_payments must be > 0; check payment date order")

Type guard

def valid_simple_interest_args(p, r, d) -> bool:
    return p > 0 and r >= 0 and d > 0

Try / catch

try:
    si = simple_interest(principal, daily_rate, days)
except ValueError as exc:
    raise ScheduleError(str(exc)) from exc

Prevention

When it happens

Trigger: simple_interest(5500.0, 0.01, -5) or days=0; computing days as (end_date - start_date).days when the dates are reversed or equal; a date parse failure yielding a 0-day interval.

Common situations: Date-order bugs where payment date precedes the loan date; timezone/DST arithmetic collapsing to 0 days; pipelines where an empty schedule row produces 0 days.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/6a8ae61175823920. Report an issue: GitHub.