Table of Contents-zone | ||
---|---|---|
| ||
OverviewThe Exchange Streaming API provides low latency access to Betfair Exchange market data allowing you to subscribe to and efficiently track changes to market, price and order data. The protocol is based on ssl sockets (normal) with a CRLF json protocol. We publish a definition of the schema of the json messages in the Swagger format. |
Swagger Definition
We provide a Swagger schema to allow specification browsing & code generation for various languages; please use:
Swagger: http://editor.swagger.io/#/
Market Stream: Swagger Definition: ESASwaggerSchema.json
To generate a client for the programming language of your choice:
...
Info | ||
---|---|---|
| ||
|
Tip | ||
---|---|---|
| ||
Betfair support sample applications are available for both C# and Java via https://github.com/betfair/stream-api-sample-code |
Typical Interactions with Stream API:
The typical API interactions are documented below (detail is below this).
Market Stream:
Order Stream:
Connection
Protocol
Every message is in json & terminated with a line feed (CRLF):
{json message}\r\n
Tip | ||
---|---|---|
| ||
As the protocol is CRLF delimited don't forget to turn-off Json pretty printing (C# has this on by default) |
TCP / SSL Connection
Connection is established with an SSL socket to the following address:
Code Block | ||
---|---|---|
| ||
stream-api.betfair.com:443 |
Tip | ||
---|---|---|
| ||
Once you have established a connection you should send a message within 15 seconds to avoid receiving a TIMEOUT error |
Pre-production (beta) endpoint
Warning |
---|
For pre-production (beta) releases the following URL should be used for integration testing only. |
Code Block | ||
---|---|---|
| ||
stream-api-integration.betfair.com |
Basic Message Protocol
Two base message classes exist:
- RequestMessage - These are messages sent to the server.
- ResponseMessage - These are messages received from the server.
Every child message type has:
- id - A unique counter you should supply on a RequestMessage and which will be supplied back on a ResponseMessage.
- op - This identifies the request type and may be used to switch / deserialize correctly
Info |
---|
Note: Any fields representing time and having a long type will represent the UNIX Timestamps (See https://currentmillis.com/ for conversions) |
RequestMessage
RequestMessage is the base class for requests from the client; the discriminator is op=<message type>
Key fields:
...
Tip | ||
---|---|---|
| ||
|
ResponseMessage
ResponseMessage is the base class for responses back to the client; the discriminator is op=<message type>
Key fields:
...
Tip | ||
---|---|---|
| ||
As mentioned earlier the id=<request id> and links your request with your response. ChangeMessages carry the id of the original request that established the subscription |
Status / StatusMessage
Every request receives a status response with a matching id.
Key fields:
statusCode - The status of the request i.e success / fail
- SUCCESS - Call processed correctly
- FAILURE - Call failed (inspect errorCode and errorMessage for reason)
- connectionClosed - Boolean set to true if the connection was closed as a result of a failure
errorCode - The type of error in case of a failure - see the swagger spec / enum.
errorMessage - Additional message in case of a failure
ErrorCode
This categorizes the various error codes that could be expected (these are subject to change and extension)
...
INVALID_INPUT
...
Failure code returned when an invalid input is provided (could not deserialize the message)
...
TIMEOUT
...
Failure code when a client times out (i.e. too slow sending data)
...
We maintain sample code in Java, C# and Node.js here: https://github.com/betfair/stream-api-sample-code Sample Application - C#, Java & Node.jsA console based C#, Java and Node.js sample application is available for the Market & Order Streaming API and is available via https://github.com/betfair/stream-api-sample-code Users wishing to interact with the Streaming API using one of these languages are strongly advised to make use of this sample code. Swagger DefinitionFor users wishing to use other languages or develop their own implementation, we provide a swagger schema to allow browsing & code generation. We recommend using Swagger Code Gen (http://swagger.io/swagger-codegen/) for generation,
The Swagger editor can also be used to view the domain model
Typical Interactions with Stream API:The typical API interactions are documented below (detail is below this). Market Stream: Order Stream: ConnectionProtocolEvery message is in json & terminated with a line feed (CRLF): {json message}\r\n
TCP / SSL ConnectionConnection is established with an SSL socket to the following address:
Pre-production (beta) endpoint
Basic Message ProtocolTwo base message classes exist:
Every child message type has:
RequestMessageRequestMessage is the base class for requests from the client; the discriminator is op=<message type> Key fields:
ResponseMessageResponseMessage is the base class for responses back to the client; the discriminator is op=<message type> Key fields:
Status / StatusMessageEvery request receives a status response with a matching id. Key fields:
ErrorCodeThis categorizes the various error codes that could be expected (these are subject to change and extension)
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
Connection / ConnectionMessageThis is received by the client when it successfully opens a connection to the server Key fields:
Authentication / AuthenticationMessageThis message is the first message that the client must send on connecting to the server - you must be authenticated before any other request is processed. Key fields:
|
...
|
Subscription / SubscriptionMessage
...
Subscription / SubscriptionMessageThis message changes the client's subscription - there are currently two subscription message types:
On creating a subscription you will receive:
It is possible to subscribe multiple times - each replaces the previous (each will send a new initial image and deltas) - |
...
they are not additive. Key fields on a SubscriptionMessage:
|
...
ChangeMessageThis message is the payload that delivers changes (both initial image & updates) to a client - there are currently two change message types:
|
Key fields on a ChangeMessage:
...
Key fields on a ChangeMessage:
Change Message SegmentationThe below shows the key interactions for subscription & changes with segmentation applied: |
...
Typically on changing your subscription you will want to clear any local cache you maintain.
MarketSubscriptionMessageThis subscription type is used to receive price changes for one or more markets; your subscription criteria determine what you see. |
...
|
...
A MarketSubscription has two types of filter:
Limiting the amount of data that you consume will make your initial image much smaller (and faster) & suppress changes that are uninteresting to you. Market Filtering / MarketFilterAs with the APING API users have the ability to filter the market data they get from the new Exchange Stream API (ESA). All subscriptions are evaluated with a few default criteria:
Users can then specify the following filters when they subscribe to ESA:
|
...
Example marketSubscriptionFor example a subscription message with almost all filters enabled will look something like this:
|
...
Market data field filtering / MarketDataFilterA market data filter restricts the fields that you get back (and only if the fields have changed). Key fields:
|
...
...
The field filter flags are defined as:
|
...
|
...
EX_BEST_OFFERS
...
batb, batl
...
|
...
|
...
ExamplesMultiple field filters may be combined; a subscription message that contains data fields should look like the following:
|
...
Tip | ||
---|---|---|
| ||
Correctly configuring field filters can help by:
|
MC / MarketChangeMessage
This is the ChangeMessage stream of data we send back to you once you subscribe to the market stream.
Key fields:
...
The below example shows how to correctly use the ladderLevels marketDataFilter: {"op": "marketSubscription", "id": 1, "marketFilter": { "marketIds": [ "1.134085859" ] }, "marketDataFilter": { "ladderLevels": 2, "fields": [ "EX_MARKET_DEF", "EX_BEST_OFFERS" ] } }
MC / MarketChangeMessageThis is the ChangeMessage stream of data we send back to you once you subscribe to the market stream. Key fields:
|
...
Building a price cacheMost of the change based data (RunnerChange) is delta based - this means a few rules:
|
OrderSubscriptionMessage
This subscription type is used to receive order changes; there are no additional filter criteria (you will see the orders for the account you authenticated with).
OCM / OrderChangeMessage
This is the ChangeMessage stream of data we send back to you once you subscribe to the order stream.
Key fields:
- <as for ChangeMessage>
- oc / OrderAccountChange - the modifications to account's orders (will be null on a heartbeat)
- closed - indicates when the market is closed
- id / Market Id - the id of the market the order is on
- orc / Order Changes - a list of changes to orders on a runner
- id / Selection Id - the id of the runner (selection)
- uo / Unmatched Orders - orders on this runner that are unmatched
- Every order change is sent in full; the transient on a change to EXECUTION_COMPLETE is sent (but it would not be sent on initial image)
- id / Bet Id - the id of the order
- p / Price - the original placed price of the order
- s / Size - the original placed size of the order
- bsp / BSP Liability - the BSP liability of the order (null if the order is not a BSP order)
- side / Side - the side of the order
- status / Status - the status of the order (E = EXECUTABLE, EC = EXECUTION_COMPLETE)
- pt / Persistence Type - whether the order will persist at in play or not (L = LAPSE, P = PERSIST, MOC = Market On Close)
- ot / Order Type - the type of the order (L = LIMIT, MOC = MARKET_ON_CLOSE, LOC = LIMIT_ON_CLOSE)
- pd / Placed Date - the date the order was placed
- md / Matched Date - the date the order was matched (null if the order is not matched)
- avp / Average Price Matched - the average price the order was matched at (null if the order is not matched
- sm / Size Matched - the amount of the order that has been matched
- sr / Size Remaining - the amount of the order that is remaining unmatched
- sl / Size Lapsed - the amount of the order that has been lapsed
- sc / Size Cancelled - the amount of the order that has been cancelled
- sv / Size Voided - the amount of the order that has been voided
- rac / Regulator Auth Code - the auth code returned by the regulator
- rc / Regulator Code - the regulator of the order
- Price point / full depth Ladders (price, size - tuples - keyed by price) of matches:
- mb / Matched Backs - matched amounts by distinct matched price on the Back side for this runner
- ml / Matched Lays - matched amounts by distinct matched price on the Lay side for this runner
Building an order cache
An order cache is somewhat simpler as orders are sent in full (on change) and only matches need delta merging
- img / Image - if this is set to true then you should replace this item in your cache
- Orders - replace each order according to order id.
- Price point / full depth ladders
- [1.2, 20] -> Insert / Update price 1.2 with size 20
- [1.2, 0] -> Remove price 1.2 i.e. there is no size at this price
- An empty list of points also means the ladder is now empty
- [1.2, 20] -> Insert / Update price 1.2 with size 20
...
Tip | ||
---|---|---|
| ||
|
Performance Considerations
Here are a few tips on performance which are worth bearing in mind:
Tip | ||
---|---|---|
| ||
|
Currency Support
The Exchange Stream API supports GBP currency only.
Those looking to convert data from GBP to a different currency should use listCurrencyRates to do so.
Tip | ||
---|---|---|
| ||
Market subscriptions - are always in underlying exchange currency - GBP. The default roll-up for GBP is £2 for batb / batl and bdatb / bdatl, This means that stakes of less than £2 (or currency equivalent) are rolled up to the next available price on the odds ladder. For atb / atl there is no roll-up. Available volume is displayed at all prices including those with less than £2 available. Orders subscriptions - are provided in the currency of the account that the orders are placed in. |
Runner Removals on the Order Stream
When a Rule 4 Runner Removal occurs in a Horse Race the price of matched bets on remaining runners are reduced by a Reduction Factor.
For these matched bets, you will receive on the Order Stream both a uo for the affected bet and the relevant updates to mb or ml (reducing the matched volume at the original matched price and adding volume at the new reduced price).
Initial bet placement at price 12
{ "op" : "ocm" , "id" : 2 , "clk" : "AK0CAPsBALEC" , "pt" : 1467219304831 , "oc" :[{ "id" : "1.102151675" , "orc" :[{ "fullImage" : true , "id" : 6113662 , "uo" :[{ "id" : "10822867886" , "p" : 12 , "s" : 2 , "side" : "B" , "status" : "E" , "pt" : "L" , "ot" : "L" , "pd" : 1467219304000 , "sm" : 0 , "sr" : 2 , "sl" : 0 , "sc" : 0 , "sv" : 0 , "rac" : "" , "rc" : "REG_GGC" }]}]}]} |
Bet fully matched at price 12
{ "op" : "ocm" , "id" : 2 , "clk" : "AK0CAPsBALMC" , "pt" : 1467219316709 , "oc" :[{ "id" : "1.102151675" , "orc" :[{ "id" : 6113662 , "uo" :[{ "id" : "10822867886" , "p" : 12 , "s" : 2 , "side" : "B" , "status" : "EC" , "pt" : "L" , "ot" : "L" , "pd" : 1467219304000 , "md" : 1467219316000 , "avp" : 12 , "sm" : 2 , "sr" : 0 , "sl" : 0 , "sc" : 0 , "sv" : 0 }], "mb" :[[ 12 , 2 ]]}]}]} |
Runner removed (and so bet reduced in price to 9.47)
{ "op" : "ocm" , "id" : 2 , "clk" : "AK0CAJACALsC" , "pt" : 1467219376611 , "oc" :[{ "id" : "1.102151675" , "orc" :[{ "id" : 6113662 , "uo" :[{ "id" : "10822867886" , "p" : 12 , "s" : 2 , "side" : "B" , "status" : "EC" , "pt" : "L" , "ot" : "L" , "pd" : 1467219304000 , "md" : 1467219316000 , "avp" : 9.47 , "sm" : 2 , "sr" : 0 , "sl" : 0 , "sc" : 0 , "sv" : 0 }], "mb" :[[ 9.47 , 2 ],[ 12 , 0 ]]}]}]} |
See the avp in the uo record showing the new price of 9.47 and see the two entries in mb, one to remove the previously added size of 2 at price point 12 and one to add the size of 2 into the new price point of size 9.47.
Bets placed on the actual removed runner will be voided/lapsed (for matched/unmatched bets respectively), these updates will not be sent through the order stream. The advice to consumers should be to also consume the market stream, detect that the runner has been marked as REMOVED in an update to the Market Definition and to therefore consider all bets held on that runner to be Void (or Lapsed for unmatched bets).
Sample Applications - C# & Java
A console based C# & Java sample application is available for the Market & Order Streaming API and is available via https://github.com/betfair/stream-api-sample-code
...
MarketDefinition FieldsThe following fields are returned within the marketDefintition.
|
Filter name | Type | Mandatory | Default | Description |
---|---|---|---|---|
accountIds | Set<Integer> | No | null | This is for internal use only & should not be set on your filter (your subscription is already locked to your account). |
includeOverallPosition | Boolean | No | true | Returns overall / net position (OrderRunnerChange.mb / OrderRunnerChange.ml) |
customerStrategyRefs | Set<String> | No | null | Restricts to specified customerStrategyRefs (specified in placeOrders) ; this will filter orders and StrategyMatchChanges accordingly (Note: overall position is not filtered) |
partitionMatchedByStrategyRef | Boolean | No | false | Returns strategy positions (OrderRunnerChange.smc=Map<customerStrategyRef, StrategyMatchChange>) - these are sent in delta format as per overall position. |
Example
{"op":"orderSubscription","orderFilter":{"includeOverallPosition":false,"customerStrategyRefs":["betstrategy1"],"partitionMatchedByStrategyRef":true},"segmentationEnabled":true}
OCM / OrderChangeMessage
This is the ChangeMessage stream of data we send back to you once you subscribe to the order stream.
Key fields:
- <as for ChangeMessage>
- oc / OrderAccountChange - the modifications to account's orders (will be null on a heartbeat)
- closed - indicates when the market is closed
- id / Market Id - the id of the market the order is on
- fullImage - replace existing data at market level with the data supplied: it is not a delta (or null if delta)
- orc / Order Changes - a list of changes to orders on a runner
- fullImage - replace existing data at runner level with the data supplied: it is not a delta (or null if delta)
- id / Selection Id - the id of the runner (selection)
- hc / Handicap - the handicap of the runner (selection) (null if not applicable)
- uo / Unmatched Orders - orders on this runner that are unmatched
- Every order change is sent in full; the transient on a change to EXECUTION_COMPLETE is sent (but it would not be sent on initial image)
- id / Bet Id - the id of the order
- p / Price - the original placed price of the order
- s / Size - the original placed size of the order
- bsp / BSP Liability - the BSP liability of the order (null if the order is not a BSP order)
- side / Side - the side of the order
- status / Status - the status of the order (E = EXECUTABLE, EC = EXECUTION_COMPLETE)
- pt / Persistence Type - whether the order will persist at in play or not (L = LAPSE, P = PERSIST, MOC = Market On Close)
- ot / Order Type - the type of the order (L = LIMIT, MOC = MARKET_ON_CLOSE, LOC = LIMIT_ON_CLOSE)
- pd / Placed Date - the date the order was placed
- md / Matched Date - the date the order was matched (null if the order is not matched)
- cd / Cancelled Date - the date the order was cancelled (null if the order is not cancelled)
- ld / Lapsed Date - the date the order was lapsed (null if the order is not lapsed)
- lsrc/Lapse Status Reason Code - the reason that some or all of this order has been lapsed (null if no portion of the order is lapsed)
- avp / Average Price Matched - the average price the order was matched at (null if the order is not matched
- sm / Size Matched - the amount of the order that has been matched
- sr / Size Remaining - the amount of the order that is remaining unmatched
- sl / Size Lapsed - the amount of the order that has been lapsed
- sc / Size Cancelled - the amount of the order that has been cancelled
- sv / Size Voided - the amount of the order that has been voided
- rac / Regulator Auth Code - the auth code returned by the regulator
- rc / Regulator Code - the regulator of the order
- rfo / Reference Order - the customer supplied order reference
- rfs / Reference Strategy - the customer supplied strategy reference used to group orders together - default is ""
- Price point / full depth Ladders (price, size - tuples - keyed by price) of matches:
- mb / Matched Backs - matched amounts by distinct matched price on the Back side for this runner
- ml / Matched Lays - matched amounts by distinct matched price on the Lay side for this runner
Building an order cache
An order cache is somewhat simpler as orders are sent in full (on change) and only matches need delta merging
- fullImage - if the market or runner's fullImage value is set to true then you should replace this item in your cache N.B. it is possible for the fulllImage flag to sent with an empty update for a market/runner which indicates you no longer have any position on that market/runner and it can be removed from your cache completely
- Orders - replace each order according to order id.
- Price point / full depth ladders
- [1.2, 20] -> Insert / Update price 1.2 with size 20
- [1.2, 0] -> Remove price 1.2 i.e. there is no size at this price
- An empty list of points also means the ladder is now empty
- [1.2, 20] -> Insert / Update price 1.2 with size 20
Tip | ||
---|---|---|
| ||
Market subscriptions - are always in underlying exchange currency - GBP. The default roll-up for GBP is £1 for batb / batl and bdatb / bdatl, This means that stakes of less than £1 (or currency equivalent) are rolled up to the next available price on the odds ladder. For atb / atl there is no roll-up. Available volume is displayed at all prices including those with less than £2 available. Orders subscriptions - are provided in the currency of the account that the orders are placed in. |
Tip | ||
---|---|---|
| ||
New subscriptions: Will receive an initial image with only E - Executable orders (unmatched). Live subscriptions: Will receive a transient of the order to EC - Execution Complete as the order transits into that state (allowing you to remove the order from your cache). Please note: EXECUTION_COMPLETE (fully matched) orders are only returned when transitioning from EXECUTABLE to EXECUTION_COMPLETE. The full details of EXECUTION_COMPLETE orders can only be viewed using listCurrentOrders/listMarketBook using orderProjections. |
Tip | ||
---|---|---|
| ||
During normal streaming, you may on rare occasions receive a market-level snapshot, in which case you should replace the item in your cache. The update will be a fullImage, as shown in the example below {"clk": "AIElAJgiAIYjAMAhAOsm", "oc": [{"orc": [{"uo": [{"status": "E", "rfs": "", "sm": 0, "pt": "L", "sr": 2, "rc": "REG_GGC", "sv": 0, "side": "B", "p": 990, "s": 2, "pd": 1603894536000, "sl": 0, "sc": 0, "ot": "L", "rfo": "", "id": "215144775671", "rac": ""}], "id": 30246, "fullImage": true}], "id": "1.174743281", "fullImage": true}], "pt": 1603895058618, "op": "ocm"} |
Example Output of Order Stream Message on Connection/Re-connection
Here's an example showing the data provided following a connection/re-connection to the Order Stream API. The example shows matched backs on two separate markets one of which has a size remaining of 0.25.
Code Block | ||||
---|---|---|---|---|
| ||||
{
"op": "ocm",
"id": 6,
"initialClk": "GpOH0JwBH762w50BHKKomJ0BGpzR5ZoBH5mWsJwB",
"clk": "AAAAAAAAAAAAAA==",
"conflateMs": 0,
"heartbeatMs": 5000,
"pt": 1468943673782,
"ct": "SUB_IMAGE",
"oc": [{
"id": "1.125657695",
"orc": [{
"fullImage": true,
"id": 48756,
"mb": [
[1.4, 2]
]
}]
}, {
"id": "1.125657760",
"orc": [{
"fullImage": true,
"id": 151478,
"uo": [{
"id": "71352090695",
"p": 12,
"s": 5,
"side": "B",
"status": "E",
"pt": "L",
"ot": "L",
"pd": 1468919099000,
"md": 1468933833000,
"avp": 12,
"sm": 4.75,
"sr": 0.25,
"sl": 0,
"sc": 0,
"sv": 0
}],
"mb": [
[12, 4.75]
]
}]
}]
} |
Remaining 0.25 is then matched on marketId 1.125657760
Code Block | ||||
---|---|---|---|---|
| ||||
{
"op": "ocm",
"id": 10,
"initialClk": "GtD10ZwBH5OJxZ0BHK75mZ0BGsKq6JoBH4THsZwB",
"clk": "AAAAAAAAAAAAAA==",
"conflateMs": 0,
"heartbeatMs": 5000,
"pt": 1468944647413,
"ct": "SUB_IMAGE",
"oc": [{
"id": "1.125670254",
"orc": [{
"fullImage": true,
"id": 5643663
}]
}, {
"id": "1.125657760",
"orc": [{
"fullImage": true,
"id": 151478,
"mb": [
[12, 5]
]
}]
}, {
"id": "1.125657695",
"orc": [{
"fullImage": true,
"id": 48756,
"mb": [
[1.4, 2]
]
}]
}]
} |
Heartbeat / HeartbeatMessage
This is an explicit heartbeat request (in addition to server heartbeat interval which is automatic).
This functionality should not normally be necessary unless you need to keep a firewall open.
Tip | ||
---|---|---|
| ||
No - under normal circumstances the subscription level ChangeType.HEARTBEAT is an acceptable guarantee of connection health. Use the HeartbeatMessage only if you need to keep a firewall open - as it will incur some performance penalty (as a response will block your connection) |
Re-connection / Re-subscription
If a client is disconnected a client may connect, authenticate and re-subscribe.
Prerequisite steps:
- Store your subscription criteria (re-subscribe will only work correctly with identical subscription criteria.
- Store initialClk (normally only initial image) & Clk (normally on every non-segmented message or a SEG_END) on any change message they are sent on.
Connection is broken.
- Connect & Authenticate as normal
- Subscribe setting initialClk and Clk to the last values sent on the subscription
- Change message with ChangeType.RESUB_DELTA is sent - this will patch your cache
- Some markets might have img=true set indicating they are either new or can't be patched.
Tip | ||
---|---|---|
| ||
|
Performance Considerations
Here are a few tips on performance which are worth bearing in mind:
Tip | ||
---|---|---|
| ||
|
Currency Support
The Exchange Stream API supports GBP currency only.
Those looking to convert data from GBP to a different currency should use listCurrencyRates to do so.
Tip | ||
---|---|---|
| ||
Market subscriptions - are always in underlying exchange currency - GBP. The default roll-up for GBP is |
£1 for batb / batl and bdatb / bdatl, This means that stakes of less than |
£1 (or currency equivalent) are rolled up to the next available price on the odds ladder. For atb / atl there is no roll-up. Available volume is displayed at all prices including those with less than £2 available. Orders subscriptions - |
Tip | ||
---|---|---|
| ||
New subscriptions: Will receive an initial image with only E - Executable orders (unmatched). Live subscriptions: Will receive a transient of the order to EC - Execution Complete as the order transits into that state (allowing you to remove the order from your cache). |
Example Output of Order Stream Message on Connection/Re-connection
Here's an example showing the data provided following a connection/re-connection to the Order Stream API. The example shows matched backs on two separate markets one of which has a size remaining of 0.25.
Code Block | ||||
---|---|---|---|---|
| ||||
{
"op": "ocm",
"id": 6,
"initialClk": "GpOH0JwBH762w50BHKKomJ0BGpzR5ZoBH5mWsJwB",
"clk": "AAAAAAAAAAAAAA==",
"conflateMs": 0,
"heartbeatMs": 5000,
"pt": 1468943673782,
"ct": "SUB_IMAGE",
"oc": [{
"id": "1.125657695",
"orc": [{
"fullImage": true,
"id": 48756,
"mb": [
[1.4, 2]
]
}]
}, {
"id": "1.125657760",
"orc": [{
"fullImage": true,
"id": 151478,
"uo": [{
"id": "71352090695",
"p": 12,
"s": 5,
"side": "B",
"status": "E",
"pt": "L",
"ot": "L",
"pd": 1468919099000,
"md": 1468933833000,
"avp": 12,
"sm": 4.75,
"sr": 0.25,
"sl": 0,
"sc": 0,
"sv": 0
}],
"mb": [
[12, 4.75]
]
}]
}]
} |
Remaining 0.25 is then matched on marketId 1.125657760
Code Block | ||||
---|---|---|---|---|
| ||||
{
"op": "ocm",
"id": 10,
"initialClk": "GtD10ZwBH5OJxZ0BHK75mZ0BGsKq6JoBH4THsZwB",
"clk": "AAAAAAAAAAAAAA==",
"conflateMs": 0,
"heartbeatMs": 5000,
"pt": 1468944647413,
"ct": "SUB_IMAGE",
"oc": [{
"id": "1.125670254",
"orc": [{
"fullImage": true,
"id": 5643663
}]
}, {
"id": "1.125657760",
"orc": [{
"fullImage": true,
"id": 151478,
"mb": [
[12, 5]
]
}]
}, {
"id": "1.125657695",
"orc": [{
"fullImage": true,
"id": 48756,
"mb": [
[1.4, 2]
]
}]
}]
} |
Heartbeat / HearbeatMessage
This is an explicit heartbeat request (in addition to server heartbeat interval which is automatic).
This functionality should not normally be necessary unless you need to keep a firewall open.
Tip | ||
---|---|---|
| ||
No - under normal circumstances the subscription level ChangeType.HEARTBEAT is an acceptable guarantee of connection health. Use the HeartbeatMessage only if you need to keep a firewall open - as it will incur some performance penalty (as a response will block your connection) |
Re-connection / Re-subscription
If a client is disconnected a client may connect, authenticate and re-subscribe.
Prerequisite steps:
- Store your subscription criteria (re-subscribe will only work correctly with identical subscription critieria
- Store initialClk (normally only initial image) & Clk (normally on every non-segmented message or a SEG_END) on any change message they are sent on.
Connection is broken.
...
Runner Removals on the Order StreamWhen a Rule 4 Runner Removal occurs in a Horse Race the price of matched bets on remaining runners are reduced by a Reduction Factor. For these matched bets, you will receive on the Order Stream both a uo for the affected bet and the relevant updates to mb or ml (reducing the matched volume at the original matched price and adding volume at the new reduced price). Initial bet placement at price 12
Bet fully matched at price 12
Runner removed (and so bet reduced in price to 9.47)
See the avp in the uo record showing the new price of 9.47 and see the two entries in mb, one to remove the previously added size of 2 at price point 12 and one to add the size of 2 into the new price point of size 9.47. Bets placed on the actual removed runner will be voided/lapsed (for matched/unmatched bets respectively) and these will also be sent through on the Order Stream. Identifying Cancelled BSP BetsWhilst BSP bets cannot be cancelled in general, in the scenario where a Limit Price applied to the BSP bet is updated this is modelled as a Cancellation of the original bet with the original Limit Price and a Place of a new bet with the new Limit Price. In this scenario, the cancellation of the original bet can be identified by looking at the "Cancelled Date" field ("cd") on the "Unmatched Orders" object ("uo") - N.B. there will be no "Size Cancelled" ("sc") because a BSP bet does not have any Size before reconciliation. Line MarketsLine markets being sent on the Market Stream can be identified by the bettingType field of MarketDefinition (with value of "LINE"). The MarketDefinition of Line markets provide some additional fields that will be null for all other types,
For updates for Orders on Line markets received on the Order Stream be aware of how the following properties behave,
Stream API Status - latencyEvery ChangeMessage, for order and market stream, contains a 'status' field which will give an indication on the health of the stream data provided by the service. This is feature will be used in addition to the heartbeat mechanism which only gives an indication that the service is up but doesn't provide an indication of the latency of the data provided. By default, when the stream data is up to date the value is set to null and will be set to 503 when the stream data is unreliable (i.e. not all bets and markets changes will be reflected on the stream) due to an increase in push latency. Clients shouldn't disconnect if status 503 is returned; when the stream recovers updates will be sent containing the latest data. The status is sent per each subscription on heartbeats and change messages. Example of message containing the status field:
Stream HealthIn addition to the Stream API status field we'd recommend the below as best practice for monitoring the health of the Stream API:
Lapse Status Reason Code Possible ValuesThis field will now be present in some cases on the Order object of the Order Stream to denote the reason that some or all of the order is lapsed. It will be null if no portion of the order is lapsed or if the order lapsed for some reason other than those listed below. The full list of currently supported values for this field is:
Offline DocumentationAn offline version of the Exchange Stream API is available via ExchangeStreamAPI-March2018.pdf Please note, the full Exchange Stream API specification is available online here Known Issues
|