HKUDS/Vibe-Trading · error · ValueError
valuation on {when} must be numeric, got {raw_value!r}
Error message
valuation on {when} must be numeric, got {raw_value!r} What it means
Each valuation value is coerced with float(); if that raises TypeError/ValueError the item is not numeric and _normalize_valuations reports the date and the offending value. This catches strings like 'N/A', None, Decimal-with-comma formats, or objects without __float__ before they poison the return computation.
Source
Thrown at agent/src/quantlib/performance.py:332
raise ValueError(
f"valuations[{index}] must have exactly two elements "
f"(date, value), got {len(pair)}"
)
raw_items.append((pair[0], pair[1]))
if len(raw_items) < 2:
raise ValueError(
"a return needs an opening and a closing valuation; got "
f"{len(raw_items)}"
)
resolved: list[tuple[date, float]] = []
for raw_date, raw_value in raw_items:
when = normalize_date(raw_date, field_name="valuation date")
try:
value = float(raw_value)
except (TypeError, ValueError) as exc:
raise ValueError(
f"valuation on {when} must be numeric, got {raw_value!r}"
) from exc
if not math.isfinite(value):
raise ValueError(
f"valuation on {when} must be finite, got {raw_value!r}; a "
"missing mark must be fixed at the source, not carried as NaN"
)
resolved.append((when, value))
resolved.sort(key=lambda item: item[0])
for earlier, later in zip(resolved, resolved[1:], strict=False):
if earlier[0] == later[0]:
raise ValueError(
f"two valuations share the date {earlier[0]}; a single day can "
"carry only one mark"
)
return tuple(resolved)
View on GitHub (pinned to 80ffdda44c)
Solutions
- Clean values before calling: coerce with pd.to_numeric(errors='coerce') and then handle NaN deliberately (note NaN is also rejected downstream as non-finite).
- Represent missing marks by omitting the date entirely rather than a placeholder.
- For strings, strip separators: float(s.replace(',', '')).
Example fix
# before
twr = time_weighted_return([('2024-01-01', '1,050.00'), ('2024-12-31', '1,100.00')]) # raises
# after
clean = [(d, float(str(v).replace(',', ''))) for d, v in marks]
twr = time_weighted_return(clean) Defensive patterns
Strategy: validation
Validate before calling
clean = []
for d, v in valuations:
try:
clean.append((d, float(v)))
except (TypeError, ValueError):
continue # or raise with contract/account context
Type guard
def all_values_numeric(vals) -> bool:
try:
return all(float(v) is not None for _, v in vals)
except (TypeError, ValueError):
return False Try / catch
try:
r = time_weighted_return(valuations)
except ValueError as e:
if 'must be numeric' in str(e):
raise MarkDataError(str(e)) from e
raise Prevention
- Coerce DB/CSV columns to float dtype at load time, surfacing errors.
- Avoid locale-formatted strings; strip thousand separators explicitly.
- Use dropna-and-log rather than placeholder strings for missing marks.
When it happens
Trigger: Passing [('2024-01-01', 'N/A'), ...], a value of None from a sparse DB column, or a string '1,050.00' with a thousands separator — float() rejects all of these.
Common situations: CSV import with empty cells becoming None or ''; locale-formatted numbers; ORM models returning Decimal is fine but custom Money objects without __float__ are not; mixed dtype object columns in pandas.
Related errors
- valuation on {when} must be finite, got {raw_value!r}; a mis
- valuations[{index}] must be a (date, value) pair, got {type(
- valuations[{index}] must have exactly two elements (date, va
- a return needs an opening and a closing valuation; got {len(
- {model}: {name} must be a number, got {value!r}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/f101738e7a2bdacc.
Report an issue: GitHub.