Table of Contents

Information about Portfolios and Orders

When creating your own adapter for working with an exchange, it is necessary to implement methods for requesting the current state of the portfolio and orders. These methods are called when receiving PortfolioLookupMessage and OrderStatusMessage messages respectively.

Requesting Portfolio State

To request the portfolio state, the PortfolioLookupAsync method is implemented. This method usually performs the following actions:

  1. Sends a confirmation of receiving the request using SendSubscriptionReplyAsync.
  2. Checks whether the request is a subscription or unsubscription using the IsSubscribe property.
  3. In case of a subscription:
  • Sends a PortfolioMessage message with information about the portfolio.
  • Requests the current account balances from the exchange.
  • For each account, creates and sends a PositionChangeMessage message with information about the position.
  1. Sends a message about the subscription result using SendSubscriptionResultAsync.
public override async ValueTask PortfolioLookupAsync(PortfolioLookupMessage lookupMsg, CancellationToken cancellationToken)
{
	var transId = lookupMsg.TransactionId;

	// Send confirmation of receiving the request
	await SendSubscriptionReplyAsync(transId, cancellationToken);

	if (!lookupMsg.IsSubscribe)
		return;

	// Send a message with information about the portfolio
	await SendOutMessageAsync(new PortfolioMessage
	{
		PortfolioName = PortfolioName,
		BoardCode = BoardCodes.Coinbase,
		OriginalTransactionId = transId,
	}, cancellationToken);

	// Request current account balances
	var accounts = await _restClient.GetAccounts(cancellationToken);

	foreach (var account in accounts)
	{
		// For each account, create and send a message with information about the position
		await SendOutMessageAsync(new PositionChangeMessage
		{
			PortfolioName = PortfolioName,
			SecurityId = new SecurityId
			{
				SecurityCode = account.Currency,
				BoardCode = BoardCodes.Coinbase,
			},
			ServerTime = CurrentTime.ConvertToUtc(),
		}
		.TryAdd(PositionChangeTypes.CurrentValue, (decimal)account.Available, true)
		.TryAdd(PositionChangeTypes.BlockedValue, (decimal)account.Hold, true), cancellationToken);
	}

	// Send a message about successful completion of the subscription
	await SendSubscriptionResultAsync(lookupMsg, cancellationToken);
}

Requesting Orders State

To request the orders state, the OrderStatusAsync method is implemented. This method usually performs the following actions:

  1. Sends a confirmation of receiving the request using SendSubscriptionReplyAsync.
  2. Checks whether the request is a subscription or unsubscription using the OrderStatusMessage.IsSubscribe property.
  3. In case of a subscription:
  • Requests the list of current orders from the exchange.
  • For each order, creates and sends an ExecutionMessage message with information about the order.
  • If necessary, sets up a subscription to receive order updates in real time.
  1. Sends a message about the subscription result using SendSubscriptionResultAsync.
public override async ValueTask OrderStatusAsync(OrderStatusMessage statusMsg, CancellationToken cancellationToken)
{
	// Send confirmation of receiving the request
	await SendSubscriptionReplyAsync(statusMsg.TransactionId, cancellationToken);

	if (!statusMsg.IsSubscribe)
		return;

	// Request the list of current orders
	var orders = await _restClient.GetOrders(cancellationToken);

	foreach (var order in orders)
		await ProcessOrder(order, statusMsg.TransactionId, cancellationToken);

	if (!statusMsg.IsHistoryOnly())
	{
		// Set up a subscription to receive order updates in real time
		await _socketClient.SubscribeOrders(cancellationToken);
	}

	// Send a message about successful completion of the subscription
	await SendSubscriptionResultAsync(statusMsg, cancellationToken);
}

private async ValueTask ProcessOrder(Order order, long originTransId, CancellationToken cancellationToken)
{
	if (!long.TryParse(order.ClientOrderId, out var transId))
		return;

	var state = order.Status.ToOrderState();

	// Create and send a message with information about the order
	await SendOutMessageAsync(new ExecutionMessage
	{
		ServerTime = originTransId == 0 ? CurrentTime.ConvertToUtc() : order.CreationTime,
		DataTypeEx = DataType.Transactions,
		SecurityId = order.Product.ToStockSharp(),
		TransactionId = originTransId == 0 ? 0 : transId,
		OriginalTransactionId = originTransId,
		OrderState = state,
		Error = state == OrderStates.Failed ? new InvalidOperationException() : null,
		OrderType = order.Type.ToOrderType(),
		Side = order.Side.ToSide(),
		OrderStringId = order.Id,
		OrderPrice = order.Price?.ToDecimal() ?? 0,
		OrderVolume = order.Size?.ToDecimal(),
		TimeInForce = order.TimeInForce.ToTimeInForce(),
		Balance = (decimal?)order.LeavesQuantity,
		HasOrderInfo = true,
	}, cancellationToken);
}

Processing Real-Time Updates

To process real-time order state updates, a separate method is usually implemented, which is called when receiving corresponding events from the WebSocket client:

private async ValueTask SessionOnOrderReceived(Order order, CancellationToken cancellationToken)
{
	// Process the received order update
	// OriginTransId = 0, since this is a real-time update, not a response to a specific request
	await ProcessOrder(order, 0, cancellationToken);
}