HKUDS/Vibe-Trading · error · ValueError
a kind cannot be both external and internal; overlapping: {'
Error message
a kind cannot be both external and internal; overlapping: {', '.join(sorted(overlap))} What it means
external_flows classifies each cash-flow kind as either external (crosses the portfolio boundary, affects return) or internal (rebalancing inside the portfolio, ignored). This error fires when a kind appears in both the external and internal sets (or their defaults overlap with your custom sets), making the classification ambiguous.
Source
Thrown at agent/src/quantlib/performance.py:401
internal, because assuming would understate the flow adjustment and
return a plausible wrong number.
"""
if flows is None:
return ()
external = (
DEFAULT_EXTERNAL_KINDS
if external_kinds is None
else frozenset(normalize_kind(kind) for kind in external_kinds)
)
internal = (
DEFAULT_INTERNAL_KINDS
if internal_kinds is None
else frozenset(normalize_kind(kind) for kind in internal_kinds)
)
overlap = external & internal
if overlap:
raise ValueError(
"a kind cannot be both external and internal; overlapping: "
f"{', '.join(sorted(overlap))}"
)
selected: list[tuple[date, float]] = []
for flow in flows:
if flow.is_valuation:
continue
if flow.kind in external:
selected.append((flow.date, -flow.amount))
elif flow.kind not in internal:
raise ValueError(
f"cash-flow kind {flow.kind!r} on {flow.date} is classified "
"neither external nor internal, so it cannot be treated as "
"either. Pass external_kinds=[...] or internal_kinds=[...] to "
"say which side of the portfolio boundary it crosses. Known "
f"external: {', '.join(sorted(external))}. Known internal: "
f"{', '.join(sorted(internal))}."View on GitHub (pinned to 80ffdda44c)
Solutions
- Remove the overlapping kind(s) listed in the error message from one of the two sets.
- Prefer overriding only one of external_kinds/internal_kinds and let the defaults supply the other, after checking the shipped default sets.
- Assert disjointness in your config before calling: external & internal == set().
Example fix
# before
external_flows(flows,
external_kinds=['dividend', 'fee'],
internal_kinds=['fee', 'rebalance'], # 'fee' in both -> ValueError
)
# after
external_flows(flows,
external_kinds=['dividend', 'fee'],
internal_kinds=['rebalance'],
) Defensive patterns
Strategy: validation
Validate before calling
ext, intl = set(external_kinds or DEFAULT_EXTERNAL_KINDS), set(internal_kinds or DEFAULT_INTERNAL_KINDS)
assert not (ext & intl), f'overlap: {sorted(ext & intl)}' Try / catch
try:
flows_ext = external_flows(flows, external_kinds=ext, internal_kinds=intl)
except ValueError as e:
if 'both external and internal' in str(e):
overlap = ext & intl
intl -= overlap # resolve: external wins
flows_ext = external_flows(flows, external_kinds=ext, internal_kinds=intl)
else:
raise Prevention
- Define the classification once in config and unit-test disjointness.
- Override only one of the two kind sets; derive the other from defaults minus the override.
- Log the active external/internal sets at startup.
When it happens
Trigger: Calling external_flows, time_weighted_return, modified_dietz_return, or money_weighted_return and passing external_kinds={'dividend'} while 'dividend' is also in internal_kinds, or passing a custom set that overlaps with DEFAULT_INTERNAL_KINDS/DEFAULT_EXTERNAL_KINDS.
Common situations: Customizing external_kinds to include 'fee' or 'dividend' without removing it from internal_kinds; copying classification lists from another system where the same label means different things; defaults changing across library versions so a previously-fine custom list now overlaps.
Related errors
- cash-flow kind {flow.kind!r} on {flow.date} is classified ne
- cash flow on {when} lies outside the valuation window {first
- brinson_fachler needs at least one sector
- portfolio and benchmark weights must sum to the same total f
- sector {sector!r} has portfolio weight {w_p!r} but no portfo
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/5a0ae5b83ee95cf4.
Report an issue: GitHub.