Batch processing

Use batch processing for large portfolios or high-volume workloads that should be processed asynchronously in the background. The batch workflow automatically chunks large submissions and tracks progress until completion.

The batch API accepts the same payload as POST /portfolios, returns a batch_id, and lets you track progress until processing completes.

Overview

The typical flow is:

  1. Submit a portfolio to POST /portfolios/batch
  2. Poll GET /portfolios/batch/{batch_id} until the batch reaches a terminal state
  3. Fetch the resulting account outputs from GET /results/accounts
  4. Filter those results to the account codes that belonged to the submitted batch

This workflow is useful when:

  • the portfolio is large
  • you want background processing instead of waiting on a synchronous response
  • you want queueing and progress tracking
  • you want the platform to split large submissions into chunks automatically

How It Works

Batch submission returns:

{
  "batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

You then poll the batch status endpoint until status becomes one of:

  • completed
  • failed
  • completed_with_errors

Once the batch completes, the results are written into the user's live portfolio store. The linked public batch example then retrieves the latest per-account results using GET /results/accounts.

The linked public batch example uses GET /results/accounts after completion, then filters those account-level results down to the submitted account_code values.

Submit the batch

POST /portfolios/batch accepts the same JSON payload as POST /portfolios.

Example request:

{
  "calculation_type": "margins",
  "vendor_symbology": "clearing",
  "portfolio": [
    {
      "account_code": "account_0000",
      "exchange_code": "ICE.EU",
      "contract_code": "B",
      "contract_type": "FUT",
      "contract_expiry": "203212",
      "net_position": "100",
      "account_type": "H"
    }
  ]
}

The batch endpoint also supports the x-processing-mode header:

x-processing-mode only applies to POST /portfolios/batch. It controls queue handling, not margin calculation.

  • fifo: default. Batch jobs are processed in submission order.
  • priority: can move the job ahead of the same user's other queued non-priority jobs.
  • replace_all: removes the user's currently queued batch jobs before adding the new one. Jobs already processing are not cancelled.

Poll batch status

Use GET /portfolios/batch/{batch_id} to check progress.

Example response:

{
  "batch_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "processing",
  "queue_position": 0,
  "created_at": "2025-01-03T09:31:14Z",
  "completed_at": null,
  "runtime_ms": 4523,
  "completed_pct": 67.5
}

Poll until status is:

  • completed
  • failed
  • completed_with_errors

If the batch fails, stop there and do not attempt to fetch results.

Fetch results

The batch example shows the next step after completion:

results_response = requests.get(f"{C9_API_ENDPOINT}/results/accounts", headers=HEADERS)
results_response.raise_for_status()
accounts = results_response.json()

submitted = set(account_codes)
batch_accounts = [a for a in accounts if a["account_code"] in submitted]

This means:

  • GET /results/accounts returns the latest calculation for every live account owned by the caller
  • your client should keep track of the submitted account_code values
  • after the batch completes, filter the returned accounts down to the ones from that batch

The example then:

  • prints how many account results were fetched
  • calculates total initial margin across the batch
  • lists the top 5 accounts by initial margin

Was this page helpful?