verify_cash_account() refuses a margin-postured account, fails closed on a classification it cannot read, and runs at broker build so no engine path ever sees a broker on a posture keel does not trade. It is implemented only in keel-broker-alpaca (/v2/account's multiplier must be 1) and called only on _build_broker's alpaca branch (keel/commands/_common.py:340).
Coinbase has no equivalent, and Coinbase is the venue this deployment actually trades.
The hole
keel's long-only guarantee is four layers deep — the engine hardcodes Side.BUY for entries, Setup.__post_init__ refuses a non-long setup, engine._long_shaped_ok refuses non-long geometry, and rails 18/19 refuse non-spot instrument shapes. All four are about what keel asks for. None of them is about what the venue does with the ask.
If the underlying account has margin privileges or overdraft enabled at the broker level, a SELL for slightly more than the held quantity does not fail — the venue borrows the difference and opens a short. keel's four layers are all satisfied: it asked for a spot SELL of a long position it believes it holds. The short is created by the venue, out of band, and nothing in keel would know.
This is bay' ma la yamlik (بيع ما لا يملك) reached by a route riba-based reasoning does not cover: "Do not sell what is not with you" (Sunan an-Nasa'i 4613, Abu Dawud 3503). The borrow's interest is a second violation; the sale of what is not possessed is the first and more direct one.
Why it belongs at broker build, not in a rail
_common.py:331-339 already argues this and the argument holds for Coinbase:
Refusing HERE -- rather than at order time -- is what makes it a posture and not a rail: guards are broker-less by design, and a per-order raise could fire on an exit path, where a refusal can trap a position.
A margin-enabled account is a property of the deployment, not of an order. Discovering it mid-exit would be the worst possible moment.
Scope
Related
#372 (the alpaca posture and its reasoning), #233 (the attestation pattern if a venue read turns out impossible), and the sibling issues on SELL-side balance clamping and the orphan-bracket sweep.
verify_cash_account()refuses a margin-postured account, fails closed on a classification it cannot read, and runs at broker build so no engine path ever sees a broker on a posture keel does not trade. It is implemented only inkeel-broker-alpaca(/v2/account'smultipliermust be 1) and called only on_build_broker's alpaca branch (keel/commands/_common.py:340).Coinbase has no equivalent, and Coinbase is the venue this deployment actually trades.
The hole
keel's long-only guarantee is four layers deep — the engine hardcodes
Side.BUYfor entries,Setup.__post_init__refuses a non-long setup,engine._long_shaped_okrefuses non-long geometry, and rails 18/19 refuse non-spot instrument shapes. All four are about what keel asks for. None of them is about what the venue does with the ask.If the underlying account has margin privileges or overdraft enabled at the broker level, a SELL for slightly more than the held quantity does not fail — the venue borrows the difference and opens a short. keel's four layers are all satisfied: it asked for a spot SELL of a long position it believes it holds. The short is created by the venue, out of band, and nothing in keel would know.
This is bay' ma la yamlik (بيع ما لا يملك) reached by a route riba-based reasoning does not cover: "Do not sell what is not with you" (Sunan an-Nasa'i 4613, Abu Dawud 3503). The borrow's interest is a second violation; the sale of what is not possessed is the first and more direct one.
Why it belongs at broker build, not in a rail
_common.py:331-339already argues this and the argument holds for Coinbase:A margin-enabled account is a property of the deployment, not of an order. Discovering it mid-exit would be the worst possible moment.
Scope
verify_cash_account()on the Coinbase adapter, reading the venue's own account classification._build_broker's coinbase branch, same as alpaca's.Related
#372 (the alpaca posture and its reasoning), #233 (the attestation pattern if a venue read turns out impossible), and the sibling issues on SELL-side balance clamping and the orphan-bracket sweep.