交易系统开发(十)——FIX协议

一、FIX协议简介

1、FIX协议简介

FIX(Financial Information eXchange Protocol,金融信息交换协议)是由国际FIX协会组织提供的一个开放式协议,目的是推动国际贸易电子化进程,在各类参与者之间,包括投资经理、经纪人、买方、卖方建立起实时的电子化通讯协议。
FIX协议的目标是把各类证券金融业务需求流程格式化,成为一个可用计算机语言描述的功能流程,并在每个业务功能接口上统一交换格式,方便各个功能模块的连接。
 2006年10月,FPL(FIX Protocol Ltd)发布了FIX5.0,FIX5.0引入TI(the transport independence )传输无关框架。TI将FIX会话层从应用层协议中分离出来。在TI框架下,应用层协议消息可以通过任意合适的传输技术进行传送,FIX会话层协议是FIX应用层消息的可选传输传输协议之一。两个协议层的版本标注将会有所不同,FIX X.Y为FIX应用层协议版本,应用层协议定义金融活动相关的业务数据结构;FIXT X.Y 为FIX会话层协议版本编号,会话层协议定义数据通信相关的协议。

2、FAST协议

为了解决FIX协议传输市场数据存在的冗余度高,带宽需求大的问题,芝加哥商品交易所(CME)在2003年向FPL(FIX Protocol Ltd)提交了一个解决方案,FPL在2004年成立了市场数据优化工作组(MDOWG),2005年MDOWG开始根据一些POC(Prove of Concept)的结果进行协议标准制定,并于2006年初完成了FAST(FIX Adapted for Streaming) V1.0,2006年12月完成了FAST V1.1。 
FAST协议核心是一个压缩算法,将按照FIX规范定义的数据经过压缩后,可以在很大程度上降低发送、接收双方的带宽。
FAST协议的优点是高压缩比,低资源消耗,算法简单高效,每秒百万级别的消息处理能力。

3、STEP协议

STEP(Securities trading exchange protocol,证券交易数据交换协议)是基于FIX4.4版本FIX协议制定出来的中国本地化FIX协议版本,是中国国家金融行业标准,已成为事实上的证券数据标准,其语法简单定义灵活易扩展,数据相对冗余。

4、Binary协议

Binary即二进制协议,定义了各种报文的字段、编解码规则等。在深交所的Binary协议中,所有的消息都有3部分组成:消息头,消息体和消息尾。消息头有8个字节,包括整数MsgType和整数BodyLen,MsgType表示消息的类型,BodyLen表示消息体的长度;消息体根据BodyLen大小进行读取;消息尾是4个字节的 checksum。

5、FIX协议的优缺点

FIX协议优点是使用key-value对,可以很方便地查看报文内容以及扩展新字段,国际通用,适应力强。
FIX协议缺点是速度慢。

二、FIX协议工作原理

1、FIX应用模式

FIX有Initiator和Acceptor两种应用类型,Initiator是通信发起者,通过发送初始Logon消息发起Session;Acceptor是FIX Session的接收方,负责执行第一层次认证和通过传输Logon消息响应确认正式连接请求被接受。
FIX协议规定Initiator是通信发起者,Acceptor为接受者。FIX标准应用模式以网关为Acceptor,客户端为Initiator。

2、FIX Connection

FIX Connection由3部分组成:logon登录,message exchange消息传输,logout注销。

3、Fix Session

FIX Session由一个或多个FIX Connection组成,一个FIX Session可以有多次登录。
一个FIX Session定义为一个在连接双方间的的带有连续序列号的有序消息双向传输流。单个FIX Session能够跨越多个连续(不是并行的)的物理连接。在一个FIX Session中,参与方能够多次连接和断开连接。连接的参与方必须根据单个系统及时间区域需求,公共协商Session的开始和结束。
建议一个新的FIX会话在每24小时期间建立一次,可以维持24小时的连接和通过设置在Logon消息中的ResetSeqNumFlag建立一套新的序列号。
每个FIX参与方必须为FIX Session维护两个序列号,一个是接收序列号,一个是发送序列号,两者都在建立FIX Session开始时初始化为1。每个消息被赋予一个唯一的序列号值,并在消息发送后递增。此外,每个收到的消息都有一个唯一的序列号,接收序列号计数器在收到每个消息后将会被递增。
当接收序列号与所希望得到的的正确序列号不必配时,必须采取纠错处理。

4、序列号

每条FIX消息都由一个唯一的序列号进行标识,序列号在每一个FIX Session开始时被初始化为1,并在整个Session期间递增。监控序列号可以使Session参与者识别和处理丢失的消息,当在一个FIX Session中重新连接时能够快速进行应用程序同步。
每个Session将建立一组互不依赖的接收和发送序列。Session参与者将维护一个赋予发送消息的序列和一个监控接收消息的消息块间隙序列号。

