Broker APIs

The Broker Adapter Pattern: One Strategy, Multiple Brokers

How to isolate broker-specific authentication, symbols and order formats behind one internal interface.

Broker interface showing positions, stop loss and take profit
Hands-on screenshot: an adapter should translate strategy intent into broker-specific orders and state.

How to isolate broker-specific authentication, symbols and order formats behind one internal interface.

Updated 2026-09-06Broker APIsPractical guide2 min read

In plain English

This guide treats the broker as an external API with its own authentication, symbols, limits and failure states. A successful HTTP request is not always the same as a confirmed final action.

authenticationdemorate limitorder confirmation

Why adapters matter

Broker APIs differ in authentication, symbol names, order parameters, response structures and session behavior. If strategy code calls a broker SDK directly everywhere, changing broker becomes a rewrite.

Define your own small interface

from typing import Protocol

class Broker(Protocol):
    def get_price(self, symbol: str) -> float: ...
    def get_positions(self) -> list[dict]: ...
    def place_order(self, symbol: str, side: str, size: float) -> dict: ...
    def close_position(self, position_id: str) -> dict: ...

Then implement CapitalBroker, OandaBroker, IBKRBroker and so on. Strategy code only sees the protocol.

Normalize symbols

Create a mapping layer. Your internal name might be BTCUSD, while different providers may use an epic, conid, instrument identifier or another symbol format.

Normalize results too

{
  "ok": true,
  "broker": "example",
  "order_id": "123",
  "status": "accepted",
  "raw": {...}
}

Keep the raw response for diagnostics, but let the rest of the application use your normalized fields.

Practical lesson: put broker-specific retry rules inside the adapter. A strategy should not know that one provider uses session tokens while another uses OAuth.

Before you rely on this in production

  • Demo/live environments are clearly separated.
  • Authentication renewal is handled.
  • Position/order state is checked before retrying.
  • Rate limits and final confirmations are logged.