arrow_backBACK TO LOW-LATENCY TRADING SYSTEMS & ALGO TRADING — FROM THE ORDER BOOK TO A LIVE RETAIL ALGO
Lesson 09Low-Latency Trading Systems & Algo Trading — From the Order Book to a Live Retail Algo5 min read

A Multi-Broker Framework

October 28, 2026

TL;DR

Don't scatter broker-specific code through your strategy — put it behind a single BrokerAdapter interface (place_order, cancel, positions, subscribe) so your strategy, risk and UI speak one common language and never know which broker they're on. Each broker gets an adapter that translates those common calls to that broker's API and hides the messy differences: auth and token refresh, symbol/instrument-id mapping, order-field naming, lot and tick sizes, rate limits and retry/backoff, reconnection and re-subscription, and error-code normalisation — exposing one normalised model for orders, fills, positions and ticks. Zerodha Kite Connect is the worked example for India (REST for orders, WebSocket for ticks, a daily access-token login). The payoff: adding a new broker means writing one adapter, with your strategies, risk and UI unchanged — and the same design lets you add a crypto exchange later (Lesson 13) as just another adapter. Educational, not financial advice.

Your strategy should care about trading, not about the quirks of a particular broker’s API. Yet broker APIs are messy and all different — different authentication, different field names, different symbol formats, different rate limits, different ways of disconnecting. If you let those differences leak into your strategy code, you get a tangle that’s painful to maintain and impossible to move to another broker. The fix is a classic piece of software design applied to trading: a broker-adapter layer. This lesson builds that abstraction, which also sets up the crypto reuse in Lesson 13.

One Interface, Many Brokers

The core idea: define a single BrokerAdapter interface — a small set of operations your system needs — and make every broker implement it. Your strategy, risk layer and UI talk only to that interface, in one common language, and never know (or care) which broker is behind it.

One interface, many brokers: a broker-adapter layer so your strategy never knows which broker it's on. Your strategy and OMS (speaks ONE common language) connects down to the BrokerAdapter interface: place_order, cancel, positions, subscribe. Below it, three adapters: Zerodha Kite (REST plus WebSocket), Broker B (different auth, different fields), Crypto exchange (24/7, same shape, Lesson 13). Each adapter translates the common calls to that broker's API. What the adapter hides (so your strategy stays clean): auth and token refresh, symbol/instrument-id mapping, order-field naming, lot sizes and tick sizes; rate limits and retry/backoff, reconnection and re-subscription, error-code normalisation; a common normalised model for orders, fills, positions and ticks, one shape everywhere. Add a new broker equals write one adapter; your strategies, risk and UI don't change at all

The interface is deliberately small — the operations every broker must support:

  • place_order(...) — send an order (with your normalised fields).
  • cancel(order_id) — cancel a resting order.
  • positions() / orders() — query current positions and order states.
  • subscribe(instruments) — subscribe to market data (Lesson 3).
  • plus callbacks/events for fills, order updates, and ticks.

Your strategy calls place_order and gets back a normalised result; it never writes broker-specific code. Behind the interface, each adapter is a translator: it takes these common calls and turns them into the specific API calls, field names, and formats that one particular broker expects — and translates the responses back into your common, normalised model.

What the Adapter Hides

The value of the adapter is everything ugly it keeps out of your strategy. A good adapter handles:

  • Auth and token refresh. Many broker APIs (including Kite) use a login flow that produces a session/access token, sometimes valid only for the day. The adapter manages obtaining and refreshing it, so your strategy never thinks about auth.
  • Symbol / instrument-id mapping. Every broker and exchange identifies instruments differently (a trading symbol, a numeric token, an exchange code). The adapter maps between your internal symbol and the broker’s identifiers.
  • Order-field naming and semantics. One broker says transaction_type: BUY, another side: B; order types, product types (intraday vs delivery), and validity flags all differ. The adapter normalises them.
  • Lot sizes and tick sizes. Derivatives trade in fixed lots and minimum price increments (Lesson 1); the adapter knows and enforces them.
  • Rate limits, retry and backoff. Brokers cap how many orders/requests per second you may send. The adapter respects those caps (tying into the rate-limit risk check of Lesson 8) and retries transient failures with sensible backoff.
  • Reconnection and re-subscription. When the market-data WebSocket drops (Lesson 3), the adapter reconnects, re-authenticates, re-subscribes, and re-snapshots — so your strategy just keeps receiving clean ticks.
  • Error-code normalisation. Each broker returns its own error codes and messages; the adapter maps them into a common set your system understands (retryable vs fatal, rejected vs failed).

