Plugin Types¶
Every component in Meridian beyond the kernel, the message bus, and the sidecar is a plugin. Plugins are built by vendors and run within deployments. Each plugin connects exclusively to its local sidecar on localhost:9191 and communicates with the rest of the platform through pub/sub messages on the bus.
This page covers each plugin type: what it does, what it publishes, what it subscribes to, and how it interacts with the kernel.
DGM (Data Gateway Manager)¶
A DGM plugin normalizes external data sources into the kernel's canonical schema. Each DGM instance corresponds to one external data provider or venue (e.g., Bloomberg, Polygon, Databento, a CSV file).
Three-Stage Pipeline¶
Every DGM plugin implements a three-stage data fetch pipeline, orchestrated by the sidecar:
| Stage | Method | Description |
|---|---|---|
| 1 | transform_query(subscription_request) |
Translates a kernel subscription request into a vendor-specific query. Maps kernel instrument identifiers to the provider's symbology. |
| 2 | extract_data(normalized_query, credentials) |
Fetches data from the external provider. All network egress passes through the sidecar's network proxy. Credentials are injected by the sidecar and must not be stored or logged. |
| 3 | transform_data(normalized_query, raw_response) |
Transforms the provider-specific response into kernel-canonical events. Every output event must carry both ts_event and ts_init. |
The plugin does not call these stages directly in response to bus messages. The sidecar orchestrates the pipeline.
Streaming Hooks¶
DGM plugins that support real-time streaming implement three additional hooks:
| Hook | Description |
|---|---|
on_subscribe(symbol, resolution) |
Initiates a streaming subscription at tick, 1s, 1m, 1h, or 1d resolution. |
on_unsubscribe(symbol) |
Terminates a streaming subscription. |
on_tick(raw_tick) |
Normalizes a single raw tick into a NormalizedTick with dual timestamps. |
Subscription management is handled by the sidecar. The plugin does not maintain its own subscription registry.
Feed Status¶
DGM plugins publish feed status updates to platform.dgm.{id}.data.feed.status whenever connection state changes. Status values: CONNECTED, DISCONNECTED, DEGRADED, RECONNECTING.
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.dgm.{id}.data.price.eod |
End-of-day prices |
platform.dgm.{id}.data.price.tick |
Real-time tick data |
platform.dgm.{id}.data.reference.instrument |
Instrument reference data |
platform.dgm.{id}.data.alt.{subtype} |
Alternative data |
platform.dgm.{id}.data.feed.status |
Feed health status |
Subscribes To¶
DGM plugins subscribe to kernel subscription requests. They do not subscribe to other plugin output.
Kernel API¶
DGM plugins do not use OMS, EMS, or BOR kernel APIs directly. They produce data that other plugins consume.
Signal Engine¶
A Signal Engine consumes market data and reference data to generate trading insights. Signal Engines operate in a read-only capacity with respect to order flow.
Primary Hook¶
| Method | Input | Output |
|---|---|---|
on_data(data_window) |
A DataWindow bundling bars, ticks, reference data, and corporate actions |
Zero or more Insight objects |
Insight Schema¶
Insight {
symbol string Instrument identifier (kernel canonical ID)
direction enum Up, Down, or Flat
magnitude float64 Expected magnitude, normalized to [0.0, 1.0]
confidence float64 Confidence in prediction, [0.0, 1.0]
source_model string Name of the generating model or strategy
weight float64 Relative weight (default: 1.0, optional)
period Duration Expected time horizon
generated_at Timestamp Plugin wall-clock time
close_at Timestamp Expiration time (must equal generated_at + period)
}
Order Submission Prohibition¶
A Signal Engine must not submit, modify, or cancel orders. The sidecar enforces this: any attempt to publish to platform.oms.* or platform.ems.* is rejected with ACL_DENIED. Signal Engines are restricted to platform.signal.* topics.
Warmup Protocol¶
A Signal Engine may declare a warmup requirement (warmup_bars or warmup_period). During warmup, the sidecar replays historical data through on_data with is_warmup = true. Insights generated during warmup are discarded, not published to the bus. The plugin transitions to RUNNING only after warmup completes.
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.signal.{id}.signal.insight |
Individual insight objects |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.dgm.*.data.price.* |
Market data from DGM plugins |
platform.dgm.*.data.reference.* |
Reference data |
Kernel API¶
Signal Engines do not use kernel APIs. They produce insights consumed by Portfolio Optimizers.
Portfolio Optimizer¶
A Portfolio Optimizer converts aggregated signals into target portfolio weights. It bridges the gap between alpha research (Signal Engines) and order generation (OMS).
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.optimizer.{id}.target.weights |
Target portfolio weights per instrument |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.signal.*.signal.aggregated |
Aggregated insights from Signal Pool Manager |
Kernel API¶
Portfolio Optimizers may read current positions via the BOR API (GetPositions) to compute the delta between current and target weights. They do not write to the kernel directly. Order creation is handled downstream by the OMS.
OMS (Order Management System)¶
An OMS plugin manages order creation, compliance checks, allocation, and the pre-trade/post-trade lifecycle. It is the entry point for all order flow into the kernel.
Key Responsibilities¶
- Create, modify, and cancel orders
- Trigger pre-trade and post-trade compliance checks
- Allocate block fills to individual accounts
- Hand off orders to the trading desk (
SendToTrader) and to operations (SendToOperations) - Create remainder orders for partial fills via the
CloseOrder/CreateRemainderOrderpattern - Merge and split orders
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.oms.{id}.order.created |
New order events |
platform.oms.{id}.order.compliance.* |
Compliance check results |
platform.oms.{id}.order.allocated |
Allocation results |
platform.oms.{id}.order.cancelled |
Cancellation events |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.optimizer.*.target.weights |
Target weights from Portfolio Optimizer |
platform.oms.*.order.compliance.* |
Compliance results (from compliance plugins) |
Kernel API¶
OMS plugins use the OMS API surface extensively: CreateOrder, UpdateOrder, CancelOrder, CloseOrder, CreateRemainderOrder, CreateAllocation, SendToTrader, SendToOperations.
EMS (Execution Management System)¶
An EMS plugin handles smart order routing, algorithm selection, RFQ workflows, and fill aggregation. It takes orders approved by the OMS and creates placements at venues via CCM plugins.
Key Responsibilities¶
- Split orders into placements across brokers and venues
- Select execution strategies via the algo wheel (
SelectStrategy) - Manage RFQ (Request for Quote) workflows for quote-driven markets
- Aggregate responses from child placements back to the parent order
- Close orders and compute executed/unfilled quantities
Strategy Wheel¶
The EMS supports pluggable execution algorithms as named strategies. SelectStrategy evaluates the order and market context, returning a broker, algorithm, parameters, and confidence score. The result is a recommendation; the caller may override it.
RFQ Workflow¶
RFQ is a first-class execution paradigm, not a special case. It is the primary pattern for fixed income and certain FX instruments. The workflow:
RequestQuotescreates one placement per dealer with strategyRFQ- Dealers respond with quotes (responses in
QUOTEDstate) SelectQuoteaccepts one quote (transitions toFILLED) and cancels the others
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.ems.{id}.placement.created |
New placement events |
platform.ems.{id}.order.closed |
Order close events with executed/unfilled quantities |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.oms.*.order.* |
Order events from OMS |
platform.ccm.*.fill.recorded |
Fill events from CCM plugins |
platform.ccm.*.execution.rfq.* |
RFQ quotes from CCM plugins |
Kernel API¶
EMS plugins use the EMS API surface: CreatePlacement, CancelPlacement, CloseOrder, CreateResponse, SelectStrategy, RequestQuotes, SelectQuote.
CCM (Capital and Connectivity Manager)¶
A CCM plugin manages connectivity to a single execution venue or broker. Each CCM instance corresponds to one broker session or venue connection.
Required Methods¶
| Method | Description |
|---|---|
connect(credentials) |
Establishes connection to the venue. Credentials are injected by the sidecar and must not be stored or logged. |
disconnect() |
Gracefully disconnects. Must cancel or acknowledge all in-flight orders first. |
submit_order(order) |
Submits a child order to the venue. Translates to venue's native protocol (e.g., FIX NewOrderSingle). |
cancel_order(order_id) |
Requests cancellation at the venue. The acknowledgment does not guarantee cancellation. |
modify_order(order_id, changes) |
Requests modification (price, quantity, time-in-force). Translates to the venue's cancel/replace protocol. |
FIX Adapter Pattern¶
CCM plugins typically implement a FIX adapter. The plugin translates between the kernel's order model and FIX messages (NewOrderSingle, OrderCancelRequest, OrderCancelReplaceRequest, ExecutionReport). The kernel model is a superset of FIX, so translation is always possible.
Fill Requirements¶
- Every fill event must include a
trade_idfield with the venue-assigned trade identifier. This field is required and must not be empty or synthetic. - Fill deduplication is handled by the sidecar using the composite key
(trade_id, side, price, quantity, venue). The plugin must not implement its own deduplication. - Fills must carry dual timestamps:
ts_event(venue execution time) andts_init(CCM receive time).
Session Management¶
CCM plugins publish session status to platform.ccm.{id}.session.status with values: CONNECTED, DISCONNECTED, LOGON_PENDING, RECONNECTING. They must implement automatic reconnection with exponential backoff. During reconnection, the plugin enters DEGRADED state and rejects new order submissions. Pending orders must be reconciled on reconnection.
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.ccm.{id}.fill.recorded |
Fill events |
platform.ccm.{id}.execution.rfq.quote.received |
RFQ quotes |
platform.ccm.{id}.order.child.routed |
Child order routed confirmations |
platform.ccm.{id}.session.connected |
Session connected |
platform.ccm.{id}.session.disconnected |
Session disconnected |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.ems.*.placement.created |
Placement events from EMS |
Kernel API¶
CCM plugins use the EMS API to report responses: CreateResponse, UpdateResponseStatus, AmendResponse, CancelResponse.
BOR (Book of Record)¶
The BOR API surface provides position queries, cash management, settlement, reconciliation, journal accounting, and multi-currency translation. The order-book kernel handles the order-to-fill lifecycle; BOR focuses on the post-trade balance sheet.
Key Responsibilities¶
- Query positions by portfolio, instrument, status, or date
- Query and project cash balances and cash movements
- Manage the settlement lifecycle: confirm, settle, reconcile
- Run reconciliations (any-versus-any matching pattern)
- Ingest external statements (MT535, MT536, CSV, API JSON)
- Maintain a double-entry journal with chart of accounts
- Multi-currency translation and FX P&L
What BOR Does Not Do¶
BOR records transactions and maintains balances. It explicitly does not:
- Value positions (valuation plugin)
- Select lots to sell (OMS decides, advised by tax plugin)
- Compute P&L (reporting plugin over transactions)
- Translate currencies autonomously (FX plugin provides rates)
- Calculate NAV (aggregation plugin over valuation + fees + cash)
- Compute accruals (accruals plugin reads holdings + instrument data)
Publishes¶
BOR publishes settlement status updates, reconciliation break events, and position change events.
Subscribes To¶
BOR subscribes to fill events, corporate action events, and settlement confirmations from custodians.
Kernel API¶
BOR uses the BOR API surface: GetPositions, GetCashBalances, SettleOrder, ReconcileOrder, CreateReconciliation, RunReconciliation, PostJournalEntry, TranslatePortfolio.
Valuation (Vendor Plugin)¶
A Valuation plugin reads BOR positions and market data, then computes mark-to-market values and P&L. Valuation is a vendor plugin, not part of the kernel. The kernel stores quantities and costs; the valuation plugin computes values.
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.valuation.{id}.mark.* |
Mark-to-market prices and portfolio values |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.dgm.*.data.price.* |
Market data |
| BOR position events | Current positions |
Kernel API¶
Reads positions via BOR API (GetPositions). Does not write to the kernel.
Compliance (Vendor Plugin)¶
A Compliance plugin evaluates rules at the pre-trade and post-trade checkpoints in the order lifecycle. Compliance is a vendor plugin, not part of the kernel. The kernel provides the compliance checkpoint state transitions; the compliance plugin evaluates the rules.
Publishes¶
| Topic Pattern | Content |
|---|---|
platform.compliance.{id}.result.* |
Compliance check results (pass, fail, with violations) |
Subscribes To¶
| Topic Pattern | Content |
|---|---|
platform.oms.*.order.compliance.* |
Compliance check requests from OMS |
| BOR position and cash data | For rule evaluation (concentration limits, etc.) |
Kernel API¶
Reads orders and positions via OMS and BOR APIs. Publishes compliance results back to the OMS.
Plugin Lifecycle¶
All plugins, regardless of type, follow the same lifecycle state machine:
INITIALIZING -> READY -> RUNNING -> STOPPING -> STOPPED
| |
v v
DEGRADED DISPOSED
|
v
FAULTED -> DISPOSED
| State | Meaning |
|---|---|
INITIALIZING |
Sidecar is completing its 8-step startup sequence |
READY |
Sidecar startup complete, waiting for on_start() |
RUNNING |
Plugin is active and processing messages |
DEGRADED |
Plugin is impaired but operational (e.g., lost upstream connection) |
FAULTED |
Terminal failure after 3 consecutive health check failures |
STOPPING |
Graceful shutdown in progress |
STOPPED |
Clean shutdown complete |
DISPOSED |
All resources released |
Required Hooks¶
| Hook | When Called |
|---|---|
on_start() |
After sidecar completes startup. Must complete within 30 seconds. |
on_stop() |
When graceful shutdown is requested. Must complete within 30 seconds. |
on_degrade(reason) |
When the plugin detects an impairment (e.g., lost data feed). |
on_resume() |
When the plugin recovers from degraded state. |
Summary Table¶
| Plugin Type | Produces | Consumes | Uses Kernel API |
|---|---|---|---|
| DGM | Market data, reference data, feed status | Subscription requests | No |
| Signal Engine | Insights | Market data | No |
| Portfolio Optimizer | Target weights | Aggregated signals | BOR read (positions) |
| OMS | Orders, compliance events, allocations | Target weights, compliance results | OMS API |
| EMS | Placements, order close events | Orders, fills, RFQ quotes | EMS API |
| CCM | Fills, RFQ quotes, session status | Placements | EMS API (responses) |
| BOR | Settlement status, break events | Fills, corporate actions, settlements | BOR API |
| Valuation | Mark-to-market values | Market data, positions | BOR read |
| Compliance | Compliance results | Compliance requests, positions | OMS/BOR read |
Next Steps¶
- Kernel Model -- the unified execution kernel and order lifecycle
- Sidecar Pattern -- how the sidecar mediates all communication
- CCM Adapter Guide -- building a broker connectivity plugin