{"record":{"id":"d8307b829ce4aa5f","repo":"TheAlgorithms/Python","slug":"discount-rate-cannot-be-negative","errorCode":null,"errorMessage":"Discount rate cannot be negative","messagePattern":"Discount rate cannot be negative","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"financial/present_value.py","lineNumber":30,"sourceCode":"def present_value(discount_rate: float, cash_flows: list[float]) -> float:\n    \"\"\"\n    >>> present_value(0.13, [10, 20.70, -293, 297])\n    4.69\n    >>> present_value(0.07, [-109129.39, 30923.23, 15098.93, 29734,39])\n    -42739.63\n    >>> present_value(0.07, [109129.39, 30923.23, 15098.93, 29734,39])\n    175519.15\n    >>> present_value(-1, [109129.39, 30923.23, 15098.93, 29734,39])\n    Traceback (most recent call last):\n        ...\n    ValueError: Discount rate cannot be negative\n    >>> present_value(0.03, [])\n    Traceback (most recent call last):\n        ...\n    ValueError: Cash flows list cannot be empty\n    \"\"\"\n    if discount_rate < 0:\n        raise ValueError(\"Discount rate cannot be negative\")\n    if not cash_flows:\n        raise ValueError(\"Cash flows list cannot be empty\")\n    present_value = sum(\n        cash_flow / ((1 + discount_rate) ** i) for i, cash_flow in enumerate(cash_flows)\n    )\n    return round(present_value, ndigits=2)\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n","sourceCodeStart":12,"sourceCodeEnd":43,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/financial/present_value.py#L12-L43","documentation":"Raised by present_value() in financial/present_value.py when discount_rate < 0. The function discounts each cash flow by (1 + discount_rate) ** i; a negative rate would mean money gains value waiting, which the implementation refuses rather than silently computing. discount_rate = 0 is accepted and returns the plain sum.","triggerScenarios":"Calling present_value(rate, cash_flows) with a negative first argument, e.g. present_value(-1, [109129.39, 30923.23]). Only fires when years/rate checks upstream in your own code are absent — this is the function's first validation.","commonSituations":"Central-bank negative-rate eras feeding market data straight into the function, sign flips when converting from yield conventions, or debugging with -1 sentinels. Note: the module's own docstring example uses 0.07 for the happy path, so doctest runs never cover negative-rate paths.","solutions":["Pass a discount_rate >= 0 (0 is valid and returns the undiscounted sum).","If negative rates are genuinely needed (EUR/CHF regimes), implement the discounting manually instead of using this function.","Sanitize market-derived rates at the boundary: validate sign once where data enters your program."],"exampleFix":"# before\npresent_value(market_rate, flows)  # market_rate == -0.002\n\n# after\nif market_rate < 0:\n    pv = sum(flows)  # or custom negative-rate discounting\nelse:\n    pv = present_value(market_rate, flows)","handlingStrategy":"validation","validationCode":"if discount_rate < 0:\n    raise ValueError(f'negative discount rate not supported: {discount_rate}')\npresent_value(discount_rate, cash_flows)","typeGuard":null,"tryCatchPattern":"try:\n    pv = present_value(r, flows)\nexcept ValueError as exc:\n    if 'Discount rate' in str(exc):\n        pv = sum(flows)  # explicit fallback policy\n    else:\n        raise","preventionTips":["Validate rates from market feeds before they reach pricing helpers.","Remember the sibling check: an empty cash_flows list raises next, so validate both."],"tags":["finance","input-validation","valueerror"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}