5、心跳

在消息交互期间,FIX应用程序将周期性产生Heartbeat心跳消息。心跳消息可以监控通信链路状态及识别接收序列号间隙。Heartbeat消息的周期间隔由Session发起者使用在Logon消息中HeartBtInt域进行定义。
Heartbeat心跳消息的时间间隔应当在每一个消息发送后复位,即发送一个消息后,在间隔给定的时间内无其它消息发送则发送一个Heartbeat心跳消息。HeartBtInt值应当被Session双方认同,由Session发起方定义并由Session接收者通过Logon消息进行确认。同一个HeartBtInt被Session双方——登录的发起者和登录的接受者共同使用。

6、数据完整校验

消息数据内容的完整性可以参用两种方式来验证:消息长度和校验码检查。
程序通过计算BodyLength域到CheckSum标记(“10=”)分界符的字符数,域BodyLength标识的消息长度进行比较来完成完整性效验。
ChekSum完整性检查,通过计算从域“8=” 中“8”开始,包括紧跟在CheckSum标记域的分界符每个字符的2进制和同CheckSum进行比较得到。
一个FIX消息校验和通过计算到ChechSum域(不包括)的消息的每个字节和得到。然后,校验和被转换为模256的数字用于传送和比较。校验和在所有加密操作后被计算。
FIX消息示例如下:
8=FIX.4.29=7335=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y10=208
消息长度:9=73,标识的消息体如下:
35=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y

7、消息确认

FIX协议不支持单个消息的确认,采用监控消息时隙的方法来进行消息恢复和验证。
普通的数据传送(无单个消息确认)通过消息序列间隙进行错误识别。每个消息由一个唯一的序列号进行标识。接收端应用程序负责监控接收消息序列号以识别消息间隙并产生重传请求。

8、加密

加密算法由连接双方共同协商。
一个消息的任何一个Field可以被加密并放在SecureData Field中。然而,一些显示的标志域必须采用明文进行传输。为确保完整性,明文域可以在SecureData域中重复。
当使用加密时,建议所有的消息体都进行加密。如果一个消息中的循环组数据中的部分数据要加密,循环组必须全部进行加密。
预先协商好的加密算法在Logon消息中进行声明。

9、自定义域

FIX协议为给用户提供最大的灵活性,其允许用户自定义域。自定义域在认同的参与者之间实现、应用,因此需要注意避免冲突。
FIX协议规定,Tag在5000 到9999保留用于用户自定义域,用于企业联盟的信息交换,可以通过FIX网站进行注册;Tag在10000以上保留用于单一企业内部使用,不用注册。

10、有序消息处理

FIX协议假设消息在所有参与者间完全按照顺序进行传输。协议的实现者在设计消息间隙填充处理时应当考虑顺序传输假设。有两种方式处理消息间隙。第一种是,要求接收的消息是最后一个接收消息的后续消息或在维护一个所有新消息有序序列时,请求特定丢失消息。比如:接收方丢失了5个消息块中的第二个,程序能忽略第3到第5个消息,产生一个对消息2到消息5的重传请求,或者从消息2到无穷大消息编号的重传请求。第二种方式是,暂时存储消息3到消息5,仅要求重传消息2。

11、重复消息

当一个FIX引擎对一个消息是否成功地被指定的目标接收或者当对一个重传请求进行响应时,将会产生一个可能的消息复制。复制消息将用同样的序列号进行重新传送,此时在头部的PossDupFlag域将会被设置为‘Y’。接收端程序负责处理重发消息,可以作为一个新消息进行处理,或者根据实际情况忽略该消息。
所有重传请求的响应消息都将包含其值为‘Y’的PossDupFlag域。没有PossDupFlag域或者PossDupFlag域为‘N’的消息应被当作初始传送消息。PossDupFlag值为‘Y’的重传消息需要重新计算其CheckSum值。复制消息中发生变化的域包括:CheckSum,OrigSendingTime,SendingTime,BodyLength和PossDupFlag,加密相关域(SecureDataLen和SecureData)也必须被重新构造。

12、消息重发

模糊的应用层消息可能随同Po***esend标志被重传。当一个指令没有在规定时间长度内进行确认或者终端用户挂起该指令没有进行传送时这种方法非常有用。接收程序必须识别此标志,并质疑其内部域以确定该指令是否在之前已经被接收过。重传消息将包含与原始消息相同的数据体,但包含Po***esend标志和一个新的序列号。此外,CheckSum和与加密相关的域值需要重构。

三、消息类型

1、管理消息

管理消息(Adminitrative Message)是为了信息交换过程更加顺畅一致而使用的控制,包括登录、心跳、检验请求、重新发送请求、拒绝(交换过程)顺序重设及注销等。

2、应用消息

