OpenAPI

This article only covers technical aspects of algo orders. To learn more about how algo orders work, please see our general documentation Algorithmic Order Guide (June 2018).

The structure of an AlgoOrder

In OpenApi, an Algo order is a regular Order that has an AlgoOrderData section added in the Place Order or Change Order requests. The somewhat different thing about this, is that the parameters going into an algo order depend on the chosen strategy. This in turn means that creating a UI for handling algo orders requires the ability to adapt the fields according to the strategy.

This is an example of an algo order:

An Algo Order Request
// POST /openapi/trade/v2/orders

{
  "Uic": 211,
  "AssetType": "CfdOnStock",
  "Amount": 100,
  "BuySell": "Buy",
  "OrderType": "Limit",
  "OrderPrice": 150,
  "OrderDuration": {
    "DurationType": "DayOrder"
  },
  "AlgoOrderData": {
    "StrategyName": "Iceberg",
    "Arguments": {
      "MaxFloor": 100
    }
  }
}

The AlgoOrderData part contains the name of the strategy and an "Arguments"-object. The contents of the Arguments are the part that depends on the chosen strategy. In the example above, there is a parameter named "MaxFloor" that is of integer type. Parameter names and types are all exposed through OpenApi to make it possible for developers to create the required UI or validate the parameters before placing orders.

Strategies and parameters

To be able to determine what strategies are available for a given instrument, and what arguments those strategies support, we start in the Reference Data service. Looking up instrument details for a given instrument, will provide a list of supported strategies:

Abbreviated InstrumentDetails response
// GET /openapi/ref/v1/instruments/details/211/CfdOnStock

{
  "AmountDecimals": 0,
  "AssetType": "CfdOnStock",
  "CurrencyCode": "USD",
  "DefaultAmount": 0,
  "DefaultSlippage": 0,
  "DefaultSlippageType": "Ticks",
  "Description": "Apple Inc.",
  "Exchange": {
    "CountryCode": "US",
    "ExchangeId": "NASDAQ",
    "Name": "NASDAQ"
  },
...
  "SupportedStrategies": [
    "With Volume",
    "Implementation Shortfall",
    "Smart Dark",
    "Iceberg",
    "MOC",
    "IEX",
    "Stop POV"
  ],
...
  "Symbol": "AAPL:xnas",
  "Uic": 211,
  "YearlyExpensePercent": 0
}

These strategy names can be looked up in the AlgoStrategies endpoint (remember to URL-encode the names, as they can contain spaces), providing a response like this:

AlgoStrategies endpoint response (long)
// GET /openapi/ref/v1/algostrategies/With%20Volume

{
  "Description": "Group of With Volume strategies",
  "Name": "With Volume",
  "Parameters": [
    {
      "DataType": "UtcTimeStamp",
      "Description": "Time when order should stop working",
      "DisplayName": "EndTime",
      "IsEditable": true,
      "IsMandatory": false,
      "MaxDayTimeValue": "23:59:00",
      "MinDayTimeValue": "00:00:00",
      "Name": "ExpireTime",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "Price",
      "Description": "Specifies 'I Would' trigger price in absolute terms",
      "DisplayName": "IWouldPrice",
      "IsEditable": true,
      "IsMandatory": false,
      "MaxFloatValue": 0,
      "MinFloatValue": 0,
      "Name": "TriggerPx",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "Int",
      "Description": "Specifies the volume limit as a percentage",
      "DisplayName": "MaxParticipationRate",
      "IsEditable": true,
      "IsMandatory": true,
      "MaxFloatValue": 15,
      "MinFloatValue": 0,
      "Name": "ParticipationRate",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "UtcTimeStamp",
      "Description": "Time when order should start working",
      "DisplayName": "StartTime",
      "IsEditable": true,
      "IsMandatory": false,
      "Name": "EffectiveTime",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "String",
      "Description": "Indicates open auction inclusion",
      "DisplayName": "InOpenAuction",
      "IsEditable": true,
      "IsMandatory": true,
      "Name": "InOpenAuction",
      "ParameterValues": [
        {
          "Name": "No",
          "Value": "N"
        },
        {
          "Name": "Yes",
          "Value": "Y"
        }
      ],
      "UiOrderingIndex": 0
    },
    {
      "DataType": "String",
      "Description": "Indicates close auction inclusion",
      "DisplayName": "InCloseAuction",
      "IsEditable": true,
      "IsMandatory": true,
      "Name": "InCloseAuction",
      "ParameterValues": [
        {
          "Name": "No",
          "Value": "N"
        },
        {
          "Name": "Yes",
          "Value": "Y"
        }
      ],
      "UiOrderingIndex": 0
    }
  ],
  "SupportedDurationTypes": [
    "DayOrder"
  ],
  "SupportedOrderTypes": [
    "Market",
    "Limit"
  ],
  "TradableInstrumentTypes": [
    "Stock",
    "CfdOnStock"
  ]
}

