TheAlgorithms/Python · error · ValueError
Discount rate cannot be negative
Error message
Discount rate cannot be negative
What it means
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.
Source
Thrown at financial/present_value.py:30
def present_value(discount_rate: float, cash_flows: list[float]) -> float:
"""
>>> present_value(0.13, [10, 20.70, -293, 297])
4.69
>>> present_value(0.07, [-109129.39, 30923.23, 15098.93, 29734,39])
-42739.63
>>> present_value(0.07, [109129.39, 30923.23, 15098.93, 29734,39])
175519.15
>>> present_value(-1, [109129.39, 30923.23, 15098.93, 29734,39])
Traceback (most recent call last):
...
ValueError: Discount rate cannot be negative
>>> present_value(0.03, [])
Traceback (most recent call last):
...
ValueError: Cash flows list cannot be empty
"""
if discount_rate < 0:
raise ValueError("Discount rate cannot be negative")
if not cash_flows:
raise ValueError("Cash flows list cannot be empty")
present_value = sum(
cash_flow / ((1 + discount_rate) ** i) for i, cash_flow in enumerate(cash_flows)
)
return round(present_value, ndigits=2)
if __name__ == "__main__":
import doctest
doctest.testmod()
View on GitHub (pinned to f5988cc097)
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.
Example fix
# before
present_value(market_rate, flows) # market_rate == -0.002
# after
if market_rate < 0:
pv = sum(flows) # or custom negative-rate discounting
else:
pv = present_value(market_rate, flows) Defensive patterns
Strategy: validation
Validate before calling
if discount_rate < 0:
raise ValueError(f'negative discount rate not supported: {discount_rate}')
present_value(discount_rate, cash_flows) Try / catch
try:
pv = present_value(r, flows)
except ValueError as exc:
if 'Discount rate' in str(exc):
pv = sum(flows) # explicit fallback policy
else:
raise Prevention
- Validate rates from market feeds before they reach pricing helpers.
- Remember the sibling check: an empty cash_flows list raises next, so validate both.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- number_of_years must be > 0
- nominal_annual_percentage_rate must be >= 0
- Cash flows list cannot be empty
- Window size must be a positive integer
- Useful years cannot be less than 1
AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14).
Data as JSON: /api/errors/d8307b829ce4aa5f.
Report an issue: GitHub.