Amazon SQS Integration

Overview

DriveWealth leverages Amazon SQS (Simple Queue Service) to proactively push out events to our partners as they occur. For every event that occurs, a message or "event" will be produced and accessible through a queue created by DriveWealth. By taking advantage of these event notifications, you can greatly reduce the total number of API requests made to the DriveWealth infrastructure.

🚧

DriveWealth only utilizes the Standard Queue structure. First In, First Out (FIFO) is not supported. See Handling Non-Sequential Order Events for more details.

All queues are hosted within DriveWealth's AWS environment. Permissions are granted to the partner's IAM or Lambda user to access the queue.

If utilizing a Lambda user to pick messages off the queue, make sure that the regions of the queue and the Lambda match, otherwise it will not connect.

For partners that do not utilize AWS, it is still possible to take advantage of SQS. DriveWealth recommends that you create a free account with AWS for the purpose of generating an IAM user. Afterwards, a partner can use the SQS SDK or AWS APIs in order to pull down the messages and ingest them into a local cloud provider message service.


How to Request Access

In order to get access to an SQS, DriveWealth simply requires the arn of the IAM or Lambda user that is to going to be reading messages from the queue. A standard arn format resembles the following:

arn:aws:iam::123456789012:user/JohnDoe

DriveWealth will create the queue and grant permissions to the user provided by the partner. DriveWealth will then provide the ARN and URL of the queue to the partner so it may be accessed by the permissioned user.


Example of Events

DriveWealth publishes events for many internal resource changes. Each event object is structured in similar fashion.

{
  "id": "event_dcadb7df-a677-4ba6-8a06-15005d4a491d",
  "type": "orders.created",
  "timestamp": "2019-03-28T22:40:03.260922189Z",
  "payload": {
    "id": "GC.f7590a52-75c7-4f3a-92c7-6b03e02dc44f",
    "orderNo": "GCWS000039",
    "type": "MARKET",
    "side": "BUY",
    "status": "NEW",
    "symbol": "AAPL",
    "averagePrice": 0,
    "cumulativeQuantity": 0,
    "quantity": 1,
    "fees": 0,
    "orderExpires": "2019-03-29T20:00:00.000Z",
    "createdBy": "b25f0d36-b4e4-41f8-b3d9-9249e46402cd",
    "userID": "b25f0d36-b4e4-41f8-b3d9-9249e46402cd",
    "accountID": "b25f0d36-b4e4-41f8-b3d9-9249e46402cd.1403540676095",
    "accountNo": "DWZR000001",
    "created": "2019-03-28T22:40:03.240Z"
  }

If a partner does not use SQS they can receive the same information by calling the DriveWealth APIs. Web hooks and other integration techniques are not available; partners must use SQS or the APIs. Due to the nature of pushing events, almost all DriveWealth partners leverage SQS.


Standard Queue Structure



Handling Non-Sequential Order Events

Due to the standard queue structure it's highly likely that order events are going to be received out of sequence. Meaning a FILLED status orders.completed event may be received prior to a PARTIAL_FILL orders.updated event. To account for this discrepancy, the partner has to implement logic handling to determine whether or not to internalize a certain order notification.

To create the logic handling, the following fields should be considered:

  • type - the type of event that has been received
  • status - the current status of the order
  • cumulativeQuantity - the total number of shares filled up until that point in time. This value differs from lastShares as it encompasses the entire order lifecycle and not just the last update

The first logic check to determine if an event should be saved or ignored is to look at the type

  • If type is received as orders.completed it is known that the order has completed its lifecycle, meaning it should be saved.
  • The next step is to determine the status of the order from this completed message.
    • If status = FILLED the entire order had been completely filled and all shares / notional value requested were executed.
    • If status = CANCELLED proceed to check cumulativeQuantity to determine if any shares had been executed against. Should cumulativeQuantity be returned as > 0, then part of the customer's order had been executed and then wound up being cancelled.
    • If status = REJECTED proceed to check cumulativeQuantity to determine if any shares had been executed against. Should cumulativeQuantity be returned as > 0, then part of the customer's order had been executed and then wound up being rejected.
  • Since type = orders.completed all other received messages for the same order should be ignored.

The second logic check should be done if a type received is orders.updated, in order to determine how many shares were filled thus far in an orders lifecycle, and to not over count.

  • If type = orders.updated the next step is to check the cumulativeQuantity
  • For the first event message received within this orders lifecycle save the cumulativeQuantity value
  • If the following event message received has a cumulativeQuantity > the last saved cumulativeQuantity update the saved value with the new quantity
  • If the following event message received has a cumulativeQuantity < the last saved cumulativeQuantity ignore the event
  • This cycle continues until the eventType receive is orders.completed