HKUDS/Vibe-Trading · error · ValueError
two valuations share the date {earlier[0]}; a single day can
Error message
two valuations share the date {earlier[0]}; a single day can carry only one mark What it means
This error is raised by _normalize_valuations when two (or more) portfolio valuations in the input resolve to the same calendar date. A single day can carry only one mark because return calculations need an unambiguous ordering of valuations over time; duplicate dates make the interval between them zero-length and the period return undefined.
Source
Thrown at agent/src/quantlib/performance.py:345
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)
def external_flows(
flows: CashFlowSeries | Iterable[CashFlow] | None,
*,
external_kinds: Iterable[str] | None = None,
internal_kinds: Iterable[str] | None = None,
) -> tuple[tuple[date, float], ...]:
"""Select the boundary-crossing flows and restate them portfolio-side.
The returned amounts are the **negation** of ``CashFlow.amount``: the input
is holder-perspective (a contribution is cash leaving the client, hence
negative), the output is portfolio-perspective (a contribution is cash
arriving, hence positive). This is the only place in the module where thatView on GitHub (pinned to 80ffdda44c)
Solutions
- Deduplicate valuations by date before calling the API (keep the last mark per day, e.g. dict(date -> value)).
- If two marks on one day are genuinely different (e.g. pre- and post-contribution), decide which one represents the official end-of-day value and drop the other.
- If you need to represent a flow on a valuation day, pass it as a flow, not as a second valuation.
- Check the input pipeline for duplicate rows or datetime-to-date coercion producing collisions.
Example fix
# before
time_weighted_return(valuations=[
(date(2024,1,15), 100_000.0),
(date(2024,1,15), 105_000.0), # duplicate date -> ValueError
(date(2024,2,15), 110_000.0),
], flows=[])
# after
merged = {d: v for d, v in [
(date(2024,1,15), 100_000.0),
(date(2024,1,15), 105_000.0), # last wins
(date(2024,2,15), 110_000.0),
]}
time_weighted_return(valuations=sorted(merged.items()), flows=[]) Defensive patterns
Strategy: validation
Validate before calling
def dedupe_valuations(valuations):
merged = {}
for when, value in valuations:
d = when if isinstance(when, date) else when.date() if hasattr(when, 'date') else parse(when)
merged[d] = value # last mark per day wins
return sorted(merged.items()) Type guard
def has_unique_valuation_dates(valuations) -> bool:
ds = [normalize_date(v[0]) for v in valuations]
return len(set(ds)) == len(ds) Try / catch
try:
twr = time_weighted_return(valuations, flows)
except ValueError as e:
if 'share the date' in str(e):
valuations = dedupe_valuations(valuations)
twr = time_weighted_return(valuations, flows)
else:
raise Prevention
- Deduplicate valuation rows by date during ingestion.
- Store valuations in a date-keyed mapping so duplicates cannot accumulate.
- Warn on intraday marks being collapsed to one date.
When it happens
Trigger: Calling time_weighted_return, modified_dietz_return, or money_weighted_return with a valuations list containing two entries whose dates normalize to the same day, e.g. two CashFlow/valuation records on 2024-01-15 (same date given as date vs datetime vs ISO string), or the same date supplied twice from a CSV import.
Common situations: Intraday marks imported as datetimes that collapse to the same date; duplicate rows in a valuation feed; a valuation recorded at midnight boundary; merging two data sources that both contain the period-end mark.
Related errors
- cash-flow kind {flow.kind!r} on {flow.date} is classified ne
- valuations[{index}] needs both 'date' and 'value'
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
- delay requires n >= 1 (lookahead ban)
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/8cbf1b28a1d4eb6c.
Report an issue: GitHub.