feat(executor): the increment read goes through the port, and stops fetching 900 products for one - #563
Open
eaitbrahim wants to merge 1 commit into
Open
feat(executor): the increment read goes through the port, and stops fetching 900 products for one#563eaitbrahim wants to merge 1 commit into
eaitbrahim wants to merge 1 commit into
Conversation
…etching 900 products for one #561 gave the port `get_instrument` and wired nothing to it. This wires it, which was the point. Third additive step on #524 and, like the two before it, no live behaviour changes: the same increments reach the same quantization by the same cache. ── THE READ THE PORT WAS BUILT FOR ──────────────────────────────────────────── `_base_increment_for` called `broker.list_products()` -- about 900 rows on Coinbase -- to use ONE field of ONE of them, then picked through raw dicts for `product_id` and `base_increment`. That was the pre-port `CoinbaseClient`'s only catalogue read. `CoinbaseClient.get_instrument()` now answers the port's type too, the same bridge `get_balances` is, so the executor asks one question whether it holds this client or a real adapter. `list_products` stays exactly where it belongs: `keel assets discover`, which genuinely wants the catalogue. ── A CACHING ARGUMENT THAT NO LONGER APPLIES ────────────────────────────────── The old docstring defended writing one cache row per miss "even though the response carries every product", because `Repository.set_state` commits per call and caching all ~900 would mean ~900 fsyncs inside the order-placement path. The argument was sound and the SHAPE was not: asking for one product removes the temptation rather than resisting it, and there is no longer a catalogue to decline to cache. The test that pinned it stays -- one venue answer must still write one row -- with its reasoning updated rather than deleted. ── AND THE ADAPTER THAT REFUSES ─────────────────────────────────────────────── `keel-broker-alpaca` raises `NotImplementedError` from `get_instrument`, deliberately (#561): `None` would tell a caller a symbol is unlisted when the truth is that nobody wrote the read. On THIS path that must land as unknown, not as a crash -- `_base_increment_for` never raises by contract, and an exit that refused to place because a catalogue lookup was unimplemented would be a protective order withheld over a missing convenience. Pinned. Gates: 4304 passed / 3 skipped, ruff clean, mypy clean across 347 files. ── WHAT IS LEFT OF #524 ─────────────────────────────────────────────────────── Only order PLACEMENT. Every read the executor makes -- balances, increments -- now goes through port shapes and needs no further change at the flip. What remains is `preview_order`/`place_order` taking `OrderSpec` instead of raw dicts, and `_build_broker` resolving through `load_broker`. That one is not additive and rewrites every live order path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6yA5khYnJ2qzheArRToQ2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#561 gave the port
get_instrumentand wired nothing to it. This wires it, which was the point.Third additive step on #524, and like the two before it no live behaviour changes — the same
increments reach the same quantization through the same cache.
The read the port was built for
_base_increment_forcalledbroker.list_products()— about 900 rows on Coinbase — to use onefield of one of them, then picked through raw dicts for
product_idandbase_increment. Thatwas the pre-port
CoinbaseClient's only catalogue read.CoinbaseClient.get_instrument()now answers the port's type too — the same bridgeget_balancesis — so the executor asks one question whether it holds this client or a real adapter.
list_productsstays exactly where it belongs:keel assets discover, which genuinely wants thecatalogue.
A caching argument that no longer applies
The old docstring defended writing one cache row per miss "even though the response carries every
product", because
Repository.set_statecommits per call and caching all ~900 would mean ~900fsyncs inside the order-placement path. The argument was sound and the shape was not. Asking
for one product removes the temptation rather than resisting it — there is no longer a catalogue to
decline to cache.
The test that pinned it stays, with its reasoning updated rather than deleted: one venue answer must
still write one row.
And the adapter that refuses
keel-broker-alpacaraisesNotImplementedErrorfromget_instrument, deliberately (#561) —Nonewould tell a caller a symbol is unlisted when the truth is nobody wrote the read.On this path that must land as unknown, not as a crash.
_base_increment_fornever raises bycontract: unknown means send the quantity unquantized, and an exit that refused to place because a
catalogue lookup was unimplemented would be a protective order withheld over a missing convenience.
Now pinned with a test.
Verification
4304 passed / 3 skipped, ruff clean, mypy clean across 347 files.
What's left of #524
Only order placement. Every read the executor makes — balances, increments — now goes through
port shapes and needs no further change at the flip. What remains is
preview_order/place_ordertaking
OrderSpecinstead of raw dicts, and_build_brokerresolving throughload_broker.That one is not additive. It rewrites every live order path, and it's where
_bracket_order_configuration, theConfirmFndual arm and thecapabilities()grandfather clausefinally get deleted. Worth doing as its own reviewed change rather than tacked onto this.
🤖 Generated with Claude Code
https://claude.ai/code/session_01T6yA5khYnJ2qzheArRToQ2