Skip to main content

Smart Order Router

The SOR module optimally splits and routes orders across multiple venues to minimize execution cost.

Features

  • Cost Estimation: Walk the orderbook to estimate slippage and fees
  • Venue Scoring: Rank venues by total cost + confidence penalty
  • Balance Constraints: Respects available balances per account
  • Daily Limits: Enforces trading limits per exchange account
  • Multi-venue Splitting: Splits orders across up to 3 venues (configurable)

Cost Calculation

For each venue, the SOR:
  1. Walks the orderbook to estimate VWAP for the order size
  2. Calculates slippage vs mid price in basis points
  3. Adds exchange taker fees (4-6 bps depending on venue)
  4. Applies confidence penalty for stale or unreliable data
Fee Rates (Taker):
VenueFee (bps)
Binance4
Bybit6
Gate.io4
Kraken5

Venue Scoring

score = total_cost_bps + (1 - confidence) * 10
Lower score = better venue. The confidence penalty prevents routing to venues with stale data even if displayed prices look better.

POST /oems/sor/estimate

Get routing estimate without executing.

Request Body (JSON)

  • symbol (string, required): Trading pair (e.g., “BTC/USDT”)
  • side (string, required): Order side: “buy” or “sell”
  • quantity (number, required): Order quantity in base currency
  • exchange_account_ids (array, required): List of eligible exchange account IDs
  • max_venues (number, optional): Maximum venues to use for splitting. Default: 3
  • max_slippage_bps (number, optional): Maximum allowed slippage in basis points. Default: 50

Request Example

curl -X POST http://localhost:8082/oems/sor/estimate \
  -H "Content-Type: application/json" \
  -d '{
    "symbol": "BTC/USDT",
    "side": "buy",
    "quantity": 0.01,
    "exchange_account_ids": ["binance-sandbox-001", "gateio-001"]
  }'

Response Example

{
  "isError": false,
  "message": "Routing estimate",
  "statusCode": 200,
  "data": {
    "symbol": "BTC/USDT",
    "side": "buy",
    "total_quantity": 0.01,
    "estimated_vwap": 88150.50,
    "estimated_cost_bps": 4.2,
    "routable": true,
    "allocated_quantity": 0.01,
    "slices": [
      {
        "venue": "binance",
        "exchange_account_id": "binance-sandbox-001",
        "quantity": 0.006,
        "estimated_price": 88150.20,
        "cost_bps": 4.1,
        "confidence": 0.95
      },
      {
        "venue": "gateio",
        "exchange_account_id": "gateio-001",
        "quantity": 0.004,
        "estimated_price": 88151.00,
        "cost_bps": 4.4,
        "confidence": 0.88
      }
    ]
  }
}

POST /oems/sor/execute

Create and execute a routing plan.

Request Body (JSON)

  • symbol (string, required): Trading pair (e.g., “BTC/USDT”)
  • side (string, required): Order side: “buy” or “sell”
  • quantity (number, required): Order quantity in base currency
  • exchange_account_ids (array, required): List of eligible exchange account IDs
  • max_venues (number, optional): Maximum venues to use for splitting. Default: 3
  • max_slippage_bps (number, optional): Maximum allowed slippage in basis points. Default: 50

Request Example

curl -X POST http://localhost:8082/oems/sor/execute \
  -H "Content-Type: application/json" \
  -d '{
    "symbol": "BTC/USDT",
    "side": "buy",
    "quantity": 0.001,
    "exchange_account_ids": ["gateio-001"]
  }'

Response Example

{
  "isError": false,
  "message": "Routing plan completed",
  "statusCode": 200,
  "data": {
    "plan_id": "plan-abc123def456",
    "symbol": "BTC/USDT",
    "side": "buy",
    "total_quantity": 0.001,
    "status": "completed",
    "executed_quantity": 0.001,
    "actual_vwap": 88152.30,
    "actual_cost_bps": 4.5,
    "slices": [
      {
        "venue": "gateio",
        "exchange_account_id": "gateio-001",
        "quantity": 0.001,
        "status": "filled",
        "order_id": "12345678",
        "filled_quantity": 0.001,
        "avg_fill_price": 88152.30,
        "confidence": 0.88
      }
    ]
  }
}

GET /oems/sor/plan/

Retrieve status of a routing plan.

Path Parameters

  • plan_id (string, required): The routing plan ID

Request Example

curl http://localhost:8082/oems/sor/plan/plan-abc123def456

Response Example

{
  "isError": false,
  "message": "Plan retrieved",
  "statusCode": 200,
  "data": {
    "plan_id": "plan-abc123def456",
    "symbol": "BTC/USDT",
    "side": "buy",
    "total_quantity": 0.001,
    "status": "completed",
    "created_at": "2025-01-15T10:30:00Z",
    "executed_at": "2025-01-15T10:30:01Z",
    "completed_at": "2025-01-15T10:30:02Z",
    "executed_quantity": 0.001,
    "actual_vwap": 88152.30,
    "slices": []
  }
}

GET /oems/sor/venues

Get venue availability and cost estimates for a symbol.

Query Parameters

  • symbol (string, required): Trading pair
  • venues (string, optional): Comma-separated venue list (defaults to all)

Request Example

curl "http://localhost:8082/oems/sor/venues?symbol=BTC/USDT"

Response Example

{
  "isError": false,
  "message": "Venue status",
  "statusCode": 200,
  "data": {
    "symbol": "BTC/USDT",
    "venues": [
      {
        "venue": "binance",
        "available": true,
        "confidence": 0.95,
        "spread_bps": 0.5,
        "staleness_ms": 45.2,
        "quality": "GOOD",
        "fee_bps": 4
      },
      {
        "venue": "bybit",
        "available": true,
        "confidence": 0.88,
        "spread_bps": 0.8,
        "staleness_ms": 120.5,
        "quality": "GOOD",
        "fee_bps": 6
      },
      {
        "venue": "kraken",
        "available": false,
        "confidence": 0.15,
        "reason": "Stale data"
      }
    ]
  }
}

Plan Status Values

StatusDescription
pendingPlan created, not yet executed
executingOrders being submitted
completedAll slices filled successfully
partialSome slices filled, others failed
failedNo slices were filled

Slice Status Values

StatusDescription
pendingSlice waiting to be submitted
submittedOrder submitted to exchange
filledOrder completely filled
partialOrder partially filled
failedOrder failed
skippedSlice skipped (constraints not met)

Constraints

  • Minimum Slice Size: $10 USD equivalent
  • Maximum Venues: Configurable (default 3)
  • Minimum Confidence: 0.4 (venues below this are excluded)
  • Maximum Staleness: 2000ms (stale venues excluded)
  • Daily Limit: $100/day per exchange account (enforced)

Integration

The SOR uses:
  • GOB Module: For real-time orderbook data and quality metrics
  • Balance Cache: For available balances (from DB, updated by PMS)
  • TradingLimitService: For daily limit enforcement
  • ExecutionService: For actual order execution