HKUDS/Vibe-Trading · error · ValueError

cash flow on {when} coincides with the opening valuation and

Error message

cash flow on {when} coincides with the opening valuation and flow_timing={FLOW_TIMING_END!r} places it inside the opening value, where it would be counted twice. Use flow_timing={FLOW_TIMING_START!r}, or start the valuations one period earlier.

What it means

With flow_timing=END, a flow is treated as arriving at the end of its sub-period, so a flow on the same date as the opening valuation would be baked into the opening value and counted again as a flow — double counting. The library refuses this combination instead of producing an inflated/deflated return.

Source

Thrown at agent/src/quantlib/performance.py:489

    Returns:
        One net flow per interval, so ``len(dates) - 1`` entries.

    Raises:
        ValueError: If a flow falls outside the valuation window. Dropping it
            silently would move the client's money into the manager's return.
    """
    first, last = dates[0], dates[-1]
    buckets = [0.0] * (len(dates) - 1)
    for when, amount in flows:
        if when < first or when > last:
            raise ValueError(
                f"cash flow on {when} lies outside the valuation window "
                f"{first}..{last}; extend the valuations or trim the flows "
                "rather than dropping the flow"
            )
        if flow_timing == FLOW_TIMING_END:
            if when == first:
                raise ValueError(
                    f"cash flow on {when} coincides with the opening valuation "
                    f"and flow_timing={FLOW_TIMING_END!r} places it inside the "
                    "opening value, where it would be counted twice. Use "
                    f"flow_timing={FLOW_TIMING_START!r}, or start the "
                    "valuations one period earlier."
                )
            # First interval whose closing date is at or after the flow.
            index = next(k for k in range(1, len(dates)) if dates[k] >= when) - 1
        else:
            if when == last:
                raise ValueError(
                    f"cash flow on {when} coincides with the closing valuation "
                    f"and flow_timing={FLOW_TIMING_START!r} places it after the "
                    "window ends. Use flow_timing="
                    f"{FLOW_TIMING_END!r}, or extend the valuations."
                )
            # Last interval whose opening date is at or before the flow.
            index = max(k for k in range(len(dates) - 1) if dates[k] <= when)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass flow_timing=FLOW_TIMING_START for same-day opening flows.
  2. Start the valuations one period earlier so the opening mark predates the flow.
  3. Alternatively, fold the same-day flow into the opening valuation and drop the flow record.

Example fix

# before
time_weighted_return(valuations=marks, flows=flows, flow_timing=FLOW_TIMING_END)
# flow lands on marks[0].date -> ValueError

# after
from quantlib.performance import FLOW_TIMING_START
time_weighted_return(valuations=marks, flows=flows, flow_timing=FLOW_TIMING_START)
Defensive patterns

Strategy: validation

Validate before calling

if flow_timing == FLOW_TIMING_END:
    assert all(f.date != marks[0][0] for f in selected_flows), 'flow on opening valuation date'

Try / catch

try:
    twr = time_weighted_return(marks, flows, flow_timing=FLOW_TIMING_END)
except ValueError as e:
    if 'coincides with the opening valuation' in str(e):
        twr = time_weighted_return(marks, flows, flow_timing=FLOW_TIMING_START)
    else:
        raise

Prevention

When it happens

Trigger: Calling time_weighted_return with flow_timing=FLOW_TIMING_END (the end-of-day convention) while an external flow's date equals the first valuation date.

Common situations: An account funded on the first reporting date (contribution and opening mark share a day); using the default flow timing with same-day deposit; daily marks where flows land exactly on mark dates.

Related errors


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