orders: route an order carrying only conditions through the extended encoder (ibx#325) - #326
Conversation
fd3f59a to
e72b6dd
Compare
|
Two corrections after a closer look at what the test actually guarantees. The forward guard is now real. The commit said a field added to The Python client made the Also confirmed while checking: |
…encoder (ibx#325) `has_extended_attrs()` decides whether an order reaches the encoder that emits the attribute block, and it named thirteen fields. `conditions` was not one of them, nor were `conditions_cancel_order`, `conditions_ignore_rth` or `oca_type` — all four are copied into `OrderAttrs` by `attrs()` and were then thrown away, because the order had already been routed to the plain encoder that emits no condition tags at all. A conditional order therefore went out unconditional. A DAY limit whose only extra attribute is a price condition that is currently false carries no condition tags, so the gateway routes it immediately and it fills — the position is taken now, at the current price, in the direction the caller said they were not ready to trade. Nothing in the message shows a condition was ever asked for, and no error is raised. Setting any one of the thirteen listed attributes, or a TIF other than DAY, made it behave correctly, which is why an order with a realistic attribute bundle never showed it. The predicate now names everything `attrs()` carries. The two have to agree field for field: anything copied into `OrderAttrs` and not named here is dropped in silence. The test has one entry per carried attribute and sets each alone, so removing any arm fails it. It also destructures `OrderAttrs` without a rest pattern, which is the part that survives the next change: adding a field there stops the test compiling until it is accounted for both in the predicate and in the list. The Python client copies the two condition flags across to the Rust order but not `oca_type`, so an OCA type set from Python was replaced by the gateway default before reaching any of this. It crosses now, which is what makes the new arm reachable from that client at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
A second omission in the same Python function, found by the same comparison that turned up
On the test: Two reviewers built plain and extended messages for all 21 encoder shapes and compared 210 pairs: every extended tag set is a superset of the plain one, with matching order type, TIF, quantity, price, routing, currency, side and account. The condition arm is the one that changes broker behaviour; the two flag arms and |
e72b6dd to
83f8fa1
Compare
Summary
has_extended_attrs()decides whether an order reaches the encoder that emits the attribute block. It named thirteen fields, andconditionswas not one of them — nor wereconditions_cancel_order,conditions_ignore_rthoroca_type.OrderAttrsbyattrs(). They were simply never reached: the order had already been routed to the plain encoder, which emits no condition tags at all. Copied, then thrown away.Closes #325.
Why it hides
Setting any one of the thirteen listed attributes, or a TIF other than DAY, makes it behave correctly. Any test using a realistic attribute bundle passes.
Reachable from
EClient::place_orderand the Python client. Not fromContext::submit_*_ex, which takesOrderAttrsdirectly and always routes through the shared encoder.Change
The predicate names everything
attrs()carries. The two have to agree field for field — anything copied intoOrderAttrsand not named by the predicate is dropped in silence.Test
One entry per carried attribute, each set alone on an otherwise default order. Dropping any of the four added arms fails it. It doubles as the checklist: a field added to
attrs()without being added to the predicate fails the test rather than shipping.cargo test --lib: 803 pass. The twoconfig::expiry_testsfailures are pre-existing and unrelated (timezone data).Test plan
cargo test --offline --lib— 803 passed. The 2 failures areconfig::expiry_tests::{named_zone_converts_with_dst, instant_round_trips_to_wire}, which fail on the base commit too: the host has no legacy timezone files (fixed separately in config: resolve the legacy timezone names IB states its times in (ibx#335) #336).cargo check --offline --features python— clean.🤖 Generated with Claude Code