HKUDS/Vibe-Trading · error · ValueError

rate must be finite and strictly positive -- it is quote-per

Error message

rate must be finite and strictly positive -- it is quote-per-base units -- got {rate!r}; a zero or negative rate would silently zero out or flip the sign of every flow translated with it

What it means

An FxRate must be finite and strictly positive because the rate is quote-per-base units: zero would null every translated flow and a negative rate would flip every sign. NaN/inf/0/negative values are rejected at construction.

Source

Thrown at agent/src/entities/cashflow.py:494

                unsupported, or the rate is not finite and strictly positive.
        """
        object.__setattr__(
            self,
            "base_currency",
            normalize_currency(self.base_currency, field_name="base_currency"),
        )
        object.__setattr__(
            self,
            "quote_currency",
            normalize_currency(self.quote_currency, field_name="quote_currency"),
        )
        object.__setattr__(self, "date", normalize_date(self.date))
        try:
            rate = float(self.rate)
        except (TypeError, ValueError) as exc:
            raise ValueError(f"rate must be numeric, got {self.rate!r}") from exc
        if not math.isfinite(rate) or rate <= 0:
            raise ValueError(
                f"rate must be finite and strictly positive -- it is "
                f"quote-per-base units -- got {rate!r}; a zero or negative "
                "rate would silently zero out or flip the sign of every flow "
                "translated with it"
            )
        object.__setattr__(self, "rate", rate)


@dataclass(frozen=True)
class FxRateTable:
    """A lookup of FX rates, every entry quoted against one fixed currency.

    All entries must share the same ``quote_currency``: a table that mixed
    quote currencies would make "translate to X" ambiguous, so that is
    rejected at construction rather than left to whichever rate happens to be
    looked up first.

    Attributes:

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Fix the rate value to the correct positive quote-per-base number (e.g. USD per EUR = 1.0850, not EUR per USD)
  2. If the rate came from a division, correct the direction: rate = quote_amount / base_amount
  3. Reject or skip bad rates at ingest with a finiteness/positivity check

Example fix

# before
FxRate('EUR','USD',d, rate=1/1.0850 if wrong else 0)
# after
FxRate('EUR','USD',d, rate=1.0850)
Defensive patterns

Strategy: validation

Validate before calling

if not (math.isfinite(rate) and rate > 0):
    raise BadRateError(f'{rate!r}')

Type guard

def is_valid_rate(v) -> bool:
    return isinstance(v, (int, float)) and math.isfinite(v) and v > 0

Try / catch

try:
    FxRate(...)
except ValueError as e:
    if 'strictly positive' in str(e):
        rate = 1.0 / rate if rate else None  # possibly inverted source

Prevention

When it happens

Trigger: FxRate(..., rate=0), rate=-1.085, rate=float('nan'), or rate=float('inf'). Also inverted quotes producing nonsense like tiny values are numerically fine but 1/0-derived values are not.

Common situations: Computing rates by division (base/quote instead of quote/base) that yields zero or negative numbers; parsing 'inf' or 'NaN' strings from a feed; unit-test fixtures with rate=0 placeholders.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/33bab4fbcb574641. Report an issue: GitHub.