HKUDS/Vibe-Trading · error · MissingExchangeRateError

no {base}/{self.quote_currency} rate for {day}; pass allow_s

Error message

no {base}/{self.quote_currency} rate for {day}; pass allow_stale=True to reuse the most recent earlier rate instead -- stale reuse is flagged on the translated flow, never applied silently

What it means

FxRateTable.get_rate raises MissingExchangeRateError when no exact (base, date) quote exists and allow_stale is False. The library never silently substitutes a different day's rate: stale reuse must be opted into and is flagged on the translated flow.

Source

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

        Returns:
            A tuple of the ``FxRate`` used and whether it was stale (its
            ``date`` is earlier than ``on_date``).

        Raises:
            MissingExchangeRateError: If there is no exact same-day quote and
                either ``allow_stale`` is False, or no earlier quote exists
                (within ``max_staleness_days`` when given).
        """
        base = normalize_currency(base_currency, field_name="base_currency")
        day = normalize_date(on_date)

        exact = self.rates.get((base, day))
        if exact is not None:
            return exact, False

        if not allow_stale:
            raise MissingExchangeRateError(
                f"no {base}/{self.quote_currency} rate for {day}; pass "
                "allow_stale=True to reuse the most recent earlier rate "
                "instead -- stale reuse is flagged on the translated flow, "
                "never applied silently"
            )

        candidates = [
            entry
            for (entry_base, entry_date), entry in self.rates.items()
            if entry_base == base and entry_date <= day
        ]
        if max_staleness_days is not None:
            candidates = [
                entry
                for entry in candidates
                if (day - entry.date).days <= max_staleness_days
            ]
        if not candidates:

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass allow_stale=True (or allow_stale_rates=True on translate_cashflows) to reuse the most recent earlier quote, accepting the staleness flag
  2. Add an FxRate for the exact missing (base, date) — e.g. source a daily FX series covering all settlement dates
  3. Broaden max_staleness_days if the default window excludes an otherwise acceptable earlier quote

Example fix

# before
rate, stale = table.get_rate('EUR', date(2024,3,16))  # Saturday, no quote
# after
rate, stale = table.get_rate('EUR', date(2024,3,16), allow_stale=True)
# or: table.translate_cashflows(flows, allow_stale_rates=True)
Defensive patterns

Strategy: try-catch

Validate before calling

needed = {(f.currency, f.date) for f in flows}
have = set(table.rates)
missing = needed - have - {(c, None) for c in {f.currency for f in flows}}
# approximate; exact-coverage check requires date-level set comparison

Try / catch

from agent.src.entities.cashflow import MissingExchangeRateError
try:
    table.translate_cashflows(flows)
except MissingExchangeRateError:
    translated = table.translate_cashflows(flows, allow_stale_rates=True)

Prevention

When it happens

Trigger: table.get_rate('EUR', date(2024,3,15)) when only a 2024-03-14 EUR quote exists and allow_stale is omitted/False; equivalently translate_cashflows hitting a settlement date with no quote.

Common situations: Weekend/holiday settlement dates with weekday-only FX feeds; a table built from month-end rates used on intra-month dates; forgetting to extend the rates file after a new data range.

Related errors


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