应用消息(Application Messages)是交易的数据,包括如下数据:
公告:宣布已完成的交易信息。
重要提示:告知由经纪人买卖的证券是由私人股份有限公司所有,还是由代理持有,以及持有量。
消息:是经纪人和机构之间传送的一般自由格式信息,带有识别信息紧急性和商号主题词分类标志。
电子邮件:其格式和用途与消息信息相同,但更倾向于双方非公开的用途。
报价请求:有些市场要求经纪人在每次订单前提出报价。
报价与多宗报价:回应报价请求的信息并用于发表主动的报价。
请求对多宗报价的确认:使用报价回应水平标记,有选择地支持对报价的确认。
报价撤销:报价发起人用于撤销报价。
报价状况请求:机构用来生成执行报告。
报价确认:针对报价、多宗报价、报价撤销和报价请求,作出回应。
行情数据请求:通过此请求得到所指定的证券和外汇交易报价的行情数据。
行情数据—快照、完全刷新:用于发送双方的订单登记簿、报价清单、交易清单、指数值、开盘价、收盘价、成交单价、最高价、最低价和变动加权平均价等。
行情数据—添加刷新:用于添加刷新请求。
行情数据请求拒绝:用于经纪人因交易或技术上的原因不承兑行情数据请求的情况。
证券定义请求:用于某一指定证券与第二方交易。
证券定义:接受或拒绝证券定义信息中请求的证券,发回证券及类型清单。
证券状况请求:用于提出有关证券状况的请求。
证券状况:提供有关证券状况改变的报告。
交易盘状况请求:请求有关市面状况的信息。
交易盘状况:提供有关市场状况的信息。
新订单:机构向经纪人提供有关证券或外汇的订单。
执行报告:确认收到订单或订单改变信息,传递订单状况或订单成交信息,报告交易的费用。
未知交易:通知交易方,收到的订单已被执行。
订单撤销、替换请求:改变订单的参数。
订单撤销拒绝:经纪人在不能承兑所收到的撤销请求信息时发出的信息。
订单状况请求:机构要求经纪人生成并发挥有关订单状况的信息。
划拨:指定如何将一个订单或一组订单细分为一个或多个账户。
划拨确认:确认收到机构发送的划拨信息及状态。
结算指令:经纪人或机构交易结算的指令。
出价请求:在非公开市场与公开市场,因市场规则不同用法也不同。
出价回应:因两个市场规则不同,有不同的用法。
新订单—清单:因两种市场规则的不同而不同。
敲定价:交换本金交易的敲定价。
状况清单:卖方以主动方式发送回应状况清单请求信息。
清单执行:机构用于指示经纪人开始执行已被提交的证券订单信息。
清单撤销执请求:用于机构希望在执行交易盘之前或之中,撤销已被提交的证券订单消息。
状况清单请求:用于机构指示经纪人生成有关某一状况清单的信息。
清单订单信息的分解:使用与其它FIX信息相同的方法,支持程序交易中的信息分解。
交易信息拒绝:拒绝因遵循了交易盘规则而不能以其它方式进行拒绝的应用层面的信息。

四、FIX协议

1、数据类型

FIX协议的数据类型包括整数int,浮点数float,字符char,布尔Boolean,字符串String,数据data。

2、Field

Field由Tag、Value和Delimeter组成,Delimeter用于分隔不同Field,如8=FIX4.1SOH,tag为8,value为FIX4.1,Delimeter为SOH(0x01)。
常见Field如下:
Tag FieldName Description
8 BeginString 起始串,FIX协议版本
9 BodyLength 消息长度
35 MsgType 消息类型:例如F=Order Cancel Request,取消订单
11 ClOrdID 客户端订单ID
37 OrderID 服务端订单ID
41 OrigClOrdID 原始客户端订单ID
54 Side 买卖类型。例如:1 = Buy,2 = Sell
55 Symbol 股票代码。例如:YRD
10 CheckSum 校验码

3、消息

FIX消息由多个Field组成,包括消息头、消息体、消息尾三部分。
消息头的前3个Field的次序不能改变,起始串(Tag=8)、消息体长度(Tag=9)、消息类型(Tag=35)。
消息尾的最后一个Field必须是校验和Field(Tag=10)。
8=FIX.4.49=6335=034=115849=SAMPLESENDER52=20150201-00:22:34.99556=SAMPLETARGET10=114
循环组中,Field出现的顺序应遵循循环组在消息或组件中定义时的次序;在一条FIX消息中,除循环组Field外任何其它Field不能重复出现。
由于FIX消息有可能在公网或不安全的网络上传输交换,因此需要对相关的敏感数据加密处理,具体加密的方法由连接双方达成的协议而定。
FIX消息内除某些需要公开识别的Field以明文传输外,其它任何Field都可以加密放置密文数据域 (SecureData)内,被加密的Field也可以同时保留明文的表示方式。
当决定使用加密方案时,可以对FIX消息正文内所有的Field加密。如果消息的循环组内有部分需要加密的,那么要求对整个循环组加密。
FIX协议还提供的一些Field用以支持数字签名、密钥交换和正文加密等安全技术。

