{"record":{"id":"19070c7ff5247841","repo":"TheAlgorithms/Python","slug":"daily-interest-rate-must-be-0","errorCode":null,"errorMessage":"daily_interest_rate must be >= 0","messagePattern":"daily_interest_rate must be >= 0","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"financial/interest.py","lineNumber":36,"sourceCode":"    >>> simple_interest(5500.0, 0.01, 100)\n    5500.0\n    >>> simple_interest(10000.0, -0.06, 3)\n    Traceback (most recent call last):\n        ...\n    ValueError: daily_interest_rate must be >= 0\n    >>> simple_interest(-10000.0, 0.06, 3)\n    Traceback (most recent call last):\n        ...\n    ValueError: principal must be > 0\n    >>> simple_interest(5500.0, 0.01, -5)\n    Traceback (most recent call last):\n        ...\n    ValueError: days_between_payments must be > 0\n    \"\"\"\n    if days_between_payments <= 0:\n        raise ValueError(\"days_between_payments must be > 0\")\n    if daily_interest_rate < 0:\n        raise ValueError(\"daily_interest_rate must be >= 0\")\n    if principal <= 0:\n        raise ValueError(\"principal must be > 0\")\n    return principal * daily_interest_rate * days_between_payments\n\n\ndef compound_interest(\n    principal: float,\n    nominal_annual_interest_rate_percentage: float,\n    number_of_compounding_periods: float,\n) -> float:\n    \"\"\"\n    >>> compound_interest(10000.0, 0.05, 3)\n    1576.2500000000014\n    >>> compound_interest(10000.0, 0.05, 1)\n    500.00000000000045\n    >>> compound_interest(0.5, 0.05, 3)\n    0.07881250000000006\n    >>> compound_interest(10000.0, 0.06, -4)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/financial/interest.py#L18-L54","documentation":"Raised by simple_interest() in financial/interest.py when daily_interest_rate < 0. Zero rate is allowed (interest is then 0), but a negative rate would produce negative interest that the doctest contract does not model. It is the second check, so days_between_payments is already valid when it fires.","triggerScenarios":"simple_interest(10000.0, -0.06, 3); rates computed as (new_rate - old_rate) deltas; percent-to-decimal conversion bugs that introduce a sign.","commonSituations":"Passing 6 instead of 0.06 combined with a sign flip from discount arithmetic; negative promotional rates in product data; scraping a rate field that includes a unicode minus.","solutions":["Pass the daily rate as a non-negative decimal fraction (0.0005 for 0.05%/day).","If converting from an annual percentage, divide consistently and clamp at 0 only after confirming negatives are data errors.","Validate rate >= 0 in your ingestion layer with a clear error naming the field."],"exampleFix":"# before\nsi = simple_interest(10000.0, -0.06, 3)  # ValueError\n\n# after\nsi = simple_interest(10000.0, 0.0006, 3)","handlingStrategy":"validation","validationCode":"if daily_interest_rate < 0:\n    raise InputError(\"daily rate must be >= 0 as a decimal (0.0005 for 0.05%/day)\")","typeGuard":"def valid_non_negative_rate(r) -> bool:\n    return isinstance(r, (int, float)) and r >= 0","tryCatchPattern":"try:\n    si = simple_interest(principal, daily_rate, days)\nexcept ValueError as exc:\n    raise InputError(str(exc)) from exc","preventionTips":["Keep rates as decimal fractions with a documented convention.","Sanitize scraped rate strings (unicode minus, %, commas).","Check magnitudes too: 6 instead of 0.06 silently overstates interest 100x."],"tags":["finance","interest","rate","validation"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}