Order Management System Streaming API

Servers

Establishing a connection

A connection must be established first in order to subscribe to any updates. To do this, you may use any ASP.NET Core SignalR client of your choice.

				
HubConnection connection = new HubConnectionBuilder()
	.WithUrl("{{API URL HERE}}/streams", options =>
	{
		options.AccessTokenProvider = GetBearerToken;
	})
	.AddMessagePackProtocol()
	.Build();

await connection.StartAsync();
				
				

Implement an access token provider

You need the oms-streams-api scope claim in order to be authorized to use the streaming hub. Learn from our Auth API documentation on how to get an authorization token.

					
private async Task<string> GetBearerToken()
{
	// TODO: Implement access token provider here.
}
					
				

Subscribing to Orders Updates

In order to subscribe to the current trading day's order updates, you first need to setup the event handler for incoming data. You need a handler for OrdersUpdated event.

					
private async Task HandleOrdersUpdated()
{
	this.connection.On("OrdersUpdated", orders =>
	{
		// Do something with the data
	});
}
					
				

Below is the schema of the data, in JSON, coming from the hub.

							
{
	"rootParentOrderNumber": {
		type: "number"
	},
	"orderNumber": {
		type: "number"
	},
	"parentOrderNumber": {
		type: "number"
	},
	"accountCode": {
		type: "string"
	},
	"securityCode": {
		type: "string"
	},
	"exchange": {
		type: "string"
	},
	"destination": {
		type: "string"
	},
	"subDestination": {
		type: "string"
	},
	"pricingInstructions": {
		type: "string"
	},
	"orderState": {
		type: "string"
	},
	"lastAction": {
		type: "string"
	},
	"actionStatus": {
		type: "string"
	},
	"orderVolume": {
		type: "string"
	},
	"orderPrice": {
		type: "string"
	},
	"remainingVolume": {
		type: "string"
	},
	"doneVolumeTotal": {
		type: "string"
	},
	"doneValueTotal": {
		type: "string"
	},
	"uncommittedVolume": {
		type: "string"
	},
	"averagePrice": {
		type: "string"
	},
	"lifetime": {
		type: "string"
	},
	"currency": {
		type: "string"
	},
	"expiryDateTime": {
		type: "datetime"
	},
	"doneVolumeToday": {
		type: "number"
	},
	"doneValueToday": {
		type: "number"
	},
	"stateDescription": {
		type: "string"
	},
	"createDateTime": {
		type: "datetime"
	},
	"updateDateTime": {
		type: "datetime"
	},
	"destinationVolume": {
		type: "number"
	},
	"destinationPrice": {
		type: "number"
	},
	"destinationStatus": {
		type: "string"
	},
	"destinationOrderNumber": {
		type: "string"
	},
	"principal": {
		type: "bool"
	},
	"orderMatchId": {
		type: "string"
	},
	"marketDataOrderNumber": {
		type: "string"
	},
	"side": {
		type: "string"
	},
	"effectiveDoneVolume": {
		type: "number"
	},
	"priceMultiplier": {
		type: "number"
	},
	"settlementDoneValueTotal": {
		type: "number"
	},
	"settlementDoneValueToday": {
		type: "number"
	},
	"settlementAveragePrice": {
		type: "number"
	},
	"clientSequenceNumber": {
		type: "number"
	},
	"marketDetail": {
		type: "string"
	},
	"postTradeStatusNumber": {
		type: "number"
	},
	"postTradeStatus": {
		type: "string"
	},
	"estimatedPrice": {
		type: "number"
	},
	"orderValue": {
		type: "number"
	},
	"advisorCode": {
		type: "string"
	},
	"estimatedVolume": {
		type: "number"
	},
	"estimatedValue": {
		type: "number"
	},
	"notes": {
		type: "string"
	},
	"fixedContingentOrder": {
		"triggerSecurity": {
			type: "string"
		},
		"triggerPriceType": {
			type: "string"
		},
		"triggerPrice": {
			type: "number"
		},
		"triggerCondition": {
			type: "string"
		},
		"contingentOrderStatus": {
			type: "string"
		}
	}
}
							
						

You may setup the handler before starting the connection.

						
...

this.HandleOrdersUpdates();
await connection.StartAsync();
						
					

Now, all you need to do is invoke the SubscribeToOrderUpdates hub method. This will subscribe your client to the order updates channel. Take note that you will only receive orders created during the current trading day and associated with your business id.

						
private async Task SubscribeToOrderUpdates()
{
	await connection.InvokeAsync("SubscribeToOrderUpdates");
}
						
					
Then call it after the connection has been started.

					
...
await connection.StartAsync();
this.SubscribeToOrderUpdates();
					
				

