Schema Definition v3.0
Change log
Several important innovations have been introduced to this version. In no particular order, these include:
- A new, optional
layout
section to capture presentation ordering of elements: Layout - Ability to flexibly embed field tables and examples within message presentations using custom HTML tags
- Changes to examples array, making them global and differentiating raw versus illustrative examples.
- Ablity to control the positioning of fields and examples within HTML descriptive sections.
- A new, optional
transforms
section to capture expected logic for message transformations by the receiving application: Transforms. - Change to
createdByText
andupdatedAt
in Notesto ensure consistent camel-case naming convention. - Addition of JavaScript as permitted expression language (in addtion to Groovy), with corresponding changes to various condition blocks.
Format
The files describing the APIs per the FinSpec specification are represented as JSON objects and conform to the JSON standards.
All identifiers in the specification are case sensitive.
The schema exposes two types of fields. Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name. Patterned fields can have multiple occurrences as long as each has a unique name.
Note On Descriptive Text [New in 3.0]
The FinSpec project aims to accommodate the need for both machine-readable and human-readable API documentation. This requires a careful balance between highly-structured, machine-readable elements, and more loosely-structured descriptive elements designed for humans (typically HTML descriptions).
In particular, machines will require fast, look-up access to structured elements such as field arrays, whereas human authors like to surround field lists with explanatory, descriptive text.
To accommodate this, FinSpec 3.0 defines additional custom HTML tags which to be carried in selected HTML description fields, allowing fine-grained control over how field lists and examples are positioned within other descriptive elements.
Custom HTML Tag | Description | Available In |
---|---|---|
<finspec-fields /> |
An instruction to insert a table representing the list of fields (described in the same Fieldset) as a block-level HTML div at that point. | Fieldset, FieldsetWithContext |
<finspec-example data-ref="example_key" /> |
An instruction to insert the (globally-defined) example object with the indicated key as a block-level HTML div at that point. | Datatype, InfoSection, Fieldset, FieldsetWithContext |
The use of these custom HTML tags is optional. HTML description sections which do not contain these elements should be intepreted as an instruction to insert and relevant field table and examples directly after the relevant HTML description.
File Structure
The FinSpec representation of the API is made of a single file.
By convention, the API file has .json
extension.
Vendor Extensions
While the FinSpec Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
The extensions properties are always prefixed by "x-"
and can have any valid JSON format value.
Objects
Root document
This is the root document object for the API specification.
Fixed Fields
Field Name | Type | Description |
---|---|---|
finspec | string |
Required Specifies the FinSpec Specification version being used. The value MUST be "3.0". |
info | Info | Required Provides metadata about the specification. The metadata can be used by the clients if needed. |
protocol | Protocol | Required Metadata describing the protocol. |
changes | Changes | Optional A description of the changes made in this version of the API specification. |
datatypes | Datatype | Required A list of datatypes used in the API specification. |
nav | Nav | Required A proposed UI navigation structure for the API specification. |
layout | Layout | Optional [Added in 3.0] A layout object to control the logical presentation of messages in a printed or displayed document. |
blocks | Blocks | Required if supported by protocol A list of common blocks used by the messages in the API specification. e.g. Header, footer, etc. |
messages | Messages | Required A list of messages used in the API specification. |
examples | Examples | Optional A keyed list of message examples. |
notes | Notes | Optional An list of notes about the specification as a whole. |
workflows | Workflows | Optional A list of finite state machine style workflow |
transforms | Transforms | Optional A list of message-level transformations to be performed by the receiving application |
The Root object may contain vendor extensions.
Info
{
"version": "11.5",
"issueDate": "2015-08-26",
"liveDate": "2015-08-26",
"issuer": "FixSpec Ltd.",
"title": "FixSpec Example FIX Specification",
"status": "FINAL",
"logo": "https://fixspec.com/images/fixspec.jpg",
"contacts": [...]
}
The object provides metadata about the API specification.
Field Name | Type | Description |
---|---|---|
version | string |
Required A semantic version number of the API. |
issuer | string |
Required The name of the API issuer. |
issueDate | string |
Required The issue date of the API description expressed in YYYY-MM-DD format. |
liveDate | string |
Optional The anticipated production-live date of the API description expressed in YYYY-MM-DD format. |
title | string |
Required The title of the API service. |
logo | string |
Optional A fully-qualified URL to a suitable logo image for the spec author. |
contacts | Contacts | Optional A List of contact details for the owners of the API. |
status | string |
Optional A description of the current state of this specification (eg DRAFT or FINAL). |
The Info object may contain vendor extensions.
Contacts
{
"contacts": [
{
"name": "Customer Services",
"email": "happytohelp@fixspec.com",
"url": "https://fixspec.com"
},
...
]
}
An array of contact information for the specification. Each specification must contain at least one piece of contact information.
NOTE: At least one of phone
, url
or email
must be provided.
The Contact object may contain vendor extensions.
Protocol
{
"protocol": {
"name" : "FIX",
"description": "FIX Protocol",
"isFIX": true,
"isOffsetBased": false,
"isTagValue": true,
"isBinary": false,
"isObject": false,
"charset": "UTF8",
"hasHeader": true,
"hasFooter": true
}
}
The object provides metadata about the protocol.
NOTE: At least one of the following protocol attributes must be present: isFIX
, isOffsetBased
, isTagValue
and isObject
.
The Protocol object may contain vendor extensions.
Changes
{
"changes": {
"summary": "<p>These are my changes since the last known version</p>",
"lastVersion": "11.2",
"lastVersionDate": "2001-01-01",
"history": [
{
"version": "11.1",
"issueDate": "2016-10-08",
"liveDate": "2016-10-08",
"summary": "This is my summary of changes in the 11.1 version."
},
...
]
}
}
An optional block describing changes in this, and prior, spec versions.
Field Name | Type | Description |
---|---|---|
summary | string |
Required A HTML or text description of the changes made. |
lastVersion | string |
See note below The version number of the immediately prior spec version (i.e. the starting spec to which changes have been applied). |
lastVersionDate | string |
See note below The date of the immediately prior spec version (i.e. the starting spec to which changes have been applied) in YYYY-MM-DD format. |
history | History | Optional A historical list of prior changes. |
NOTE: At least one of lastVersion
and lastVersionDate
must be present.
The Changes object may contain vendor extensions.
History
{
"version": "11.1",
"issueDate": "2016-10-08",
"liveDate": "2016-10-08",
"summary": "This is my summary of changes in the 11.1 version."
}
An optional block describing changes in this, and prior, spec versions.
The History object may contain vendor extensions.
Datatype
{
"datatypes:": [
{
"name": "Price",
"baseType": "integer",
"length": 8,
"precision": 8,
"description": "Eight byte integer field with eight implied decimal places."
},
{
"name": "Qty",
"baseType": "number",
"description": "Float field capable of storing either a whole number (no decimal places) of 'shares' (securities denominated in whole units) or a decimal value containing decimal places for non-share quantity asset classes (securities denominated in fractional units)."
},
{
"name": "MultipleStringValue",
"baseType": "string",
"description": "String field containing one or more space delimited multiple character values (e.g. |277=AV AN A| )."
},
{
"name": "UInt32E",
"baseType": "integer",
"length": 4,
"isUnsigned": true,
"description": "Little-Endian encoded 32 bit unsigned integer."
},
...
]
}
Describes the type of data stored in the field value of the API.
Field Name | Type | Description |
---|---|---|
name | string |
Required Name of the type. e.g. int, uint8e, Price, Boolean, etc. |
baseType | string |
Required Specifies the base type of the value. Value MUST be from the list: "char" , "integer" , "number" , "string" , "ascii" , "uint8" , "int8" , "uint16" , "int16" , "uint32" , "int32" , "uint64" , "int64" , "float" , "double" |
description | string |
Required Description/remark for this type. |
length | integer |
Optional Length of value for this type in number of bytes (binary) or characters (text). |
precision | integer |
Optional Implied number of decimal places for floating numbers represented as integers. |
isUnsigned | boolean |
Optional Whether numerical value is unsigned or not. Default: false |
isBitField | boolean |
Optional Whether type represents a bit field. Default: false |
pattern | string |
Optional Regular expression to describe the pattern of the value for this datatype. |
padChar | string |
Optional Character used for padding. |
padSide | string |
Optional Whether field value should be padded to left or right. Value MUST be from the list: "left" and "right" . |
examples | array |
Optional Array of keys referring to entries in the global examplesObject which describe this datatype. |
The Datatype object may contain vendor extensions.
Navigation
{
"nav": {
"info": {
"General": {
"items": [
{
"key": "info_item_unique_key",
"name": "Information section header"
},
...
]
},
...
},
"technical": {
"Session": {
"items": [...]
},
...
"Order Entry": {
"items": [...]
},
...
},
"block": {
"Core": {
"items": [...]
},
...
}
}
}
The navigation object allows the capture of intended UI navigation for a specification; how the author intended messages and information sections to be logically grouped for display. Think of it as the electronic equivalent of a Table Of Contents.
The top-level nav
object may have up to four sections (but a minimum of one), relating to various content types: info
, blocks
, technical
and functional
.
Each of these sections may have as many sub-menus as required, with each sub-menu represented as a keyed JSON fragment. In the example here, "Session" and "Order Entry" are considered sub-menus of the technical
type.
At the end nodes of this hierarchy should be a NavItemsArray (items
) array, which is a simple array containing references to the relevant information section, block or fieldset. The definition of the end-node NavItems contains the unique key
for the detail to be displayed, the same unique key used for keying the section or fieldset in the relevant JSON section allowing the navigation and detail to be linked together.
Both the (top-level) Navigation object and the (lowest-level) NavItemsArray objects may contain vendor extensions.
Layout [New in 3.0]
{
"layout": [
{
"prepend": "<h1>Section Header</h1><p>This is some introductory text for this section that should appear before all pages.</p>",
"append": "<p>This text will appear after all pages.</p>",
"orientation": "landscape",
"pages": [
{
"prepend": "<h1>Page Header</h1><p>This text will appear before all messages.</p>",
"append": "<p>This text will appear after all messages.</p>",
"messages": [
{
"type": "info",
"key": "info_item_unique_key"
},
{
"type": "technical",
"key": "technical_message_key"
},
...
]
},
...
]
},
...
]
}
The layout object is designed to capture the intended layout of messages when presented either in print format (eg PDF) or as single-page documentation online.
The top-level layout
array contains one or more "section" objects, each representing a distinct segment of a document. And each "section" object can indicate a series of pages which - in turn - links to one or more messages described elsewhere in the FinSpec. Much the same as in Word, section objects can indicate an orientation of either portrait or landscape to control the presentation. Pages can point to one or more messages within should be understood to have an implicit page break when output to Word or PDF.
At both the section and page level, it is possible to include prepend
and append
HTML sections to add additional information that is perhaps not directly relevant for messages.
####Section
Field Name | Type | Description |
---|---|---|
prepend | string |
Optional HTML content to be output before any pages in this section. |
append | string |
Optional HTML content to be output after all pages in this section. |
orientation | string |
Optional The page orientation used for Word/PDF. Valid values as portrait and landscape . Default is portrait . |
pages | PageArray | Optional An array of pages contained in this section. Each page ends with an implicit page break. |
PageArray
Field Name | Type | Description |
---|---|---|
prepend | string |
Optional HTML content to be output before any messages on this page. |
append | string |
Optional HTML content to be output after all messages on this page. |
messages | PageMessageArray | Optional An array of references to messages which should appear on this page. |
PageMessageArray
The layout
, section
and pageArray
objects may contain vendor extensions, but entries in the pageMessageArray
should not contain extensions.
Blocks
{
"blocks": {
"block_1": {
"name": "Standard FIX Header",
"description": "The standard FIX message header",
"historyKey": "block_1_hist",
"isHeader": true,
"isTrailer": false,
"fields": [...]
},
"block_2": {
"name": "Standard FIX Trailer",
"description": "The standard FIX message trailer",
"historyKey": "block_2_hist",
"isHeader": false,
"isTrailer": true,
"fields": [...]
},
"block_3": {
"name": "Instrument",
"description": "Re-used instrument identifier block",
"historyKey": "block_3_hist",
"isHeader": false,
"isTrailer": false,
"fields": [...]
},
...
}
}
A list of re-useable blocks (or components) used in the messages in the API specification. From FinSpec Schema v2.0, this is a keyed JSON fragment, with each block's key being a unique reference to that block for reference in other fieldsets. While we recommend using random keys here, your implementation may allow other keys such as slugged names. Each block (eg block_1
in the example here) represents a FieldSet.
IMPORTANT It is NOT assumed that these JSON keys are maintained across specification versions; for example, if you choose to set the key equal to a slugged name then this key will "break" should you ever change the block name. For this reason, the historyKey
attribute is used to maintain a consistent identifier across specification versions. It is historyKey
and not JSON key that should, therefore, be used in comparison logic.
The Blocks object may not contain vendor extensions.
Messages
{
"messages": {
"info": {
"info_1" : {
"name": "Symbology",
"description": "This is some text description of symbology demanded by the recipient.",
"historyKey": "info_1_hist"
},
...
},
"technical": {
"technical_1": {
"name": "Logon",
"wireId": "A",
"description": "The Logon message authenticates a user establishing a connection to a remote system.",
"fields": [...],
"isSession": true,
"direction": "both",
"historyKey": "technical_1_hist"
},
...
},
"functional": {
"functional_1": {
"name": "VWAP Order",
"wireId": "D",
"description": "The new order message type targeting the VWAP algorithmic strategy.",
"fields": [...],
"historyKey": "functional_1_hist",
"baseKey": "technical_3",
"context": {...},
"examples": [...]
},
...
}
}
}
A list of all messages used in the API specification.
The section can be used to carry up to three types of message - info
sections, technical
messages, and functional
views, where a functional view is a technical message within a specific business context.
Field Name | Type | Description |
---|---|---|
info | InfoSection | See note below Series of free-text, descriptive sections which do not directly relate to messaging e.g. Symbology, Market Phases etc. |
technical | Fieldset | See note below List of session and application-level e.g. Logon, Heartbeat, etc. |
functional | FieldsetWithContext | Optional List of functional messages, describing technical messages within a given context. |
NOTE To pass validation, a specification must contain either the info
or technical
sections (or both).
For those upgrading from 1.x schema versions, note that the session
and application
blocks have now been removed in favour of a single technical
block, combined with a new isSession
attribute at the individual message level. Note also that the JSON messages lists within a given block are keyed JSON fragments, as opposed to simple arrays under 1.x.
The Messages object may contain vendor extensions.
Info Section
{
"name": "Symbology",
"description": "<p>The symbology used on our venue is ...",
"historyKey": "unique_history_key"
}
An informational section used to convey specification data unrelated to messages. Example usage may include descriptions of symbology, connectivity approach or hours of operation.
The InfoSection object may contain vendor extensions.
Fieldset
{
"name": "NewOrderSingle",
"wireId": "D",
"direction": "in",
"description": "...",
"fields": [...],
"historyKey": "unique_history_key",
"isSession": false,
"examples": [...]
}
A list of attributes collectively used to describe a fieldset (either a re-used block or a technical message) in the specification.
Field Name | Type | Description |
---|---|---|
name | string |
Required Name of the message. |
wireId | string or integer |
Required (except blocks) Wire identifier for the message (eg A for Logon in FIX). |
description | string |
Required HMTL or plain text description of the purpose and use of the message. |
direction | string |
Optional Indication of message flow. Value MUST be from the list: "in" , "out" , and "both" . Default: both . |
historyKey | string |
Optional Unique, persistent key suitable for linking a fieldset across versions. |
isSession | boolean |
Optional Boolean to indicate whether this fieldset relates to session-level connectivity. Default is false . |
isHeader | boolean |
Optional Boolean to indicate whether this fieldset represents a common header block. Default is false . |
isTrailer | boolean |
Optional Boolean to indicate whether this fieldset represents a common trailer block. Default is false . |
fields | Field | Required List of fields available within a message. |
examples | array |
Optional Array of keys referring to entries in the global examplesObject which illustrate this Fieldset. Note that by placing entries here, the author is indicating that exaples should be displayed as a list at the end of the message as opposed to embedded within the description. |
notes | Notes | Optional An list of notes about this fieldset. |
The Fieldset object may contain vendor extensions.
FieldsetWithContext
{
"name": "NewMarketOrder",
"wireId": "D",
"direction": "in",
"description": "...",
"context": {
"lang": "groovy",
"expression": "$40 == '1'",
"description": "OrdType (40) equals 1 (Market)"
},
"isSession": false,
"fields": [...],
"baseKey": "technical_key_1",
"historyKey": "unique_history_key",
"examples": [...]
}
A functional view describes a message within a particular business context. Common use cases for functional views include:
- Views differentiating state (eg Order Acknowledgement vs Execution)
- Views differentiating order types (eg Limit Order vs VWAP)
- Views differentiating asset class (eg Spot FX Order vs FX Forward Order)
Field Name | Type | Description |
---|---|---|
name | string |
Required Name of the message. |
wireId | string or integer |
Required Wire identifier for the message (eg A for Logon in FIX). |
description | string |
Required HMTL or plain text description of the purpose and use of the message. |
direction | string |
Optional Indication of message flow. Value MUST be from the list: "in" , "out" , and "both" . Default: both . |
isSession | boolean |
Optional Indication of whether the message is related to establishing, maintaining or terminating a session connection. |
baseKey | string |
Optional The unique key given to the technical message upon which this functional view is based. |
historyKey | string |
Optional Unique, persistent key suitable for linking a fieldset across versions. |
context | Context | Required Digital description of the intended message context. |
fields | Field | Required List of fields available within a message. |
examples | array |
Optional Array of keys referring to entries in the global examplesObject which illustrate this Fieldset. Note that by placing entries here, the author is indicating that exaples should be displayed as a list at the end of the message as opposed to embedded within the description. |
notes | Notes | Optional An list of notes about this message. |
The FieldsetWithContext object may contain vendor extensions.
Context
{
"lang": "groovy",
"expression": "$40 == '1'",
"description": "OrdType (40) equals 1 (Market)"
}
Used to provide a digital description of the context for a functional (context-specific) message.
The Context object may contain vendor extensions.
Field
{
"fields": [
{
"position": 0,
"name": "Header",
"description": "Standard FIX header",
"blockKey": "header_block_key",
},
{
"position": 1,
"name": "ClearingAccount",
"description": "Clearing Account Type",
"datatype": "uint8",
"length": 1,
"values": [
{
"wireValue": 1,
"description": "Client"
},
{
"wireValue": 3,
"description": "House"
}
]
},
{
"position": 2,
"name": "Price",
"alwaysRequired": false,
"conditions": [...],
"description": "Price per share",
"wireId": "44",
"datatype": "Price"
},
...
]
}
{
"fields": [
...,
{
"offset": 12,
"name": "OrderInst",
"description": "Order instructions bit field",
"datatype": "uint8",
"bits": [
{
"offset": 0,
"width": 1,
"name": "LocateReqd",
"values": [
{
"wireValue": 0,
"description": "No Locate required"
},
{
"wireValue": 1,
"description": "Locate required"
}
]
},
...
]
},
...
]
}
An array of fields to be present in a given fieldset (message or block).
Each field entry takes one of two forms:
- A reference to a block defined elsewhere using the
blockKey
reference, or - An individual field defined in the fieldset.
IMPORTANT Re-used header and trailer blocks MUST be explicitly referenced within fields
arrays just like any other block. There is no "assumption" of their presence based on protocol. (This requirement allows FinSpec to support the definition of multiple header/trailer blocks, with flexibility for authors to indicate the correct choice for a given fieldset).
Field Name | Type | Description |
---|---|---|
offset | integer |
Required for offset-based protocols Zero-based offset of the field within the message for binary APIs. |
position | integer |
Optional Zero-based position of the field within the message for text/tag-value APIs. Where absent, ordering should be assumed from positioning within the JSON. |
key | string |
Optional Unique field identifier. In case the same wire_id appears multiple times in the same message. |
wireId | string |
Required for tag-value protocols Wire identifier for the field (eg tag 35 in FIX). |
blockKey | string |
Required for blocks The unique reference for the block from the blocks section. |
description | string |
Optional Description of the purpose and use of the field. |
name | string |
Required Name of the field. |
datatype | Datatype | Required Field datatype from the list of API datatypes. |
minValue | number |
Optional Minimum permitted field value for numeric types. Default: zero. |
maxValue | number |
optional Maximum permitted field value for numeric types. Default: unlimited |
exclusiveMinValue | boolean |
Optional Whether 'minValue' value is exclusive or not. |
exclusiveMaxValue | boolean |
optional Whether 'maxValue' value is exclusive or not. |
minLength | integer |
Optional Minimum permitted length of value for string types. |
maxLength | integer |
Optional Maximum permitted length of value for string types. |
length | integer |
Optional Field value length in number of bytes (binary) or characters (text). |
values | EnumArray | Optional List of possible values if the field is enumerated. |
pattern | string |
Optional Regular expression to describe the pattern of the value for this field. |
alwaysRequired | boolean |
Optional Boolean flag to indicate that this field is present in 100% of cases. Default for tag-value protocols: false |
conditions | ConditionArray | Optional Field conditional requirements. |
fields | Field | Optional List of nested fields, indicating a repeating group under the current field. |
bits | BitArray | Optional Details about how bits are organized if this is a bit field. |
notes | Notes | Optional An list of notes about this particular field. |
The Field object may contain vendor extensions.
Enum Array
{
"values": [
{
"wireValue": 1,
"name": "Client",
"description": "This is a long description",
"isDefault": true
},
...
]
}
A simple array of permitted enumerations for this field / bit field.
The EnumArray object may contain vendor extensions.
BitsArray
{
"bits": [
{
"offset": 0,
"width": 1,
"name": "LocateReqd",
"values": [
{
"wireValue": 0,
"description": "No Locate required"
},
...
]
},
...
]
}
A simple array of bits within a field.
NOTE Where observed, the "parent" field is expected to have a datatype with an isBitfield
value of true. If this is not the case, then the bits
array should be ignored, and the parent should be treated as a non-bitfield field.
Field Name | Type | Description |
---|---|---|
offset | integer |
Required Bit offset within a bit field indicating start of bits group. |
width | integer |
Required Width of bits group in terms of number of bits. |
name | string |
Required Name of the bits group. |
description | string |
Optional Description of the purpose and use of the bits group. |
values | EnumArray | Optional List of possible values for this bits group. |
The BitsArray object may contain vendor extensions.
ConditionArray
{
"conditions": [
{
"label": "PriceOnLimitOrder",
"lang": "groovy",
"expression": "($40 == 2)",
"isReqd": true,
"isAbsent": false
},
{
"label": "NoPriceOnMarketOrder",
"lang": "groovy",
"expression": "($40 == 1)",
"isReqd": false,
"isAbsent": true
},
...
]
}
A simple array of conditions, each of which should be evaluated in turn and the loop exited when the first evaluates to true. See below for a description of condition grammar.
NOTE For conditions to be examined, alwaysRequired
should be set to false
on the parent field, to avoid the parent field always being considered mandatory.
Field Name | Type | Description |
---|---|---|
label | string |
Required Name of the condition rule. |
lang | string |
Optional Language used in expression field. Options are grooy or javascript . Default: groovy . |
expression | string |
Required Condition expression. This block will only take effect if this expression evaluates to true. |
isReqd | boolean |
Required Field is mandatory in such condition. |
isAbsent | boolean |
Required Field should not be present in such condition. |
values | EnumArray | Optional List of (restricted) set of valid values if the expression evaluates to true. |
The Condition object may contain vendor extensions.
Condition Expression Grammar
Field 40 must equal a value of 2
($40 == 2)
Field 40 may equal 3 or 4
($40 == 3) || ($40 == 4)
Field 40 must have a value of 2, and field 44 must be greater than zero
($40 == 2) && ($44 > 0)
Field 44 must be present
$44
Field 44 must NOT be present
!$44
($2_OrderQty > 100)
In simple terms, it's a conditional expression used in if statements which evaluate to true or false.
For tag values based APIs, the value of the tag is expressed as: $<wireId>
e.g. $40
For others e.g. native APIs, the value of a field is expressed as: $<position>_<name>
e.g. $2_Price
Tokens that can be used in condition expression are:
- Comparison operators e.g. ==, >, etc.
- Logical operators e.g. &&, ||, etc.
- Brackets
- Use of ! to indicate 'not'
- In the case of
groovy
, the comparison operator of ==~ may be used to indicate a regular expression.
ExamplesObject [Revised in 3.0]
{
"examples": {
"example_1": {
"name": "Market order example",
"raw": "8=FIX.4.2|9=69|35=A|34=12|49=SENDER|52=20140228-05:42:38.026|56=TARGET|98=0|108=120|10=238|",
"example": "8=FIX.4.2|9=69|5=A|34=12|49=SENDER|52=20140228-05:42:38.026|56=TARGET|98=0|108=120|10=238|",
"description": "Market order example"
},
...
}
}
A keyed array of examples of various types. This object is placed in the root of the FinSpec document and referred to from within Fieldset objects using the unique key associate with each example. This structure allows examples to be conveniently re-used or shared between different Fieldsets.
Each (sub-)object within the examplesObject may contain vendor extensions, but the top-level examplesObject may not.
NotesArray
{
"notes": [
{
"note": "One really interesting fact about this field is...",
"createdByText": "Joe Bloggs",
"updatedAt": "2019-02-25 14:07:07"
},
...
]
}
A simple array of noted associated with a document/fieldset/field (depending on where the array appears).
The NotesArray object may contain vendor extensions.
Transforms [NEW in FinSpec 3.0]
{
"transforms": [
{
"scope": {...},
"actions": [
...
]
},
...
]
}
The transforms array provides a list of agreed transformation actions
to be performed by the receiving application.
IMPORTANT: It is assumed that order in which the transformations are applied will strictly match the order of their appearance within the transforms
array. Further, it is assumed that the transformation will apply to all tag(s) present which match the indicated scope. For example, an instruction to drop field 555 should be interpreted as an instruction to drop all such fields should they appear in multiple places.
Each Transform object is defined as follows:
Field Name | Type | Description |
---|---|---|
scope | Scope | Optional (but recommended!) Used to filter the scope of the transform to messages which match the scope. Absence of scope implies the actions should be performed on all messages (both inbound and outbound). |
actions | Actions | Required Used to describe the action(s) to be performed on messages which match the scope . |
Each Transform object may contain vendor extensions.
Transform Scope
{
"scope": {
"type": "block",
"key": "sg563fgd",
"direction": "in",
"lang": "groovy",
"condition": "$55 && $55 != 'VOD'"
}
}
The Scope object filters the set of messages down to those that should have the transformation action applied to them. A given message must satisfy all of the indicated conditions in order for it to be considered in-scope.
The object is defined as follows:
Field Name | Type | Description |
---|---|---|
type | string |
Optional (but recommended!) Used to identify the type of messages on which to perform the action. Options are block , technical or functional . |
key | string |
Required if type presentThe relevant unique key for the block / message targetted by this transformation. |
direction | string |
Optional The direction of the message. Options are in , out and both . |
lang | string |
Optional Language used for the condition field. Options are groovy or javascript . Default: groovy . |
condition | string |
Optional An expression evaluating to a boolean, where tag numbers are prefixed with the '$' sign. |
The Scope object may contain vendor extensions.
Transform Actions
{
"actions": [
{
"type": "drop",
"tag": "612"
},
{
"type": "store",
"lang": "groovy",
"uid": "$49+'-'+$11",
"expression": "$UID = $2000",
},
{
"type": "expression",
"lang": "groovy",
"expression": "$923 = $89.split(':')[0]"
},
{
"type": "plugin",
"expression": "$923 = plugin.yourCommand($923)"
}
...
]
}
The Action object indicates the set of transformation actions that should be performed in order on scoped messages.
To permit maximum flexibility, FinSpec defines only four "core" action types, while allowing the full power of JavaScript and Groovy scripting languages to accomodate a wide range of use cases:
Action Type | Description |
---|---|
drop |
An instruction to drop one or more field(s) referred to in the tag attribute. |
store |
An instruction to store (or restore) a value to disk for later use, under an index indicated by $UID . This is typically used to temporarily remove values from inbound messages and echo them on responses. |
expression |
Manipulate (or set) a tag equal to an evaluated expression. |
plugin |
Manipulate (or set) a tag equal to a value returned from a third-party plugin. |
Each action object has the following attributes:
Field Name | Type | Description |
---|---|---|
type | string |
Required Identifies the type of action to be performed. Options are drop , store , expression or plugin . |
tag | string |
Required (drop only)The tag to be dropped for drop types. Ignored for any other type . |
uid | string |
Required (store only)An expression to generate a unique index for the sotrage of The tag to be dropped for drop types. Ignored for any other type . |
lang | string |
Optional Language used in an expression type action. Options are groovy (default) and javascript . |
expression | string |
Required (store , expression , plugin only)An expression to manipulate a field in a message, set or retrieve a $UID from storage, or to a call to an external plugin. |
Each action object may contain vendor extensions.
IMPORTANT Field references ($ references) are assumed to be strings, and therefore care must be taken with certain mathematical operations such as +
which both Groovy and JavaScript use for string concatenation. Remember to cast values to numeric equivalents as required.
For convenience, we've listed some common transformation examples below and their corresponding expressions.
Transformation | Actions |
---|---|
Copy field 44 into field 144 | [{"type": "expression", "expression": "$144=$44"}] |
Move field 44 into field 144 | [{"type": "expression", "expression": "$144=$44"},{"type": "drop", "tag": "44"}] |
Set 1002 equal to the sum of fields 1000 and 1001 | [{"type": "expression", "expression": "$1002=$1000.toInteger()+$1001.toInteger()"}] |
Prefix field 180 with the string 'foo:' | [{"type": "expression", "expression": "$180='foo:'+$180"}] |
Combine fields 243 and 337 into a field 999 | [{"type": "expression", "expression": "$999=$243+$337"}] |
Default field 266 to 'bar' if it isn't set | [{"type": "expression", "expression": "$266=($266)?$266:'bar'"}] |
Multiply field 15 is 'GBX' then change to 'GBP' and multiply 44 by 100 | [{"type": "expression", "expression": "$44=($15=='GBX')?$44*100:$44"},{"type": "expression", "expression": "$15=($15=='GBX')?'GBP':'GBX'"}] |
Split 1000 into fields 450 and 560 using a delimiter of ':', and then drop 1000 | [{"type": "expression", "expression": "$450=$1000.split(':')[0]"},{"type": "expression", "expression": "$560=$1000.split(':')[1]"},{"type": "drop", "tag": "1000"}] |
Store field 890 using a reference derived from fields 49 and 11, and then drop it from the message | [{"type": "store", "uid": "$49+'-'+$11", "expression": "$UID=$890"},{"type": "drop", "tag": "890"}] |
Restore a saved value into field 890 using fields 49 and 11 if it isn't already present | [{"type": "store", "uid": "$49+'-'+$11", "expression": "$890=($890)?$890:$UID"}}] |
WorkflowsObject
{
"workflows": [
{
"nav": {...},
"event": {...},
"states": {...},
"transitions": {...}
},
...
]
}
The workflows object section is a simple list of workflow objects, each defined as follows:
Field Name | Type | Description |
---|---|---|
nav | WorkflowNav | Required List of individual workflow described in this specifications. Must contain at least 1 workflow. |
states | State | Required list of possible individual states the object (e.g. Orders, Quote) can take in the workflow |
event | Event | optional List of market related events that trigger or result from a transition. |
transitions | Transition | Required Description of transitions (including triggering event - FIX msg - and resulting state) |
workflowNav
"nav": {
"bbbbbbbb": {
"name": "Request for Quote - Order Placement session",
"description": "As an alternative to a streaming price subscription, a “Request for Quote” (RFQ) model is supported for FX Spot, FX Forward Outright, NDF & FX Swaps"
}
},
The array consists of workflow nav objects defined by the following fields:
Field Name | Type | Description |
---|---|---|
name | string |
Required Name of the workflow. |
description | string |
Required Description of the specific workflow being modelled. |
State
{
"nav": "bbbbbbbb",
"name": "Submitted",
"isInitial": true,
"description": "Request for Quote for Streaming price subscription"
},
The 'states' object is a list of state attributes which are defined by the fields below:
NOTE: Within state objects, it is expected that exactly one state is marked as isInitial
, and a second state is marked as isFinal
.
event
"MARKET_OPEN": {
"description": "This is my market open",
"time": "09:00:00"
},
The 'event' object is defined by the fields below:
Field Name | Type | Description |
---|---|---|
description | string |
Required Description of this specific event. |
time | string |
Optional Time in UTC at which the event is triggered. |
Transition
{
"description": "Cancellation of an open order",
"start": ["Order.Acknowledged","Order.PartiallyFilled"],
"trigger": {
"type": "technical",
"key": "KBfFbiqQ",
"direction": "in"
},
"responses": [
{
"messageWireId": "9",
"where": {
"expressionType": "groovy",
"expression": "($150 == 4)&($39 == 0)"
},
"end": "Order.Acknowledged",
"isSuccess": false
},
{
"messageWireId": "9",
"where": {
"expressionType": "groovy",
"expression": "($150 == 4)&($39 == 1)"
},
"end": "Order.PartiallyFilled",
"isSuccess": false
},
{
"messageWireId": "8",
"where": {
"expressionType": "groovy",
"expression": "($150 == 4)&($39 == 4)"
},
"end": "Order.Closed",
"isSuccess": true
}
]
}
The 'transition' object is defined by the fields below:
Field Name | Type | Description |
---|---|---|
description | string |
Required Description of this transition |
transitionStartstart | Array |
Required List of states the transition can initiate from. |
triggertrigger | Trigger | Optional Solicited message (Action) required to trigger the transition. |
responses | Array | Required List of possible responses: messages with field conditions. |
Trigger
The 'trigger' object is defined by the fields below:
Response
"bbbb2266": {
"type": "technical",
"messageKey": "qdmCfuBx",
"with": {
"45": {
"last": "34"
},
"372": {
"last": "35"
}
},
"description": "Cancel RFQ reject(j)",
"end": "QuoteRequest.Active",
"isSuccess": false
}
The 'response' object is defined by the fields below:
Field Name | Type | Description |
---|---|---|
Type | string |
Required Type of the message serving as a response. Possible values: "technical", "functional", "event". |
MessageKey | string |
Required Reference of the message. |
With | With | Required List of fields with specific expected values. |
End | string |
Required Resulting state at the end of the transition |
IsSuccess | boolean |
Required Did the transition successfully complete? |
Description | string |
Optional Description of the response. |
With
The 'with' object contains a series of objects. For the sake of clarity, we have organised those objects under 5 different blocks:
Block Name | Description |
---|---|
withSimpleValue | Objects used for simple fixed value of the tag. |
withReferencedValue | Objects used to define where to get the value of the tag from. |
withRange | Objects used to define here to get the value of the tag from. |
withMath | Objects used to define the operators to compute the value of the tag. |
withIf | Objects used to define the conditions to compute the value of the tag. |
Please read the following sections for details on the content of each block of objects.
withSimpleValue
"with": {
"150": {
"fixed": "2"
},
"64": {
"date": "20190131"
},
"60": {
"time": "NOW"
}
}
The 'withSimpleValue' object will contain one of the following fields:
Field Name | Type | Description |
---|---|---|
Fixed | string |
Optional Fixed value input in field. |
Date | string |
Optional date to be computed in the following format YYYYMMDD. Can also be a compute instruction like TODAY, YESTERDAY. |
Time | string |
Optional Time in timestampUTC. Can also be a compute instruction like NOW. |
withReferencedValue
"with": {
"37": {
"last": "37"
},
"58": {
"last": "58",
"default": "Trade"
},
"194": {
"this": "31"
}
}
The 'withReferencedValue' object will contain one of the following fields:
Field Name | Type | Description |
---|---|---|
This | integer |
Optional tag of the field from which the value is copied - in this message. |
Last | integer |
Optional tag of the field from which the value is copied - in previous linked message. |
Default | string |
Optional Default value if reference "this" or "last" tag is not found. |
Note that This and Last are mutually exclusive.
withRange
"32": {
"min": {
"fixed": 1
},
"max": {
"last": "38"
}
}
The 'withRange' object will contain one of the following objects:
Field Name | Type | Description |
---|---|---|
Min | with | Optional Min value of this field - used for integer fields. |
Max | with | Optional Max value of this field - used for integer fields. |
withMath
"6": {
"divide": {
"numerator": {
"sum": [
{
"multiply": [
{
"last": "14"
},
{
"last": "6"
}
]
},
{
"multiply": [
{
"this": "31"
},
{
"this": "32"
}
]
}
]
},
"denominator": {
"last": "38"
}
}
},
The 'withMath' object will contain one of the following objects:
Field Name | Type | Description |
---|---|---|
Sum | with | Optional Sum operation. |
Substract | with | Optional Subtraction operation. |
Multiply | with | Optional Multiply operation. |
Divide | divide | Optional Divide operation. |
The 'Divide' object will contain the following 2 objects:
Field Name | Type | Description |
---|---|---|
Numerator | with | Required Numerator of the divide operation. |
Denominator | with | Required Denominator of the divide operation. |
withIf
"31": {
"if": [
{
"lang": "groovy",
"condition": "$54 == 1",
"max": {
"last": "44",
"default": 99999
}
},
{
"lang": "groovy",
"condition": "$54 != 1",
"min": {
"last": "44",
"default": 0.001
}
}
]
},
The 'withIf' object is used to set the conditions to define the value of a tag
Field Name | Type | Description |
---|---|---|
if | withIfArray | Required Array of conditions used to define the value of a tag - It contains at least 1 object. |
The If is a series of 'Ifcondition' objects defined by the following attributes:
Field Name | Type | Description |
---|---|---|
lang | string |
Optional The language of the condition expression. Options are groovy (default) or javascript . |
Condition | string |
Required Condition expressed in either groovy or javascript . |
withObject | with | Required Resulting value of the tag. |