Skip to content

Broker port has no bracket/OCO order kind — live trailing stops, BE-rolls and scale_out are blocked on it #502

Description

@eaitbrahim

The finding

Split out of #442. keel's live exits ride ONE native Coinbase trigger-bracket placed at entry (keel/execution/executor.py::_bracket_order_configurationtrigger_bracket_gtc, built as a raw dict against the pre-port CoinbaseClient). Moving a stop means cancel-and-replace of that bracket (_roll_stop), and a partial exit means resizing it.

The broker port has no bracket/OCO order kind at all: OrderSpec is MarketIOCByQuote / MarketIOCByBase / LimitGTC / StopLimitGTC (packages/keel-broker-coinbase/keel_broker_coinbase/translate.py::to_order_configuration, assert_never on anything else). The bracket reaches the venue only because the executor bypasses the port with a raw configuration dict — so the three live exit primitives (trail_stop_atr, roll_to_break_even, scale_out) have no port-clean path to production. #442 wired the exit POLICY (ratchet-only ATR trailing, break-even roll) on the sim/backtest engines only and left the live primitives deliberately unwired pending this issue.

scale_out additionally carries its own prerequisites, pinned by the tripwire test tests/execution/test_executor.py::test_scale_out_has_no_production_caller: before it may be wired it must (1) cancel/resize the resting bracket that commits the FULL position (a partial SELL against it is rejected, or fills and leaves an oversized bracket able to sell more than is held), and (2) record a trade_outcomes row for the partial exit — otherwise rail 16 counts a net winner as a loss.

Why it matters

Reading executor.py in isolation still overstates what keel does live: the module implements and unit-tests stop management that nothing in the agent cycle calls. The honest docstring now says so, but the honest FIX is a port that can express the orders a managed position needs.

Scope

  • Add a bracket/OCO OrderSpec kind to keel-broker-api + the Coinbase adapter's to_order_configuration translation (and the other adapters' explicit refusal, where they cannot support it).
  • A live per-cycle stop-management step in agent.run_once that calls trail_stop_atr/roll_to_break_even per rule family — the per-family params (trail_atr_mult, be_roll_rr on pullback_continuation/rsi_meanrev) already exist and are wired through the sim/backtest engines; turtle stays on its Donchian exit by choice.
  • scale_out: bracket resize + trade_outcomes recording, then remove the tripwire test.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions