From #192. The Robinhood adapter is deliberately not reachable from live trading: keel/execution/executor.py:486 calls broker.place_order(product_id, side, order_configuration), a different signature from the port's place_order(spec), and keel/commands/_common.py still constructs CoinbaseClient. Nothing calls load_broker().
This issue records what must be true before the port migration (Phase B) wires this venue up, so the migration trips over it rather than discovering it with real money.
Hard capability gaps — not bugs, properties of the venue
- No quote-sized market orders. Robinhood's
market_order_config accepts only asset_quantity; there is no quote_amount for market orders. keel opens positions with MarketIOCByQuote, so Robinhood cannot open positions under the current entry model. The adapter declares market_ioc_quote unsupported and raises UnsupportedOrder rather than synthesizing it from an estimated price — synthesizing would silently change the sizing basis on the live-money path. Wiring this venue for entries requires a deliberate decision about marketable-limit entries (limit_order_config does accept quote_amount), not a quiet fallback.
- No OHLC/candles endpoint. Only
best_bid_ask and estimated_price exist. get_candles raises ValueError for every granularity. Robinhood can be an execution venue only; candle data must come from elsewhere.
- No sandbox. Nothing can be validated against the real venue before it touches real money.
Correctness prerequisites
- Blocked by the review findings issue — B1–B4 are live-money defects the first order that hits them.
- Blocked by the
fees_usd issue — subscription-lapse detection is inert against this venue.
- Duplicate orders on retry.
adapter.py mints a fresh uuid4 client_order_id per place_order call, so no retry is ever deduplicated. requests has no retry configured, so the risk sits at the caller: any executor-level retry after a timeout or a 5xx-after-acceptance places a second live order. The port offers no way to thread an idempotency key in; resolving this likely needs a port change, not an adapter change.
- Pre-flight sizing is unvalidated.
trading_pairs carries min_order_amount, asset_increment, and max_order_size; none are checked before submission, so a sub-minimum or off-increment order finds out at the venue. Note any pre-flight check must not raise on the exit path.
Rate limits
100 req/min sustained, 300 burst, with no backoff anywhere in the transport. get_fee_summary currently resolves the account twice and preview_order adds another call.
From #192. The Robinhood adapter is deliberately not reachable from live trading:
keel/execution/executor.py:486callsbroker.place_order(product_id, side, order_configuration), a different signature from the port'splace_order(spec), andkeel/commands/_common.pystill constructsCoinbaseClient. Nothing callsload_broker().This issue records what must be true before the port migration (Phase B) wires this venue up, so the migration trips over it rather than discovering it with real money.
Hard capability gaps — not bugs, properties of the venue
market_order_configaccepts onlyasset_quantity; there is noquote_amountfor market orders. keel opens positions withMarketIOCByQuote, so Robinhood cannot open positions under the current entry model. The adapter declaresmarket_ioc_quoteunsupported and raisesUnsupportedOrderrather than synthesizing it from an estimated price — synthesizing would silently change the sizing basis on the live-money path. Wiring this venue for entries requires a deliberate decision about marketable-limit entries (limit_order_configdoes acceptquote_amount), not a quiet fallback.best_bid_askandestimated_priceexist.get_candlesraisesValueErrorfor every granularity. Robinhood can be an execution venue only; candle data must come from elsewhere.Correctness prerequisites
fees_usdissue — subscription-lapse detection is inert against this venue.adapter.pymints a freshuuid4client_order_idperplace_ordercall, so no retry is ever deduplicated.requestshas no retry configured, so the risk sits at the caller: any executor-level retry after a timeout or a 5xx-after-acceptance places a second live order. The port offers no way to thread an idempotency key in; resolving this likely needs a port change, not an adapter change.trading_pairscarriesmin_order_amount,asset_increment, andmax_order_size; none are checked before submission, so a sub-minimum or off-increment order finds out at the venue. Note any pre-flight check must not raise on the exit path.Rate limits
100 req/min sustained, 300 burst, with no backoff anywhere in the transport.
get_fee_summarycurrently resolves the account twice andpreview_orderadds another call.