Subscribing to Trade Updates

In order to subscribe to trade updates, you first need to setup the event handler for incoming data. You need a handler for TradesUpdated event.

					
private async Task HandleTradeUpdates()
{
	this.connection.On("TradesUpdated", trades =>
	{
		// Do something with the data
	});
}
					
				

Below is the schema of the data, in JSON, coming from the hub.

							
{
	"advisorCode": {
		"type":"string"
	},
	"tradeNumber": {
		"type":"number"
	},
	"orderNumber": {
		"type":"number"
	},
	"accountCode": {
		"type":"string"
	},
	"securityCode": {
		"type":"string"
	},
	"exchange": {
		"type":"string"
	},
	"destination": {
		"type":"string"
	},
	"subDestination": {
		"type":"string"
	},
	"buyOrSell": {
		"type":"string"
	},
	"tradeVolume": {
		"type":"number"
	},
	"tradePrice": {
		"type":"number"
	},
	"tradeValue": {
		"type":"number"
	},
	"tradeFxRate": {
		"type":"number"
	},
	"tradeDateTime": {
		"type":"datetime"
	},
	"principal": {
		"type":"boolean"
	},
	"opposingBrokerNumber": {
		"type":"number"
	},
	"primaryClientOrderId": {
		"type":"string"
	},
	"secondaryClientOrderId": {
		"type":"string"
	},
	"tradeMarkers": {
		"type":"string"
	},
	"destinationUserId": {
		"type":"string"
	},
	"destinationOrderNumber": {
		"type":"string"
	},
	"destinationTradeNumber": {
		"type":"string"
	},
	"cancelledByTradeNumber": {
		"type":"number"
	},
	"marketDataOrderNumber": {
		"type":"number"
	},
	"marketDataTradeNumber": {
		"type":"number"
	},
	"fxRateBidPriceOnOrder": {
		"type":"number"
	},
	"fxRateAskPriceOnOrder": {
		"type":"number"
	},
	"fxRateBidPriceOnTrade": {
		"type":"number"
	},
	"fxRateAskPriceOnTrade": {
		"type":"number"
	},
	"sourcePrice": {
		"type":"number"
	},
	"sourceCurrency": {
		"type":"string"
	},
	"sideCode": {
		"type":"string"
	},
	"orderDetails": {
		"type":"string"
	},
	"settlementValue": {
		"type":"number"
	},
	"settlementFxRate": {
		"type":"number"
	},
	"settlemePrice": {
		"type":"number"
	},
	"organization": {
		"type":"string"
	},
	"bookingDestination": {
		"type":"string"
	},
	"tradeMarketDetail": {
		"type":"string"
	},
	"postTradeStatusNumber": {
		"type":"number"
	},
	"postTradeStatusNumber": {
		"type":"number"
	},
	"tradeDateTimeGmt": {
		"type":"datetime"
	},
	"exchangeTradeDateTime": {
		"type":"datetime"
	},
	"localMarketTradeDate": {
		"type":"datetime"
	}
}
							
						

You may setup the handler before starting the connection.

						
...

this.HandleTradeUpdates();
await connection.StartAsync();
						
					

Now, all you need to do is invoke the SubscribeToTradeUpdates hub method. This will subscribe your client to trade updates channel depending on the parameters supplied. Take note that you will only receive trades created with your business id.

						
private async Task SubscribeToTradeUpdates()
{
	await connection.InvokeAsync("SubscribeToTradeUpdates");
}
						
					

Then call it after the connection has been started.

					
...
await connection.StartAsync();
this.SubscribeToTradeUpdates();
					
				

Subscribing to Portfolio Position Updates

In order to subscribe to portfolio position updates, you first need to setup the event handler for incoming data. You need a handler for PortfolioPositionsUpdated event.

					
private async Task PortfolioPositionUpdates()
{
	this.connection.On("PortfolioPositionsUpdated", portfolioPositions =>
	{
		// Do something with the data
	});
}
					
				

