Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions skills/fomo-kernel/engine/market_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,9 +822,31 @@ def to_price_feed_envelope(bundle, currency_by_ticker=None, instruments_only=Tru

``currency_by_ticker`` is required for any ticker that is not USD:
``price_feed.currency_conflicts`` compares this against the trades, and
guessing here would either invent a conflict or hide one. Returns ``None``
when the bundle priced nothing — there is no such thing as an envelope with
no prices, and ``parse`` rightly refuses one.
guessing here would either invent a conflict or hide one.

**Returns ``None`` when no instrument row survived** — nothing the bundle
priced was both inside this envelope's scope (a benchmark is outside it
unless ``instruments_only`` is false, so a bundle whose only successes are
benchmarks yields no envelope) and reconcilable onto one split basis by the
rule above. Stated as one condition rather than a list of causes on purpose:
the claim this paragraph replaces went stale by enumerating. That is this
lane's own rule and not a restatement of what ``price_feed.parse`` will
accept: this envelope is defined over instrument closes and dates itself
from them, since ``as_of`` is ``max(row date)`` read off the rows themselves,
so with no rows there is no observed session to declare one from. Nothing is
concealed by returning ``None`` — a dropped instrument is already recorded as
a gap on the bundle before this point, so the coverage fact outlives the
envelope, and the caller degrades to the pre-#605 unpriced answer rather than
raising into a review.

One consequence worth naming, because it is not obvious from the return
value: a currency rate this bundle *did* resolve is discarded along with it,
as ``fx`` is assembled below this point. A book whose held tickers all fail
to price while its currency pair resolves therefore reaches ``consider``
rateless, even though the bundle counts as ``usable`` on the strength of that
very rate. Whether such a rate should be able to travel on its own is a
question about this lane, open at the time of writing; it is not answered by
what ``parse`` does or does not accept on the other side.
"""
currency_by_ticker = currency_by_ticker or {}
skipped = []
Expand Down
9 changes: 6 additions & 3 deletions tests/test_market_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,9 +897,12 @@ def test_i_the_declared_currency_is_the_callers_not_a_default():


def test_i_a_bundle_that_priced_nothing_yields_no_envelope():
"""`parse` rightly refuses an envelope with no prices, so the builder must
return None rather than hand one over: the caller then degrades to the
pre-#605 answer instead of raising into a review."""
"""This envelope is defined over instrument closes and dates itself from
them — `as_of` is `max(row date)` — so with no rows there is no observed
session to declare one from, and the builder returns None rather than hand
over an envelope it cannot date: the caller then degrades to the pre-#605
answer instead of raising into a review. That is this lane's own rule, not a
claim about which envelopes `price_feed.parse` accepts."""
with provider() as p:
bundle = p.resolve(_request(instruments=["DEAD"], benchmarks=[], currencies=[]))
assert market_data.to_price_feed_envelope(bundle) is None
Expand Down
Loading