The Option Chain price subscription, is a specialized bulk price subscription, made specifically to support implementation of a traditional options chain like this one (from SaxoTrader GO):
It will provide structural data for setting up the entire board for an instrument (such as all the expiries and all available strikes for the selected expiries) and stream prices and other price-data for the strikes in a "window" like the expanded expiry shown in the options board above. The options board subscription also enables the ability to move (scroll) the window within an expiry change the number of strikes in the window, as well as add or remove windows for other expiries.
The Options Board subscription supports the following asset types:
- FxVanillaOption
- StockOption
StockIndexOption
FuturesOption
- FxBinaryOption (short for a combination of FxNoTouchOption / FxOneTouchOption)
The special case of Binary Options
In the options board subscription, we have decided to include Fx Binary Options, even though they do not strictly fit into the same terminology as other options. This is the cause of a number of compromises in the contract, which we will try to address here.
For Binary Options, the sides are not called "Put" and "Call" but are instead "OneTouch" and "NoTouch" and to represent two the different option types. We keep using the term "Strike" across all types of options, even though it is really the "Barrier" for the one-touch and no-touch options - this naming enables the implementing application to keep the same parameters both when controlling the window, and while navigating the overall results.
The structure of an Options Chain
In general our options chain consists of a list of Expires, consisting of a list of Strikes, which again is made up from one or two Sides. The sides are where the price details for the individual options are updated, and so each of the sides can be considered a separate price subscription. While the overall structure of the returned data is the same for all option types, there are some differences, the major being that Fx Binary Options don't have sides called "Put" and "Call" but instead use "OneTouch" and "NoTouch" as their sides instead. Besides this, the difference is in what fields are available in the sides.
Since some options chains contain thousands of strikes, simply returning every update for every side in the entire chain would put an unacceptably high load on both the server and the client we have introduced a "window" which indicates a number of strikes that receives price updates. This window can be moved and expanded up to a total of 100 strikes, and can be used to represent either just a subset of s single expiry, or whatever can be fit on the screen at the same time, and ensures that neither client nor server drowns in the flood of price updates.
When starting a subscription, the snapshot contains basic information on all expiries, in order to provider the structurual overview of what can be selected or expanded. The expiry or expiries that are in the visible window, also contain basic information for all the strikes of that expiry, to enable setting up scrolling mechanics within the selected or expanded expiry itself. Those strikes that are part of the window also include their sides, with prices and market information, but only those.
The structure of an options board response
General Data
{ "AssetType": "FxVanillaOption", "Expiries": [...], "ExpiryCount": 10, "LastUpdated": "2017-01-20T14:28:08.695414Z" },
At the root of the options board response snapshot, we have the list of expiries, the number of expiries in the list and the timestamp.
Due to the differences in the the contract for the various supported asset types, the response contains the assetType, to help parse the structure.
Expiries
{ "DisplayDaysToExpiry": 26, "Expiry": "2017-02-15", "Index": 3, "MidStrikePrice": 1.06664, "StrikeCount": 10, "Strikes: [...] "StrikeWindowStartIndex": 5 },
An expiry consists of the necessary info to display the expiry (Expiry date and the number of days to expiry), the expiry index, used for referring to the expiry in subsequent calls, and in subscription updates. It also contains the mid strike price, and the total number of strikes and of course the list of strikes themselves.
The list of expiries contain an entry for every expiry that exists for the instrument, but an expiry only contains any strikes if it was specified as part of the "window" that shows option data. The "StrikeCount" is the number of strike elements in the list, so for basic expiry entries that have no strikes included, the count will be 0 although there are strikes for that expiry (if it is marked as part of the window).
If the expiry is part of a window, the StrikeWindowStartIndex will contain the index of the strike that contains the first part of the window.
Strikes
{ "Index": 1, "MidVolatilityPct": 0, "Strike": 1.055, "Call: "..., "Put": ... }
A strike consist of an Index and a Strike price, ans well as the mid volatility percentage for the strike price. If the strike is part of the window, it will also include a Put and/or a Call side (for ETOs and Fx Vanilla Options) or a OneTouch and/or NoTouch side. One of the sides can be null, as not all sides will be covered by options, but a Strike will always have at least one side.
Sides
{ "Ask": 0.01068, "Bid": 0.00963, "ContractId": 655804, "DeltaPct": 0.747953953807377, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }
The strike side contains the actual price information. For a given option type, both sides in the strikes will be identical, but the fields in a side, varies with the type of option.
Note that you will not receive quotable prices from the options chain price subscription, so for trading the options, it is recommended that the application starts a regular price subscription, when the user indicates that he wants to trade an option from the board.
Request and reply
Starting an options chain subscription, is much like starting a price subscription, and naturally adheres to the OpenApi subscription format. The simplest request only specifies the Identifier (it is not a uic, since ETO chains are started based on their option root id) and the AssetType.
The request is sent as a POST request to the URL /trade/v1/optionschain/subscriptions/active.
{ "Arguments": { Identifier: 21, AssetType: "FxVanillaOption" }, "ContextId": "Context1234", "ReferenceId": "options1", "RefreshRate": 5000 }
It is also possible to specify AccountKey & Amount to get more "targeted" prices. In order to control the size and position of the window, it is possible to specify the amount of strikes per expiry (in MaxStrikesPerExpiry) and set expiriy and strike using the Expiries collection:
{ "Expiries":[ {"Index":4, "StrikeStartIndex": 6 }, { "Index":5 } ], "MaxStrikesPerExpiry":12 }
By adding a given expiry (specified by its Index) to the collection, you indicate that you want a window of the specified size from that expiry - without specifying a strike start index, the window is centered arout the "At The Money" price. If you specify a strike start index, the window will start at that strike index, and have the specified size.
It is possible to add as many expiries you want to the list, but if the total number of strikes (#expiries * maxStrikesPerExpiry) exceeds the fixed limit of 100 strikes, the request will fail.
The minimum refreshrate for an OptionsChain subscription is 2000ms.
The response could look like this:
{ "ContextId": "explorer_201700201526428911", "InactivityTimeout": 60, "ReferenceId": "options1", "RefreshRate": 5000, "Snapshot": { "AssetType": "FxVanillaOption", "Expiries": [ { "DisplayDaysToExpiry": 5, "Expiry": "2017-01-25", "Index": 0, "MidStrikePrice": 1.06664, "StrikeCount": 7, "Strikes": [ { "Index": 0, "MidVolatilityPct": 0, "Strike": 1.05 }, { "Index": 1, "MidVolatilityPct": 0, "Strike": 1.055 }, { "Index": 2, "MidVolatilityPct": 0, "Strike": 1.06 }, { "Call": { "Ask": 0.00641, "Bid": 0.00539, "ContractId": 655781, "DeltaPct": 0.56752330586319, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 3, "MidVolatilityPct": 0.0996729120279811, "Put": { "Ask": 0.00463, "Bid": 0.00364, "ContractId": 655801, "DeltaPct": 0.432507945103353, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.065 }, { "Call": { "Ask": 0.004, "Bid": 0.00303, "ContractId": 655782, "DeltaPct": 0.398679062460635, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 4, "MidVolatilityPct": 0.0993014698445026, "Put": { "Ask": 0.00725, "Bid": 0.00624, "ContractId": 655802, "DeltaPct": 0.601352189404683, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.07 }, { "Call": { "Ask": 0.00239, "Bid": 0.00144, "ContractId": 655784, "DeltaPct": 0.252077300002249, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 5, "MidVolatilityPct": 0.0997059621748361, "Put": { "Ask": 0.01068, "Bid": 0.00963, "ContractId": 655804, "DeltaPct": 0.747953953807377, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.075 }, { "Index": 6, "MidVolatilityPct": 0, "Strike": 1.08 } ], "StrikeWindowStartIndex": 3 }, { "DisplayDaysToExpiry": 12, "Expiry": "2017-02-01", "Index": 1, "MidStrikePrice": 1.06664, "StrikeCount": 9, "Strikes": [ { "Index": 0, "MidVolatilityPct": 0, "Strike": 1.045 }, { "Index": 1, "MidVolatilityPct": 0, "Strike": 1.05 }, { "Index": 2, "MidVolatilityPct": 0, "Strike": 1.055 }, { "Index": 3, "MidVolatilityPct": 0, "Strike": 1.06 }, { "Call": { "Ask": 0.00852, "Bid": 0.00758, "ContractId": 659275, "DeltaPct": 0.566701939490511, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 4, "MidVolatilityPct": 0.0902147591440464, "Put": { "Ask": 0.00643, "Bid": 0.00552, "ContractId": 659281, "DeltaPct": 0.433402238310163, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.065 }, { "Call": { "Ask": 0.00601, "Bid": 0.0051, "ContractId": 655783, "DeltaPct": 0.442143349483909, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 5, "MidVolatilityPct": 0.0894923049104342, "Put": { "Ask": 0.00895, "Bid": 0.00802, "ContractId": 655803, "DeltaPct": 0.557960828608985, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.07 }, { "Call": { "Ask": 0.00411, "Bid": 0.00324, "ContractId": 659276, "DeltaPct": 0.325351443155218, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 6, "MidVolatilityPct": 0.0893763199353124, "Put": { "Ask": 0.01207, "Bid": 0.01113, "ContractId": 659282, "DeltaPct": 0.674752735149749, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.075 }, { "Index": 7, "MidVolatilityPct": 0, "Strike": 1.08 }, { "Index": 8, "MidVolatilityPct": 0, "Strike": 1.085 } ], "StrikeWindowStartIndex": 4 }, { "DisplayDaysToExpiry": 19, "Expiry": "2017-02-08", "Index": 2, "MidStrikePrice": 1.06664, "StrikeCount": 12, "Strikes": [ { "Index": 0, "MidVolatilityPct": 0, "Strike": 1.04 }, { "Index": 1, "MidVolatilityPct": 0, "Strike": 1.045 }, { "Index": 2, "MidVolatilityPct": 0, "Strike": 1.05 }, { "Index": 3, "MidVolatilityPct": 0, "Strike": 1.055 }, { "Index": 4, "MidVolatilityPct": 0, "Strike": 1.06 }, { "Call": { "Ask": 0.01101, "Bid": 0.01013, "ContractId": 660806, "DeltaPct": 0.568757684015471, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 5, "MidVolatilityPct": 0.0959477411830374, "Put": { "Ask": 0.00858, "Bid": 0.00772, "ContractId": 660818, "DeltaPct": 0.43142347060109, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.065 }, { "Call": { "Ask": 0.00844, "Bid": 0.00758, "ContractId": 660807, "DeltaPct": 0.474451707796629, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 6, "MidVolatilityPct": 0.0949765581424806, "Put": { "Ask": 0.01102, "Bid": 0.01015, "ContractId": 660819, "DeltaPct": 0.525729446985948, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.07 }, { "Call": { "Ask": 0.00633, "Bid": 0.0055, "ContractId": 660808, "DeltaPct": 0.381450655725193, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Index": 7, "MidVolatilityPct": 0.0944574526250485, "Put": { "Ask": 0.01392, "Bid": 0.01305, "ContractId": 660820, "DeltaPct": 0.618730499209608, "Net": 0, "PriceTypeAsk": "Indicative", "PriceTypeBid": "Indicative" }, "Strike": 1.075 }, { "Index": 8, "MidVolatilityPct": 0, "Strike": 1.08 }, { "Index": 9, "MidVolatilityPct": 0, "Strike": 1.085 }, { "Index": 10, "MidVolatilityPct": 0, "Strike": 1.09 }, { "Index": 11, "MidVolatilityPct": 0, "Strike": 1.095 } ], "StrikeWindowStartIndex": 5 }, { "DisplayDaysToExpiry": 26, "Expiry": "2017-02-15", "Index": 3, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 40, "Expiry": "2017-03-01", "Index": 4, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 54, "Expiry": "2017-03-15", "Index": 5, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 68, "Expiry": "2017-03-29", "Index": 6, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 89, "Expiry": "2017-04-19", "Index": 7, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 96, "Expiry": "2017-04-26", "Index": 8, "MidStrikePrice": 1.06664, "StrikeCount": 0 }, { "DisplayDaysToExpiry": 110, "Expiry": "2017-05-10", "Index": 9, "MidStrikePrice": 1.06664, "StrikeCount": 0 } ], "ExpiryCount": 10, "LastUpdated": "2017-01-20T14:28:08.695414Z" }, "State": "Active" }
Moving or resizing the window
The window is moved or resized by sending a PATCH request to the trade/v1/optionschain/subscriptions/active/<contextid>/<referenceid> url. The request can only contain MaxStrikesPerIndex and/or list of Expiries:
{ "Expiries":[ {"Index":0 }, { "Index":2, "StrikeStartIndex": 11 } ], "MaxStrikesPerExpiry":17 }
Moving the window will start pushing updates for the new section specified, and will update the old sections with null for the sides, as these are no longer part of the window.
Reset At The Money
It is also possible to reset all windows to around their "At the money" price, by sending a PUT request to the url trade/v1/subscriptions/<contextId>/<referenceId>/ResetATM. This will not change the expiries, but all windows within the previously set expiries, will be centered aroud the "At the money" price for the expiry, just as if their StrikeStartIndex had been changed using a PATCH request as decribed above.
Fields included in the "sides" for various types of options
StockOption StockIndexOption FuturesOption | Fx Vanilla Option | FxBinaryOption | |
---|---|---|---|
Put / Call | Put / Call | OneTouch / NoTouch | |
Uic | x | x | x |
Bid | x | x | x |
Ask | x | x | x |
PriceTypeBid | x | x | x |
PriceTypeAsk | x | x | x |
DeltaPct | x | x | |
Net | x | x | |
ContractId | x | x | |
High | x | ||
Low | x | ||
Open | x | ||
Close | x | ||
LastClose | x | ||
NetChange | x | ||
LastTraded | x | ||
BidSize | x | ||
AskSize | x | ||
Volume | x | ||
OpenInterest | x | ||
Greeks | x - If the exchange provides it |
See also the live sample on the options chain (with source).