Below is the schema of the data, in JSON, coming from the hub.

							
{
	"advisorCode": {
		"type":"string"
	},
	"accountCode": {
		"type":"string"
	},
	 "sharingCashAccount": {
		"type":"boolean"
	},
	"portfolioCode": {
		"type":"string"
	},
	"securityCode": {
		"type":"string"
	},
	"exchange": {
		"type":"string"
	},
	"underlyingSecurityCode": {
		"type":"string"
	},
	"underlyingExchange": {
		"type":"string"
	},
	"versionStamp": {
		"type":"number"
	},
	"updateReasonMask": {
		"type":"number"
	},
	"createDateTime": {
		"type":"datetime"
	},
	"updateDateTime": {
		"type":"datetime"
	},
	"volumeStartOfDay": {
		"type":"number"
	},
	"averagePriceStartOfDay": {
		"type":"number"
	},
	"averagePrice": {
		"type":"number"
	},
	"buyVolume": {
		"type":"number"
	},
	"buyValue": {
		"type":"number"
	},
	"buyCharges": {
		"type":"number"
	},
	"sellVolume": {
		"type":"number"
	},
	"sellValue": {
		"type":"number"
	},
	"sellCharges": {
		"type":"number"
	},
	"cfdLodgedVolume": {
		"type":"number"
	},
	"optionLodgedVolume": {
		"type":"number"
	},
	"systemLockedVolume": {
		"type":"number"
	},
	"userLockedVolume": {
		"type":"number"
	},
	"pledgedTakeOverVolume": {
		"type":"number"
	},
	"inMarketBuyVolume": {
		"type":"number"
	},
	"inMarketBuyValue": {
		"type":"number"
	},
	"inMarketSellVolume": {
		"type":"number"
	},
	"inMarketSellValue": {
		"type":"number"
	},
	"availableVolume": {
		"type":"number"
	},
	"costValue": {
		"type":"number"
	},
	"marketValue": {
		"type":"number"
	},
	"totalProfit": {
		"type":"number"
	},
	"todayProfit": {
		"type":"number"
	},
	"closedProfit": {
		"type":"number"
	},
	"exposure": {
		"type":"number"
	},
	"sfcVariationMargin": {
		"type":"number"
	},
	"averageBuyPrice": {
		"type":"number"
	},
	"averageSellPrice": {
		"type":"number"
	},
	"actualVolume": {
		"type":"number"
	},
	"shortSellVolume": {
		"type":"number"
	},
	"historicalPrice": {
		"type":"number"
	},
	"historicalProfit": {
		"type":"number"
	},
	"hedgeExp": {
		"type":"number"
	},
	"actualValue": {
		"type":"number"
	},
	"unsponsoredBuyVolume": {
		"type":"number"
	},
	"unsponsoredBuyValue": {
		"type":"number"
	},
	"unsponsoredSellVolume": {
		"type":"number"
	},
	"unsponsoredSellValue": {
		"type":"number"
	},
	"unsponsoredInMarketBuyVolume": {
		"type":"number"
	},
	"unsponsoredInMarketBuyValue": {
		"type":"number"
	},
	"unsponsoredInMarketSellVolume": {
		"type":"number"
	},
	"unsponsoredInMarketSellValue": {
		"type":"number"
	},
	"unsponsoredStartOfDayVolume": {
		"type":"number"
	},
	"historicalProfitStartOfDay": {
		"type":"number"
	},
	"totalHistoricalProfit": {
		"type":"number"
	},
	"totalDiffMktValProfitDay": {
		"type":"number"
	},
	"realizedLossAccumulatedTodayValue": {
		"type":"number"
	},
	"securityType": {
		"type":"number"
	}
}
							
						

You may setup the handler before starting the connection.

						
...

this.HandlePortfolioPositionUpdates();
await connection.StartAsync();
						
					

Now, all you need to do is invoke the SubscribeToPortfolioPositionUpdates hub method. This will subscribe your client to portfolio position updates channel depending on the parameters supplied. Take note that you will only receive portfolio position updates associated with your business id.

						
private async Task SubscribeToTradeUpdates()
{
	await connection.InvokeAsync("SubscribeToPortfolioPositionUpdates");
}
						
					

Then call it after the connection has been started.

					
...
await connection.StartAsync();
this.SubscribeToPortfolioPositionUpdates();
					
				

Subscribing to Portfolio Cash Detail Updates

In order to subscribe to portfolio cash detail updates, you first need to setup the event handler for incoming data. You need a handler for PortfolioCashDetailsUpdated event.

					
private async Task PortfolioCashDetailsUpdates()
{
	this.connection.On("PortfolioCashDetailsUpdated", portfolioCashDetails =>
	{
		// Do something with the data
	});
}
					
				

