Skip to content

Prerequisites before wiring Robinhood to the live execution path #198

Description

@eaitbrahim

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    phase-3Execution/rails/agentprerequisiteBlocks other issues; do first

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions