from typing import Optional from .math_round_div import RoundingMode, round_div # (difference * 10000) must stay an exact integer in a JavaScript number, and # the three languages must agree on what is too large. MAX_DIFFERENCE = 900719925474 def percent_change(from_value: int, to_value: int, mode: RoundingMode) -> Optional[int]: """Percentage change from ``from_value`` to ``to_value``, in basis points. Divides by |from_value| so the sign always says which way the value moved, even when the starting value is negative. """ for v in (from_value, to_value): if isinstance(v, bool) or not isinstance(v, int): raise TypeError("percent_change operates on integers only") if from_value == 0: return None difference = to_value - from_value if abs(difference) > MAX_DIFFERENCE: raise ValueError("the change from %d to %d is too large to express exactly" % (from_value, to_value)) return round_div(difference * 10000, abs(from_value), mode)