What comes out of the adapter is a common normalised model — one shape for orders, fills, positions and ticks, identical regardless of broker. That normalisation is the whole point: your strategy, OMS and risk layer (Lesson 8) operate on one consistent model forever.

Zerodha Kite Connect: the Worked Example

For Indian retail, Zerodha’s Kite Connect is the common broker API, and it’s a good concrete example of what an adapter wraps. In rough shape (check current docs before building — APIs change):

  • Auth is a login flow that yields a daily access token you attach to requests; your adapter handles obtaining it (often a once-a-day step) and attaching it.
  • Orders go over a REST API — place, modify, cancel — with Kite’s specific fields (exchange, tradingsymbol, transaction_type, quantity, order_type, product, etc.).
  • Market data comes over a WebSocket ticker you subscribe to with instrument tokens, in Kite’s binary tick format, which your adapter decodes into your normalised tick model.
  • Rate limits apply (orders per second, requests per minute); your adapter enforces them.

Your KiteAdapter implements the common BrokerAdapter interface by translating each common call into these Kite specifics and decoding Kite’s responses back into your normalised model. Your strategy, meanwhile, just calls place_order — blissfully unaware it’s Kite underneath. (The same is true if you later add a second Indian broker: a new adapter, nothing else changes.)

Why This Pays Off

The design discipline here delivers concrete wins:

  • Adding a broker = writing one adapter. Want to run on a second broker, or switch? Implement the interface once; your strategies, risk layer, OMS and UI don’t change at all. Without the adapter layer, a broker switch means touching code everywhere.
  • Testability. You can write a mock/paper adapter that implements the same interface with simulated fills — which is exactly how paper trading (Lesson 13) works: swap the live adapter for a simulated one, same strategy code.
  • Isolation of failure and change. When a broker changes its API or misbehaves, the blast radius is one adapter, not your whole system.
  • It extends to crypto. A crypto exchange is, from your system’s point of view, just another broker with a different API and some operational differences (24/7, key custody). Because you built against an interface, moving a strategy to crypto is mostly a new adapter (Lesson 13), not a rewrite.

This is just good software architecture — program to an interface, isolate what varies — applied where it pays off enormously, because broker APIs are both essential and maddeningly inconsistent.

Pitfalls to Avoid

  1. Broker-specific code in your strategy. It tangles your logic and locks you to one broker. Put it all behind the adapter interface.
  2. Not normalising the data model. If each broker’s orders/fills/ticks have different shapes in your core, every component has to special-case them. Normalise at the adapter boundary.
  3. Ignoring rate limits. Exceed the broker’s caps and you get rejected or throttled at the worst time. The adapter must enforce them (Lesson 8).
  4. No reconnection logic in the adapter. A dropped WebSocket then breaks your strategy. The adapter owns reconnect + re-subscribe + re-snapshot (Lesson 3).
  5. Hardcoding symbol formats. Instrument identifiers differ per broker/exchange; map them in the adapter, don’t scatter string formats through your code.
  6. Assuming the API is stable. Broker APIs change; keep the adapter current and version it. Read the current docs before building.

Quick Recap

  • Put all broker-specific code behind a single BrokerAdapter interface (place_order, cancel, positions, subscribe); your strategy speaks one common language.
  • Each adapter hides the mess: auth/token refresh, symbol mapping, field naming, lot/tick sizes, rate limits, reconnection, error normalisation — exposing a normalised model for orders, fills, positions and ticks.
  • Kite Connect (REST orders + WebSocket ticks + daily access token) is the Indian worked example.
  • Adding a broker = one adapter, with strategies/risk/UI unchanged; the same design enables paper trading (a mock adapter) and crypto (Lesson 13).
  • Educational, not financial advice.

Next lesson: the single most important skill for not losing money — backtesting honestly. We’ll see, with measured demos, exactly how backtests lie through lookahead and overfitting, and how to stop them.