{"record":{"id":"7f262f4bc39cae83","repo":"TheAlgorithms/Python","slug":"nominal-annual-interest-rate-percentage-must-be","errorCode":null,"errorMessage":"nominal_annual_interest_rate_percentage must be >= 0","messagePattern":"nominal_annual_interest_rate_percentage must be >= 0","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"financial/interest.py","lineNumber":70,"sourceCode":"    >>> compound_interest(0.5, 0.05, 3)\n    0.07881250000000006\n    >>> compound_interest(10000.0, 0.06, -4)\n    Traceback (most recent call last):\n        ...\n    ValueError: number_of_compounding_periods must be > 0\n    >>> compound_interest(10000.0, -3.5, 3.0)\n    Traceback (most recent call last):\n        ...\n    ValueError: nominal_annual_interest_rate_percentage must be >= 0\n    >>> compound_interest(-5500.0, 0.01, 5)\n    Traceback (most recent call last):\n        ...\n    ValueError: principal must be > 0\n    \"\"\"\n    if number_of_compounding_periods <= 0:\n        raise ValueError(\"number_of_compounding_periods must be > 0\")\n    if nominal_annual_interest_rate_percentage < 0:\n        raise ValueError(\"nominal_annual_interest_rate_percentage must be >= 0\")\n    if principal <= 0:\n        raise ValueError(\"principal must be > 0\")\n\n    return principal * (\n        (1 + nominal_annual_interest_rate_percentage) ** number_of_compounding_periods\n        - 1\n    )\n\n\ndef apr_interest(\n    principal: float,\n    nominal_annual_percentage_rate: float,\n    number_of_years: float,\n) -> float:\n    \"\"\"\n    >>> apr_interest(10000.0, 0.05, 3)\n    1618.223072263547\n    >>> apr_interest(10000.0, 0.05, 1)","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/financial/interest.py#L52-L88","documentation":"Raised by compound_interest() in financial/interest.py when nominal_annual_interest_rate_percentage < 0. The parameter is expected as a decimal fraction per period (0.05 for 5%, per the doctest compound_interest(10000.0, 0.05, 3) => 1576.25); negative rates are rejected, and (1 + rate)**n would still be computable but is outside the modeled contract. It is the second check, after periods.","triggerScenarios":"compound_interest(10000.0, -3.5, 3.0); passing -0.05 from a sign-flipped discount computation; passing a percentage like -5 instead of -0.05 (the latter raises, the magnitude error does not — see tips).","commonSituations":"Sign errors when rates are stored as spreads (lend minus borrow); negative central-bank rates in market data feeds; unicode minus signs from scraped tables.","solutions":["Pass the rate as a non-negative decimal fraction (0.05 for 5% per period).","Sanitize market data: strip unicode minus, then check sign before calling.","Double-check the unit: this parameter is a per-period decimal, so 5% monthly compounding uses 0.05, not 5."],"exampleFix":"# before\nci = compound_interest(10000.0, -3.5, 3.0)  # ValueError\n\n# after\nci = compound_interest(10000.0, 0.05, 3.0)  # matches doctest: 1576.25...","handlingStrategy":"validation","validationCode":"if nominal_annual_interest_rate_percentage < 0:\n    raise InputError(\"rate must be >= 0 as a decimal fraction (0.05 for 5%)\")","typeGuard":"def valid_rate(r) -> bool:\n    return isinstance(r, (int, float)) and r >= 0","tryCatchPattern":"try:\n    ci = compound_interest(principal, rate, periods)\nexcept ValueError as exc:\n    raise InputError(str(exc)) from exc","preventionTips":["Pass 0.05 for 5%, per the doctest — verify magnitude as well as sign.","Strip sign artifacts from spread-based rate fields before calling.","Centralize percent->decimal conversion in one helper."],"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"}