4、消息头

每一个会话或应用消息有一个消息头,消息头指明消息类型、消息体长度、发送目的地、消息序号、发送起始点和发送时间。
Tag 域名 必需 说明
8 BeginString Y 起始串,取值:FIX.4.2(不可加密,消息的第一个域)
9 BodyLength Y 消息体长度(不可加密,消息的第二个域)
35 MsgType Y 消息类型(不可加密,消息的第三个域)
49 SenderCompID Y 发送方代码(不可加密,发送方标识符)
59 TargetCompID Y 接收方代码(不可加密,接收方标识符)
115 OnBehalfOfCompID N 最初发送方标识符(可加密),用于经第三方发送。
128 DeliverToCompID N 最终接收方标识符(可加密),用于经第三方发送。
90 SecureDataLen N 密文数据长度
91 SecureData N 密文数据(紧跟密文数据长度域)
34 MsgSeqNum Y 消息序号(可加密),如果交易双方不采用 FIX 会话 机制,可将该 tag 置为一个固定的值,例如 0。
50 SenderSubID N 发送方子标识符(可加密)
142 SenderLocationID N 发送方方位标识符(可加密)
57 TargetSubID N 接收方子标识符(可加密)
143 TargetLocationID N 接收方方位标识符(可加密)
116 OnBehalfOfSubID N 最初发送方子标识符(可加密)
144 OnBehalfOfLocationID N 最初发送方方位标识符(可加密)
129 DeliverToSubID N 最终接收方子标识符(可加密)
145 DeliverToLocationID N 最终接收方方位标识符(可加密)
43 PossDupFlag N 可能重复标志,重复发送时,作此标记。(可加密)
97 Po***esend N 可能重发标志。(可加密)
52 SendingTime Y 发送时间(可加密)
122 OrigSendingTime N 原始发送时间(可加密)
347 MessageEncoding N 消息中 Encoded 域的字符编码类型(非 ASCII 码)
369 LastMsgSeqNumProcesse d N 最后处理消息序号(可加密)
370 OnBehalfOfSendingTime N 最初发送时间(用 UTC 表示时间)

5、消息尾

每一个消息(会话或应用消息)有一个消息尾,并以此终止。消息尾可用于分隔多个消息,包含有3位数的校验和值。
Tag 域名 必需 说明
93 SignatureLength N 数字签名长度(不可加密)
89 Signature N 数字签名(不可加密)
10 CheckSum Y 校验和,消息的最末域。(不可加密)

6、新订单消息

对于在消息头中设置了Po***esend标志的订单消息,应当使用交易客户方订单编号(ClOrdID)核实是否已收到该订单,具体实现时还应检查订单参数(买卖方向、证券代码、数量等)进行核实。如果之前收到该订单,应以执行报告消息回应订单状态。如果之前未收到,则以执行报告消息回应订单确认。

7、执行报告消息

订单回执包括订单确认、订单状态变化确认(如撤单确认)、成交回报、
订单拒绝。

8、订单状态请求消息

订单状态请求用于向交易服务方请求某订单的状态,交易服务方通过执行报告消息返回订单状态。

9、撤单消息

撤单消息用以撤消订单的全部订单剩余数量。
撤单消息也被赋予一个ClOrdID,如果被拒绝,撤单拒绝消息的ClOrdID放置撤单消息的ClOrdID,而原始订单的ClOrdID则放入OrigClOrdID域。ClOrdID要保证唯一。

10、撤单拒绝消息

本消息用于撤单消息的拒绝。
交易服务方接收到撤单发现无法执行(已成交订单不可更改等),将发送撤单拒绝。
拒绝撤单时,撤单拒绝消息应用 ClOrdID 指示撤单的 ClOrdID,用 OrigClOrdID 指示之前最后接受的订单(除非拒绝原因是“未知订单”)。
Tag 域名 必需 说明
标准消息头 Y MsgType=9
37 OrderID Y 期货公司委托号,同个交易日必需保证唯一
11 ClOrdID Y 交易客户方订单编号
41 OrigClOrdID Y 原始交易客户方订单编号,指示被撤消订单的ClOrdID
39 OrdStatus Y 订单状态
109 ClientID Y 客户资金帐号
1 Account Y 客户交易编码
60 TransactTime N 订单发起时间
434 CxlRejResponseTo N 撤单拒绝回应类型
102 CxlRejReason N 撤单拒绝原因
58 Text N
10 标准消息尾 Y