Below is the schema of the data, in JSON, coming from the hub.

							
{
	"portfolioCode": {
		"type":"string"
	},
	"accountCode": {
		"type":"string"
	},
	"advisorCode": {
		"type":"string"
	},
	"portfolioCashCode": {
		"type":"string"
	},
	"portfolioCashName": {
		"type":"string"
	},
	"versionStamp": {
		"type":"string"
	},
	"createDateTime": {
		"type":"datetime"
	},
	"updateDateTime": {
		"type":"datetime"
	},
	"currencyCode": {
		"type":"string"
	},
	"cashBalance": {
		"type":"number"
	},
	"unsettledBuyValue": {
		"type":"number"
	},
	"unsettledBuyCharges": {
		"type":"number"
	},
	"unsettledSellValue": {
		"type":"number"
	},
	"unsettledSellCharges": {
		"type":"number"
	},
	"yesterdayEquitySellValue": {
		"type":"number"
	},
	"yesterdayEquitySellCharges": {
		"type":"number"
	},
	"inMarketBuyValue": {
		"type":"number"
	},
	"inMarketSellValue": {
		"type":"number"
	},
	"netCash": {
		"type":"number"
	},
	"uploadSource": {
		"type":"string"
	},
	"optionUnsettledBuyValue": {
		"type":"number"
	},
	"optionUnsettledBuyCharges": {
		"type":"number"
	},
	"optionUnsettledSellValue": {
		"type":"number"
	},
	"optionUnsettledSellCharges": {
		"type":"number"
	},
	"clearingHouseMargin": {
		"type":"number"
	},
	"externalValue": {
		"type":"string"
	},
	"netUnsettledBuyValueToday": {
		"type":"number"
	},
	"netUnsettledSellValueToday": {
		"type":"number"
	},
	"netUnsettledValueToday": {
		"type":"number"
	},
	"glv": {
		"type":"number"
	},
	"freeEquity": {
		"type":"number"
	},
	"totalInitialMargin": {
		"type":"number"
	},
	"totalCfdRealisedProfit": {
		"type":"number"
	},
	"totalCfdUnrealisedProfit": {
		"type":"number"
	},
	"totalCfdCollateralValue": {
		"type":"number"
	},
	"totalNonCfdMarketValue": {
		"type":"number"
	},
	"realizedLossStartOfDayValue": {
		"type":"number"
	},
	"marginLenderTotalFinancedValue": {
		"type":"number"
	},
	"trustBalance": {
		"type":"number"
	},
	"totalCfdRealizedProfitInSettlementCurrency": {
		"type":"number"
	},
	"accruedInterest": {
		"type":"number"
	},
	"facilityLimit": {
		"type":"number"
	},
	"multiSettlementCalculationMethod": {
		"type":"number"
	},
	"defaultCashSettlementDays": {
		"type":"number"
	},
	"isDefaultCurrency": {
		"type":"number"
	}
}
							
						

You may setup the handler before starting the connection.

						
...

this.HandlePortfolioCashDetailUpdates();
await connection.StartAsync();
						
					

Now, all you need to do is invoke the SubscribeToPortfolioCashDetailUpdates hub method. This will subscribe your client to portfolio cash detail updates channel depending on the parameters supplied. Take note that you will only receive portfolio cash detail updates associated with your business id.

						
private async Task SubscribeToPortfolioCashDetailUpdates()
{
	await connection.InvokeAsync("SubscribeToPortfolioCashDetailUpdates");
}
						
					

Then call it after the connection has been started.

					
...
await connection.StartAsync();
this.SubscribeToPortfolioCashDetailUpdates();
					
				

Automatic Reconnect

Dropped connections due to network issues can be automatically reconnected by certain clients. Consult your client's documentation for more details. An example for the .NET Client is shown below:

				
HubConnection connection = new HubConnectionBuilder()
	.WithUrl("{{API URL HERE}}/streams", options =>
	{
		options.AccessTokenProvider = GetBearerToken;
	})
	.WithAutomaticReconnect() // this will enable automatic reconnect
	.AddMessagePackProtocol()
	.Build();
				
				

Handling Reconnects

Clients that were successfully reconnected need to resubscribe to the channels they were subscribed prior to disconnecting. A Reconnected event handler should be implemented to resubscribe a client.

				
connection.Reconnected += async (connectionId) =>
{
	Console.WriteLine("Reconnected.");
	
	// Resubscribe to the channels
	await SubscribeToOrderUpdates();
	await SubscribeToQuoteUpdates();
};
				
				

Additional Resources