This response contains information about the supported OrderTypes, InstrumentTypes and Duration types for the given strategy, as well as a list of parameters that can or must be provided when placing an order for this strategy.

Each parameter is described by a number of properties:

An example of a parameter
{
  "DataType": "Int",
  "Description": "Specifies the volume limit as a percentage",
  "DisplayName": "MaxParticipationRate",
  "IsEditable": true,
  "IsMandatory": true,
  "MaxFloatValue": 15,
  "MinFloatValue": 0,
  "Name": "ParticipationRate",
  "UiOrderingIndex": 0
}

The "Name" is the name that must be provided to the orders endpoint along with the value, whereas "DisplayName" is the name to display in a UI (this can be translated or reformulated of course). The "Description" is a descriptive text to explain the meaning of the parameter to the user.

"IsMandatory" indicates if the parameter is required, or can be omitted in the order-request, "IsEditable" tells if the parameter can be altered, when changing an existing order.

Numeric parameters, can be constrained to a "MaxFloatValue" and "MinFloatValue" (even integer types use the "float" constraint). Parameters of type UtcTimestamp can be constrained by "MinDayTimeValue" and "MaxDayTimeValue" . 

If a specific ordering of the parameters in the UI is configured, the "UiOrderingIndex", will indicate the relative ordering of the parameters.

Parameter types

The "DataType" field supports the following 6 datatypes:

DataTypeDescriptionExampleTypical UI element
Char a single character string"a"Text input field
Intan integer 12Numeric input field
Pricea price specified as a decimal number23.0037Numeric input field (allowing decimals)
Qtyquantity specified as an integer12Numeric input field
Stringa "choose one from a list" value like a dropdown (see below)"Anyone"Dropdown or Set of radio buttons
UtcTimestamp a timestamp (not a full date) provided as a string"13:27:53"Specialized TimePicker or 3 2-digit numeric inputs

All parameters regardless of datatype expect non-null values, as null is considered equivalent to the argument not being provided.

Parameters of datatype "String" are also provided with a list of selectable values:

An example of a String-type parameter
    {
      "DataType": "String",
      "Description": "Indicates close auction inclusion",
      "DisplayName": "InCloseAuction",
      "IsEditable": true,
      "IsMandatory": true,
      "Name": "InCloseAuction",
      "ParameterValues": [
        {
          "Name": "No",
          "Value": "N"
        },
        {
          "Name": "Yes",
          "Value": "Y"
        }
      ],
      "UiOrderingIndex": 0
    }

The "ParameterValues" array, provides a "Name" to display as well as a "Value" that is the value to submit to submit when placing the order. Since only one value is to be selected, a dropdown box or a set of radio buttons are typical UI elements used for implementing these parameters.

Placing an Algo Order

When the user have filled out the relevant fields in the UI, it is faily trivial to put together the AlgoOrderData structure by combining the "Name" property of each parameter with the selected value, to create the "Arguments" collection:

