CCM Adapters¶
A CCM (Capital/Connectivity Manager) plugin manages connectivity to a single execution venue or broker. Each CCM instance corresponds to one broker session or venue connection. The CCM translates between the platform's order model and the venue's native protocol (FIX, REST, WebSocket, etc.).
Required Methods¶
Every CCM plugin must implement these five methods:
connect¶
Establishes the connection to the venue. The plugin must transition to RUNNING only after the connection is ready. Credentials are injected by the sidecar and must not be stored or logged.
def connect(self, credentials):
self.session = fix.Session(
host=credentials["host"],
port=credentials["port"],
sender_comp_id=credentials["sender"],
target_comp_id=credentials["target"],
)
self.session.logon()
disconnect¶
Gracefully disconnects from the venue. Must cancel or acknowledge all in-flight orders before returning. Must not publish new fill events after returning.
submit_order¶
Submits a child order to the venue. Returns a venue-assigned order ID and acceptance status. Must translate to the venue's native protocol.
def submit_order(self, order):
fix_msg = self._to_new_order_single(order)
ack = self.session.send(fix_msg)
return OrderAck(
venue_order_id=ack.order_id,
accepted=ack.status == "ACCEPTED",
)
cancel_order¶
Requests cancellation of a venue order. The CancelAck does not guarantee cancellation; the plugin must publish a fill or cancel confirmation when the venue responds.
def cancel_order(self, order_id):
fix_msg = self._to_order_cancel_request(order_id)
ack = self.session.send(fix_msg)
return CancelAck(accepted=ack.status == "ACCEPTED")
modify_order¶
Requests modification of price, quantity, or time-in-force. Must translate to the venue's cancel/replace protocol.
def modify_order(self, order_id, changes):
fix_msg = self._to_order_cancel_replace(order_id, changes)
ack = self.session.send(fix_msg)
return ModifyAck(accepted=ack.status == "ACCEPTED")
Optional Methods¶
| Method | Description |
|---|---|
batch_cancel(order_ids) |
Bulk cancellation. The sidecar falls back to sequential cancel_order calls if not implemented. |
query_account() |
Queries current account state from the venue for reconciliation purposes. |
generate_fill_reports() |
Retrieves fill reports from the venue's perspective. Every report must include external_trade_id. |
Trade ID Requirement¶
Every fill event must include a trade_id field containing the venue-assigned trade identifier. This field is required and must not be empty or synthetic.
fill = FillEvent(
trade_id="NYSE-2026032700142857", # venue-assigned, required
order_id=order_id,
side="Buy",
price=150.12,
quantity=500,
venue="XNYS",
ts_event=venue_timestamp, # when venue executed
ts_init=datetime.utcnow(), # when CCM received
)
self.publish_fill(fill)
Fill Deduplication¶
The sidecar deduplicates fills automatically using the composite key:
The plugin must not implement its own deduplication. If the sidecar receives a fill with the same composite key as a previously processed fill, the duplicate is silently dropped.
Dual Timestamps¶
Every fill must carry two timestamps:
| Field | Description |
|---|---|
ts_event |
Venue execution timestamp. When the fill actually occurred at the exchange. |
ts_init |
CCM receive timestamp. When the CCM plugin received the execution report. |
The difference between ts_init and ts_event is the end-to-end latency for that fill.
Session Management¶
CCM plugins must publish session status updates to platform.ccm.{instance_id}.session.status whenever the connection state changes.
self.publish_session_status(
session_id=self.session.id,
status="CONNECTED", # CONNECTED | DISCONNECTED | DEGRADED | RECONNECTING
venue="XNYS",
)
| Status | Meaning |
|---|---|
CONNECTED |
Session is active and accepting orders. |
DISCONNECTED |
Session is down. No orders accepted. |
DEGRADED |
Partial connectivity. Existing orders tracked; new submissions rejected. |
RECONNECTING |
Automatic reconnection in progress. |
Automatic Reconnection¶
CCM plugins must implement automatic reconnection with exponential backoff. During reconnection:
- Session status transitions to
RECONNECTING, thenDEGRADED. - New
submit_ordercalls are rejected. - Pending orders must be reconciled with the venue after reconnection succeeds.
- Session status returns to
CONNECTEDafter successful reconnection.
class MyBrokerCCM(CCMPlugin):
vendor_name = "my-broker"
venue = "XNYS"
def connect(self, credentials):
self.session = FIXSession(credentials)
self.session.on_disconnect = self._handle_disconnect
self.session.logon()
def _handle_disconnect(self, reason):
self.publish_session_status(status="RECONNECTING", venue=self.venue)
# Sidecar handles exponential backoff and retry
# Plugin reconciles pending orders on reconnect
def submit_order(self, order):
if not self.session.is_connected:
raise SessionDegradedError("Cannot submit while reconnecting")
return self._send_new_order(order)
def cancel_order(self, order_id):
return self._send_cancel(order_id)
def modify_order(self, order_id, changes):
return self._send_cancel_replace(order_id, changes)
def disconnect(self):
self.session.cancel_all_open()
self.session.logout()
Bus Topics¶
| Topic | Direction | Description |
|---|---|---|
platform.ccm.{id}.fill.executed |
Publish | Fill events from venue |
platform.ccm.{id}.session.status |
Publish | Session status changes |
platform.ccm.{id}.order.child.routed |
Publish | Order routed to venue |
platform.ccm.{id}.execution.rfq.quote.received |
Publish | RFQ quote from dealer |
platform.order-book.command.create-response |
Publish | Creates a fill/quote response on the order-book |
platform.order-book.command.update-response-status |
Publish | Updates response state |