AlgoOrderData
  "AlgoOrderData": {
    "StrategyName": "With Volume",
    "Arguments": {
      "ParticipationRate": 12,
	  "InOpenAuction": "Y",
      "InCloseAuction":"N",
	  "StartTime": "12:05:30"
    }

This is subsequently added to a regular Place Order Request.

Editing Algo Orders

You cannot change the strategy of an order after it has been placed, so for the entire Edit Order scenario, the Strategy remains the same.

When having to edit an order, start by requesting the Order Details for the order in question using Portfolio's order/{id}/details endpoint, which will include AlgoStrategyName, and a list of AlgoOrderDetails.

OrderDetails response, including Algo data
// GET /openapi/port/v1/orders/49922194/details/

{
  "AccountId": "...",
  "AccountKey": "...",
  "AlgoStrategyName": "With Volume",
  "AlgoOrderDetails": {
    "ParticipationRate": 12,
    "InOpenAuction": "Y",
    "InCloseAuction":"N",
    "StartTime": "12:05:30"},
  "Amount": 100,
  "AssetType": "CfdOnStock",
  "BuySell": "Buy",
  "CalculationReliability": "OkWithConditions",
  "ClientKey": "....",
  "CurrentPrice": 143.44,
  "CurrentPriceDelayMinutes": 15,
  "CurrentPriceLastTraded": "2017-06-15T13:47:27.032000Z",
  "CurrentPriceType": "Ask",
  "DistanceToMarket": 1.28,
  "Duration": {
    "DurationType": "DayOrder"
  },
  "MarketPrice": 143.44,
  "OpenOrderType": "Limit",
  "OrderId": "49922194",
  "OrderRelation": "StandAlone",
  "OrderTime": "2017-06-15T13:58:08.933000Z",
  "Price": 142.16,
  "RelatedOpenOrders": [],
  "Status": "Working",
  "Uic": 211
}

By using the AlgoOrderDetails, and the AlgoStrategy data from ref you can create a UI as described above, but pre-filled with the original data. The major difference is that any parameter that is marked with IsEditable = false must be locked, as these data cannot change.

When the order is submitted, all the fields must be included, including the ones that were not "editable" - omitting fields will be interpreted as if they were removed from the order.

Example of usage

Load the instrument details for the instrument we are interested in

Algo Strategies
// GET /openapi/ref/v1/instruments/details/211/CfdOnStock

{
  "Data": [
    {
      "AmountDecimals": 0,
      "AssetType": "CfdOnStock",
      "CurrencyCode": "USD",
      "DefaultAmount": 0,
      "DefaultSlippage": 0,
      "DefaultSlippageType": "Ticks",
      "Description": "Apple Inc.",
      "Exchange": {
        "CountryCode": "US",
        "ExchangeId": "NASDAQ",
        "Name": "NASDAQ"
      },
	  ....
  	  ....
	  "SupportedStrategies": [
        "With Volume",
        "Implementation Shortfall",
        "Smart Dark",
        "Pre-Market Limit",
        "MOC",
        "IEX",
        "Stop POV"
        ],
      "Symbol": "AAPL:xnas",
	  ....
	  ....
	}
	]
}

We choose to get data for "With Volume" strategy:

With Volume Result
// GET /openapi/ref/v1/algostrategies/With%20Volume

{
  "Description": "Group of With Volume strategies",
  "MinAmountUSD": 0,
  "Name": "With Volume",
  "Parameters": [
    {
      "DataType": "UtcTimeStamp",
      "Description": "Time when order should stop working",
      "DisplayName": "EndTime",
      "IsEditable": true,
      "IsMandatory": false,
      "MaxDayTimeValue": "23:59:00",
      "MinDayTimeValue": "00:00:00",
      "Name": "EndTime",
      "UiDefaultValue": "22:22:22",
      "UiOrderingIndex": 0,
      "UiStepSize": 1
    },
    {
      "DataType": "Price",
      "Description": "Specifies 'I Would' trigger price in absolute terms",
      "DisplayName": "IWouldPrice",
      "IsEditable": true,
      "IsMandatory": false,
      "Name": "IWouldPrice",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "Int",
      "Description": "Specifies the volume limit as a percentage",
      "DisplayName": "MaxParticipationRate",
      "IsEditable": true,
      "IsMandatory": true,
      "Name": "MaxParticipationRate",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "UtcTimeStamp",
      "Description": "Time when order should start working",
      "DisplayName": "StartTime",
      "IsEditable": true,
      "IsMandatory": false,
      "Name": "StartTime",
      "UiOrderingIndex": 0
    },
    {
      "DataType": "String",
      "Description": "Indicates open auction inclusion",
      "DisplayName": "InOpenAuction",
      "IsEditable": true,
      "IsMandatory": false,
      "Name": "InOpenAuction",
      "ParameterValues": [
        {
          "Name": "No",
          "Value": "N"
        },
        {
          "Name": "Yes",
          "Value": "Y"
        }
      ],
      "UiOrderingIndex": 0
    },
    {
      "DataType": "String",
      "Description": "Indicates close auction inclusion",
      "DisplayName": "InCloseAuction",
      "IsEditable": true,
      "IsMandatory": false,
      "Name": "InCloseAuction",
      "ParameterValues": [
        {
          "Name": "No",
          "Value": "N"
        },
        {
          "Name": "Yes",
          "Value": "Y"
        }
      ],
      "UiOrderingIndex": 0
    }
  ],
  "SupportedDurationTypes": [
    "DayOrder"
  ],
  "SupportedOrderTypes": [
    "Market",
    "Limit"
  ],
  "TradableInstrumentTypes": [
    "ContractFutures",
    "Stock",
    "CfdOnStock",
    "StockIndex",
    "CfdOnIndex",
    "CfdOnFutures"
  ]
}

Using this information we can place an order, please note, we don't have to fill out all parameters, so we just fill out the mandatory "MaxParticipationRate", and the not mandatory "InOpenAuction":

Place order Request
// POST /openapi/trade/v2/orders

{
  "Uic": 211,
  "AssetType": "cfdonstock",
  "Amount": 100,
  "BuySell": "Buy",
  "OrderType": "Limit",
  "OrderPrice": 150,
  "OrderDuration": {
    "DurationType": "DayOrder"
  },
  "AlgoOrderData": {
    "StrategyName": "With Volume",
    "Arguments": {
      "MaxParticipationRate": 50,
      "InOpenAuction": "N"
    }
  }
}

To See the order, we get a list of orders, select pick the order id and ask for order details, as in the next two queries.

OpenOrders result
// GET /openapi/port/v1/orders/me

{
  "__count": 7,
  "Data": [
    {
      "AccountId": "...",
      "AccountKey": "YourValidAccountKey",
      "AlgoStrategyName": "With Volume",
      "Amount": 100,
      "AssetType": "CfdOnStock",
      "BuySell": "Buy",
     ....
      "Duration": {
        "DurationType": "DayOrder"
      },
      "MarketPrice": 188.2,
      "OpenOrderType": "Limit",
      "OrderAmountType": "Quantity",
      "OrderId": "53654487",
      "OrderRelation": "StandAlone",
      "OrderTime": "2018-05-25T07:48:28.216666Z",
      "Price": 150,
      "RelatedOpenOrders": [],
      "Status": "Working",
      "Uic": 211
    },
...
OrderDetails
// GET /openapi/port/v1/orders/{ClientKey}/53654487


{
  "AccountId": "...",
  "AccountKey": "YourValidAccountKey",
  "AlgoOrderDetails": {
    "MaxParticipationRate": "60",
    "InOpenAuction": "N"
  },
  "AlgoStrategyName": "With Volume",
  "Amount": 100,
  "AssetType": "CfdOnStock",
  "BuySell": "Buy",
  "CalculationReliability": "Ok",
  "ClientKey": "...",
  "CorrelationKey": "643a929d-adaa-4804-989a-1fb95dcf6f29",
  "CurrentPrice": 188.2,
  "CurrentPriceDelayMinutes": 0,
  "CurrentPriceLastTraded": "2018-05-24T19:59:59.984000Z",
  "CurrentPriceType": "Ask",
  "DistanceToMarket": 38.2,
  "Duration": {
    "DurationType": "DayOrder"
  },
  "MarketPrice": 188.2,
  "OpenOrderType": "Limit",
  "OrderAmountType": "Quantity",
  "OrderId": "53654487",
  "OrderRelation": "StandAlone",
  "OrderTime": "2018-05-25T09:04:01.873333Z",
  "Price": 150,
  "RelatedOpenOrders": [],
  "Status": "Working",
  "Uic": 211
}

If we would like to patch one or more of the parameters, we will call orders patch endpoint

Order Patch
// PATCH /openapi/trade/v2/orders

{
  "AccountKey": "YourValidAccountKey",
  "Amount": 100,
  "AssetType": "CfdOnStock",
  "OrderId": "53654487",
  "OrderType": "Limit",
  "OrderDuration": {
    "DurationType": "DayOrder"
  },
  "AlgoOrderData": {
    "StrategyName": "With Volume",
    "Arguments": {
      "MaxParticipationRate": "60",
      "InOpenAuction": "N"
    }
  }  
}