写点什么

FIX 协议介绍

  • 2020-02-13
  • 本文字数:12688 字

    阅读完需:约 42 分钟

FIX协议介绍

定义

FIX 协议是由国际 FIX 协会组织提供的一个开放式协议,目的是推动国际贸易电子化的进程,在各类参与者之间,包括投资经理、经纪人,买方、卖方建立起实时的电子化通讯协议。FIX 协议的目标是把各类证券金融业务需求流程格式化,使之成为一个个可用计算机语言描述的功能流程,并在每个业务功能接口上统一交换格式,方便各个功能模块的连接。

协议工作原理

通信模型及基本概念

通信模型

  • Initiator :发起者,建立通信连路,通过发送初始 Logon 消息发起会话的参与方。

  • Acceptor :接收方 FIX 会话的接收方。负责执行第一层次的认证和通过传输 Logon 消息的确认正式声明连接请求被接受。

  • 原则:先发起者为 Initiator ,接受者为 Acceptor 。

  • 标准模式以网关为 Acceptor,客户端为 Initiator 做为常用模式。

Fix connection

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

  • logon 登录

  • 1542963840887079291.png

  • logout 注销

  • 1542963854817074420.png

Fix session

  • FIX 会话由一个或多个 FIX Connection FIX 连接组成。一个 FIX 会话可以有多次登录。

序列号

  • 所有的 FIX 消息都由一个唯一的序列号进行标示。序列号在每一个 FIX 会话开始时被初始化为 1,并在整个会话期间递增。监控序列号可以使会话参与者识别和处理丢失的消息,当在一个 FIX 会话中重新连接时能够快速进行应用程序同步。

  • 每个会话将建立一组互不依赖的接受和发送序列。会话参与者将维护一个赋予发送消息的序列和一个监控接受消息的消息块间隙序列号。

心跳

  • 在消息交互期间,FIX 应用程序将周期性产生 Heartbeat 心跳消息。该心跳消息可以监控通信链路状态及识别接收序列号间隙。发送 Heartbeat 的周期间隔由会话发起者使用在 Logon 消息中 HeartBtInt 域进行定义。

  • Heartbeat 心跳消息的时间间隔应当在每一个消息发送后复位,即发送一个消息后,在间隔给定的时间内无其它消息发送则发送一个 Heartbeat 心跳消息。HeartBtInt 的值应当被会话双方认同,由会话发起方定义并由会话接收者通过 Logon 消息进行确认。同一个 HeartBtInt 被会话双方——登录的发起者和登录的接受者共同使用。

数据完整校验

  • 消息数据内容的完整性可以参用两种方式来验证:消息长度和效验码检查。

  • 程序通过计算 BodyLength 域到 CheckSum 标记(“10=”)分界符的字符数,域 BodyLength 标示的消息长度进行比较来完成完整性效验。

  • ChekSum 完整性检查,通过计算从域“8=” 中“8”开始,包括紧跟在 CheckSum 标记域的分界符每个字符的 2 进制和同 CheckSum 进行比较得到。

  • 一个 FIX 消息校验和通过计算到 ChechSum 域(但不包括)的消息的每个字节和得到。然后,校验和被转换为模 256 的数字用于传送和比较。校验和在所有加密操作之后被计算。

  • 校验代码:


样例:8=FIX.4.29=7335=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y10=2081、消息长度:9=7335=A34=149=CLIENT52=20181119-10:42:48.76856=SERVER98=0108=30141=Y(这段长度)2、效验码检查char *GenerateCheckSum( char *buf, long bufLen ) {static char tmpBuf[ 4 ]; long idx;unsigned int cks;for( idx = 0L, cks = 0; idx < bufLen; cks += (unsigned int)buf[ idx++ ] ); sprintf( tmpBuf, “%03d”, (unsigned int)( cks % 256 ) );return( tmpBuf );}
复制代码

消息确认

  • FIX 协议不支持单个消息的确认。采用的是监控消息时隙的方法来进行消息恢复和验证。

  • 普通的数据传送(无单个消息确认)通过消息序列间隙进行错误识别。每个消息由一个唯一的序列号进行标示。接收端应用程序负责监控接收消息序列号以识别消息间隙并产生重传请求。

  • 每个 FIX 参与方必须为 FIX 会话维护两个序列号,一个是接收序列号,一个是发送序列号,两者都在建立 FIX 会话开始时初始化为 1。每个消息被赋予一个唯一的序列号值,并在消息发送后递增。此外,每个收到的消息都有一个唯一的序列号,接收序列号计数器在收到每个消息后将会被递增。

  • 当接收序列号与所希望得到的的正确序列号不必配时,必须采取纠错处理。

加密

  • 加密算法由连接双方共同协商。

  • 一个消息的任何一个域可以被加密并放在 SecureData 域中。然而,一些显示的标志域必须采用明文进行传输。为确保完整性,明文域可以在 SecureData 域中重复。

  • 当使用加密时,建议但不是必须,所有的消息体都进行加密。如果一个消息中的重复组数据中的部分数据要加密,这个重复组必须全部进行加密。

  • 预先协商好的加密算法在 Logon 消息中进行声明。

自定义域

  • FIX 为给用户提供最大的灵活性,FIX 协议允许用户自定义域。这些域在认同的参与者之间实现、应用,并且应注意避免冲突。

  • Tag 数在 5000 到 9999 保留用于用户自定义域。这些 tag 值用于企业联盟的信息交换。可以通过 FIX 网站进行注册。

  • 10000 以上保留用于单一企业内部使用。不用注册。

消息格式

数据类型

整数 int,浮点数 float,单个字符 char,布尔 Boolean,字符串 String,数据 data

常见域

Tag(标记)FieldName(域名)备注
8BeginString起始串,FIX协议版本
9BodyLength消息长度
35MsgType消息类型:例如F=Order Cancel Request,取消订单
11ClOrdID客户端订单ID
37OrderID服务端订单ID
41OrigClOrdID原始客户端订单ID
54Side买卖类型。例如:1 = Buy,2 = Sell
55Symbol股票代码。例如:YRD
10CheckSum校验码

域语法

  • 开始部分应是消息头,随后是正文,最后是消息尾;

  • 消息头的前 3 个域的次序不能改变:起始串(Tag =8)、消息体长度(Tag =9)、消息类型(Tag =35);

  • 消息尾的最后一个域应是校验和域(Tag=10);

  • 重复组中,域出现的顺序应遵循该重复组在消息或组件中定义时的次序;

  • 在一条消息中,除重复组域外任何其他域不能重复出现。

安全与加密

  • 由于消息有可能在公网或不安全的网络上传输交换,因此需要对相关的敏感数据加密处理。

  • 具体加密的方法由连接双方达成的协议而定。

  • 消息内除某些需要公开识别的域以明文传输外其他任何域都可以加密放置密文数据域 (SecureData)内。当然,这些被加密的域也可以同时保留明文的表示方式。

  • 当决定使用加密方案时,可以对消息正文内所有的域加密。如果消息的重复组内有部分需要加密的,那么要求对整个重复组加密。

  • 本协议还提供的一些域用以支持数字签名、密钥交换和正文加密等安全技术。

消息

消息头

每一个会话或应用消息有一个消息头,该消息头指明消息类型、消息体长度、发送目的地、消息序号、发送起始点和发送时间。


Tag域名必需说明
8BeginStringY起始串,取值:FIX.4.2(不可加密,消息的第一个域)
9BodyLengthY消息体长度(不可加密,消息的第二个域)
35MsgTypeY消息类型(不可加密,消息的第三个域)
49SenderCompIDY发送方代码(不可加密,发送方标识符)
56TargetCompIDY接收方代码(不可加密,接收方标识符)
115OnBehalfOfCompIDN最初发送方标识符(可加密),用于经第三方发送。
128DeliverToCompIDN最终接收方标识符(可加密),用于经第三方发送。
90SecureDataLenN密文数据长度
91SecureDataN密文数据(紧跟密文数据长度域)
34MsgSeqNumY消息序号(可加密),如果交易双方不采用 FIX 会话 机制,可将该 tag 置为一个固定的值,例如 0。
50SenderSubIDN发送方子标识符(可加密)
142SenderLocationIDN发送方方位标识符(可加密)
57TargetSubIDN接收方子标识符(可加密)
143TargetLocationIDN接收方方位标识符(可加密)
116OnBehalfOfSubIDN最初发送方子标识符(可加密)
144OnBehalfOfLocationIDN最初发送方方位标识符(可加密)
129DeliverToSubIDN最终接收方子标识符(可加密)
145DeliverToLocationIDN最终接收方方位标识符(可加密)
43PossDupFlagN可能重复标志,重复发送时,作此标记。(可加密)
97PossResendN可能重发标志。(可加密)
52SendingTimeY发送时间(可加密)
122OrigSendingTimeN原始发送时间(可加密)
347MessageEncodingN消息中 Encoded 域的字符编码类型(非 ASCII 码)
369LastMsgSeqNumProcesse dN最后处理消息序号(可加密)
370OnBehalfOfSendingTimeN最初发送时间(用 UTC 表示时间)

消息尾

每一个消息(会话或应用消息)有一个消息尾,并以此终止。消息尾可用于分隔多个消息,包含有 3 位数的校验和值。


Tag域名必需说明
93SignatureLengthN数字签名长度(不可加密)
89SignatureN数字签名(不可加密)
10CheckSumY校验和,消息的最末域。(不可加密)

新订单消息(MsgType=D)

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


1542963901113097583.png


Tag域名必需说明


 | 标准消息头             | Y  | MsgType=D                                                        
复制代码


11 | ClOrdID | Y | 交易客户方订单编号,在订单有效交易日内必需


109 | ClientID | Y | 客户资金帐号


1 | Account | Y | 客户交易编码


110 | MinQty | N | 最小成交量。


55 | Symbol | Y | 期货合约代码


167 | SecurityType | N | FUT = 期货


200 | MaturityMonthYear | N | 用于指定期货到期的年和月


205 | MaturityDay | N | 用于期货的到期日期,并被与到期年月 (MaturityMonthYear)联合使用


207 | SecurityExchange | Y | 用于指定交易所


77 | OpenClose | Y | 指明开仓,平仓


8009 | HedgeFlag | Y | 投机套保标志


8010 | TouchCondition | N | 触发条件


54 | Side | Y | 买卖方向


38 | OrderQty | N | 委托手数


60 | TransactTime | Y | 订单发起时间


40 | OrdType | Y | 订单类型


44 | Price | N | 价格(限价订单时有效)


423 | PriceType | N | 价格类型


99 | StopPx | N | 停止价


15 | Currency | N | 币种


59 | TimeInForce | N | 新订单生效时间,默认为当日有效


168 | EffectiveTime | N | 用于指定定单有效的时间


432 | ExpireDate | N | 有条件地用于在生效时间(TimeInForce)=在某 日前有效(GTD),而没有指定截止时间 (ExpireTime)的情况之下


126 | ExpireTime | N | 有条件地用于生效时间(TimeInForce) = 在某 日前有效(GTD)和到期日没有被指定的情况之 下


8096 | MacNetInfo | N | 委托方的机器网络信息


| 标准消息尾 | Y |

执行报告消息(MsgType=8)

  • 订单确认

  • 订单状态变化确认(如撤单确认)

  • 发送订单的成交回报

  • 订单拒绝


Tag域名必需说明


 | 标准消息头             | Y  | MsgType=8                                        
复制代码


37 | OrderID | Y | 期货公司委托号,同个交易日必需保证唯一


11 | ClOrdID | N | 交易客户方订单编号。如果是强平回报,则该值 取值为以”NONE”开头的当天交易日唯一的字符 串标识


41 | OrigClOrdID | N | 原始交易客户方订单编号,指示被撤消订单的 ClOrdID


17 | ExecID | Y | 期货公司的执行编号,在订单有效交易日内应保 证唯一


150 | ExecType | Y | 执行类型


39 | OrdStatus | Y | 订单状态


103 | OrdRejReason | N | 订单拒绝时需要


109 | ClientID | Y | 客户资金帐号


1 | Account | Y | 客户交易编码


55 | Symbol | Y | 期货合约代码


167 | SecurityType | N | FUT=期货


200 | MaturityMonthYear | N | 到期年月


205 | MaturityDay | N | 到期日期


207 | SecurityExchange | Y | 用于指定交易所


77 | OpenClose | N | 指明开仓,平仓


54 | Side | Y | 买卖方向


38 | OrderQty | Y | 委托手数


40 | OrdType | N | 订单类型


44 | Price | N | 订单价格


99 | StopPx | N | 停止价


59 | TimeInForce | N | 新订单生效时间,默认为当日有效


15 | Currency | N | 币种


32 | LastShares | N | 上一成交数(最近一笔成交数量)


31 | LastPx | N | 上一成交价(最近一笔成交价格)


30 | LastMkt | N | 上一成交市场


151 | LeavesQty | Y | 订单剩余数量


14 | CumQty | Y | 成交总数


6 | AvgPx | Y | 成交平均价


60 | TransactTime | N | 执行报告时间


381 | GrossTradeAmt | N | 成交总金额


110 | MinQty | N | 最小成交量


8500 | OrderEntryTime | N | 订单申报时间


8093 | DeclarationID | N | 报单号


8094 | TradeID | N | 撮合编号


| 标准消息尾 | Y |

订单状态请求消息(MsgType=H)

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


Tag域名必需说明


| 标准消息头             | Y  | MsgType=H                                
复制代码


37 | OrderID | Y | 期货公司委托号,同个交易日必需保证唯一


11 | ClOrdID | Y | 交易客户方订单编号


109 | ClientID | Y | 客户资金帐号


1 | Account | Y | 客户交易编码


55 | Symbol | Y | 期货合约代码


207 | SecurityExchange | Y | 用于指定交易所


167 | SecurityType | N | FUT=期货


200 | MaturityMonthYear | N | 用于指定期货到期的年和月


205 | MaturityDay | N | 用于期货的到期日期,并被与到期年月 (MaturityMonthYear)联合使用


54 | Side | Y | 买卖方向


| 标准消息尾 | Y |

撤单消息(MsgType=F)

撤单消息用以撤消订单的全部订单剩余数量。


撤单消息也被赋予一个 ClOrdID,可视作另外一个订单。如果被拒绝,撤单拒绝消息的 ClOrdID 放 置撤单消息的 ClOrdID,而原始订单的 ClOrdID 则放入 OrigClOrdID 域。ClOrdID 要保证唯一。


Tag域名必需说明


 | 标准消息头             | Y  | MsgType=F                  
复制代码


41 | OrigClOrdID | Y | 原始交易客户方订单编号,指示被撤消订单的 ClOrdID


37 | OrderID | Y | 期货公司委托号,同个交易日必需保证唯一


11 | ClOrdID | Y | 交易客户方订单编号


109 | ClientID | Y | 客户资金帐号


1 | Account | Y | 客户交易编码


55 | Symbol | Y | 期货合约代码。


167 | SecurityType | N | 证券代码源


200 | MaturityMonthYear | N | FUT=期货


205 | MaturityDay | N | 期货到期年月


207 | SecurityExchange | Y | 期货到期日期


54 | Side | Y | 买卖方向


60 | TransactTime | Y | 订单发起时间


40 | OrdType | Y | 订单类型


38 | OrderQty | Y | 委托手数


8093 | DeclarationID | N | 报单号


58 | Text | N |


| 标准消息尾 | Y |

撤单拒绝消息(MsgType=9)

本消息用于撤单消息的拒绝。


交易服务方接收到撤单发现无法执行(已成交订单不可更改等),将发送撤单拒绝。


拒绝撤单时,撤单拒绝消息应用 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 |


| 标准消息尾 | Y |

FIX 配置

  • 会话配置(SESSION)


配置描述有效值默认
BeginString会话使用的FIX版本号(发送和接收消息起始字符串)FIXT.1.1、FIX.4.4、FIX.4.3、FIX.4.2、FIX.4.1、FIX.4.0
SenderCompID会话当中定义本方的ID区分大小写的字符串
SenderSubID会话相关的本方的子ID号 (可选)区分大小写的字符串
SenderLocationID会话相关的本方的locationID号 (可选)区分大小写的字符串
TargetCompID本会话当中的对方ID区分大小写的字符串
TargetSubID本会话当中的对方SubID (可选)区分大小写的字符串
TargetLocationID本会话当中的对方locationID (可选)区分大小写的字符串
SessionQualifier附加的限定词,用于消除歧义,保证会话的唯一性区分大小写的字符串
DefaultApplVerID仅FIXT1.1(或以上版本)需要。忽略早期版本的传输。指定会话的默认应用程序的版本ID。ApplVerID的枚举值(请看ApplVerID字段详细介绍),或默认BeginString。FIX.5.0SP2、FIX.5.0SP1、FIX.5.0、FIX.4.4、FIX.4.3、FIX.4.2、FIX.4.1、FIX.4.0
ConnectionType定义会话当中本方的角色:acceptor或者initiatorinitiator、acceptor
StartTime交易日的会话有效开始时间,这时FIX会话被激活UTC时间,格式: HH:MM:SS
EndTime交易日的会话失效时间,FIX会话将被停止UTC时间,格式: HH:MM:SS
StartDay对于为期一周的会话配置,一周会话开始的第一天。与STARTTIME结合使用。使用一周中某天的英语任何缩写都是有效的(比如,mo, mon, mond, monda,Monday都是有效的)
EndDay对于为期一周的会话配置,一周会话结束的最后一天。与EndTime结合使用。使用一周中某天的英语任何缩写都是有效的(比如,mo, mon, mond, monda,Monday都是有效的)
MillisecondsInTimeStamp时间戳是否加入毫秒。FIX.4.2和更高版本可用。Y、NY
ResetOnLogon接收登录请求时,序列号是否要复位。只用于AcceptorY、NN
ResetOnLogout正常注销登录时,序列号是否要复位Y、NN
ResetOnDisconnect连接异常断开后是否要将序列号重置为1Y、NN
RefreshOnLogon确定是否应当从持久层登录时恢复会话状态。在创建热故障切换会话时有用。Y、NN
EnableLastMsgSeqNumProcessed是否在header中添加最后一条消息的序列号(可选tag369)。Y、NN
MaxMessagesInResendRequest设置一次重发请求的消息的最大消息数。任何大于0的整数。使用0为无穷大(默认)。0
SendLogoutBeforeDisconnectFromTimeout指定是否因超时断开连接之前发送logout消息Y、NN
IgnorePossDupResendRequests当PossDupFlag(tag 43)设置为true时,是否忽略一次重发请求Y、NN


  • 验证配置


配置描述有效值默认
UseDataDictionary告诉会话是否使用数据字典,或不希望使用数据字典。 如果你要使用repeating group,你必须使用DataDictionary。Y、NY
DataDictionary该配置只用于比FIXT.1.1还老的版本。详细参考FIXT.1.1的TransportDataDictionary和AppDataDictionary的配置。FIX44.xml、FIX43.xml、FIX42.xml、FIX41.xml、FIX40.xml
TransportDataDictionaryXML定义文件用于验证传入的管理消息。如果没有提供DataDictionary,只会做基本消息的验证。该配置只用于FIXT.1.1(或更高版本)的会话。FIXT1.1.xml
AppDataDictionary用于验证应用层消息的XML定义文件。仅对FIXT.1.1(或更高版本)的会话有效。更多信息请参考(FIX.4.0到 FIX.4.4)的DataDictionary。该配置可以为每个会话指定一个自定义应用的数据字典。该配置仅用于FIXT.1.1或更新的传输协议。使用FIXT传输时,该配置可以作为指定多个应用的数据字典的前缀。例如: DefaultApplVerID=FIX.4.2 # For default application version ID AppDataDictionary=FIX42.xml # For nondefault application version ID # Use BeginString suffix for app version AppDataDictionary.FIX.4.4=FIX44.xml有效的XML数据字典文件。QuickFIX/N 配备默认的协议字典数据:FIX50SP2.xml、FIX50SP1.xml、FIX50.xml、FIX44.xml、FIX43.xml、FIX42.xml、FIX41.xml、FIX40.xml
ValidateFieldsOutOfOrder如果设置为N,字段放置区域错误(例如,body字段在header区域内,或在header字段在body区域内)将不会被拒绝。用于连接字段要求不严格的系统。Y、NY
ValidateFieldsHaveValues如果设置为N,没有值的字段将不会被拒绝。用于连接到系统不当发送空标签。Y、NY
ValidateUserDefinedFields如果设置为N,用户自定义的字段将不会被拒绝,即使没有在数据字典中定义,或没出现在消息中。Y、NY


  • Initiator


配置描述有效值默认
ReconnectInterval尝试重新连接的时间间隔(秒)。仅用于 initiator。正整数30
HeartBtInt心跳间隔(秒)。仅用于initiator。正整数-
LogonTimeout登录超时时间间隔(秒)正整数10
LogoutTimeout注销登录超时时间间隔(秒)正整数2
SocketConnectPortSocket服务端口,用于建立会话。仅用于 initiator正整数-
SocketConnectHost连接主机.仅用于 initiatorx.x.x.x格式IP地址或域名-
SocketConnectPort一组备用Socket端口,用于连接会话的故障转移,n是正整数。SocketConnectPort1,SocketConnectPort2 … 必须是连续的,并有一个与之相匹配的数组SocketConnectHost正整数-
SocketConnectHost一组备用Socket服务主机,用于连接会话的故障转移,n是正整数。SocketConnectHost1, SocketConnectHost2… 必须是连续的,并有一个与之相匹配的数组SocketConnectPortx.x.x.x格式IP地址或域名-
SocketNodelay连接是否禁用Nagle算法。在[DEFAULT]配置节点定义。Y、NY
ReconnectInterval尝试重新连接的时间间隔(秒)。仅用于 initiator。正整数30


  • Acceptor


配置描述有效值默认
SocketAcceptPort监听接入连接Socket端口。仅用于acceptor正整数,有效的、开放的套接字端口-
SocketAcceptHost监听接入连接的Socket服务的主机。如果不提供,acceptor将监听所有网络端口(0.0.0.0)有效的x.x.x.x格式IP地址0.0.0.0
SocketNodelay连接是否禁用Nagle算法。在[DEFAULT]配置节点定义。Y、NY


  • Storage


配置描述有效值默认
PersistMessages如果设置为N,被不会保存消息。这样将迫使quickfix总是发送GapFills,而不是重新发送消息。如果你知道你永远不需要重新发送消息,使用此配置。有用的市场数据流。Y、NY


  • File Storage


配置描述有效值默认
FileStorePath存储序列号和消息的文件目录。有效的文件存储目录,必须有写入权限。-


  • Logging


配置描述有效值默认
FileLogPath存储日志的目录。有效的文件存储目录,必须有写入权限。-

FIX 开发

FIX 引擎

DEMO

  • Acceptor 配置文件


# 定义会话的默认配置(default节点)[DEFAULT]FileStorePath=storeFileLogPath=logConnectionType=acceptorReconnectInterval=60SenderCompID=SERVERResetOnDisconnect=YResetOnLogout=YResetOnLogon=Y
[SESSION]BeginString=FIX.4.2TargetCompID=CLIENTStartTime=00:00:00EndTime=23:59:59HeartBtInt=30SocketAcceptHost=127.0.0.1SocketAcceptPort=6666DataDictionary=FIX42.xml
复制代码


  • Initiator 配置文件


[DEFAULT]ConnectionType=initiatorReconnectInterval=60FileLogPath=logFileStorePath=storeStartTime=00:00:00EndTime=23:59:59HeartBtInt=30ResetOnDisconnect=YResetOnLogout=YResetOnLogon=Y
[SESSION]BeginString=FIX.4.2SenderCompID=CLIENTTargetCompID=SERVERSocketConnectPort=6666SocketConnectHost=127.0.0.1DataDictionary=FIX42.xml
复制代码


  • FixServer


package com.app.fix;
import quickfix.*;
/** * 服务启动主类(线程) */public class FixServer { private static ThreadedSocketAcceptor acceptor = null;
/** * 指定配置文件启动 * * @param propFile * @throws ConfigError * @throws FieldConvertError */ public FixServer(String propFile) throws ConfigError, FieldConvertError { // 设置配置文件 SessionSettings settings = new SessionSettings(propFile);
// 设置一个APPlication Application application = new FixServerApplication();
/** * * quickfix.MessageStore 有2种实现。 quickfix.JdbcStore,quickfix.FileStore . * JdbcStoreFactory 负责创建JdbcStore , FileStoreFactory 负责创建FileStorequickfix * 默认用文件存储,因为文件存储效率高。 */ MessageStoreFactory storeFactory = new FileStoreFactory(settings);
LogFactory logFactory = new FileLogFactory(settings);
MessageFactory messageFactory = new DefaultMessageFactory();
acceptor = new ThreadedSocketAcceptor(application, storeFactory, settings, logFactory, messageFactory);
}
private void startServer() throws RuntimeError, ConfigError { acceptor.start(); }
/** * 测试本地使用的main方法 * * @param args * @throws FieldConvertError * @throws ConfigError */ public static void main(String[] args) throws ConfigError, FieldConvertError { FixServer fixServer = new FixServer("res/acceptor.config"); fixServer.startServer(); }
}
复制代码


  • FixServerApplication


package com.app.fix;
import quickfix.Application;import quickfix.DoNotSend;import quickfix.FieldNotFound;import quickfix.IncorrectDataFormat;import quickfix.IncorrectTagValue;import quickfix.Message;import quickfix.MessageCracker;import quickfix.RejectLogon;import quickfix.Session;import quickfix.SessionID;import quickfix.UnsupportedMessageType;import quickfix.field.MsgType;
/** * */public class FixServerApplication extends MessageCracker implements Application { @Override protected void onMessage(Message message, SessionID sessionID) { try { String msgType = message.getHeader().getString(35); Session session = Session.lookupSession(sessionID); switch (msgType) { case MsgType.LOGON: // 登陆 session.logon(); session.sentLogon(); break; case MsgType.HEARTBEAT: // 心跳 session.generateHeartbeat(); break; }
} catch (FieldNotFound e) { e.printStackTrace(); }
}
@Override public void onCreate(SessionID sessionId) { System.out.println(" 服务器启动时候调用此方法创建");
}
@Override public void onLogon(SessionID sessionId) { System.out.println("客户端登陆成功时候调用此方法");
}
@Override public void onLogout(SessionID sessionId) { System.out.println("客户端断开连接时候调用此方法");
}
@Override public void toAdmin(Message message, SessionID sessionId) { System.out.println("发送会话消息时候调用此方法");
}
@Override public void toApp(Message message, SessionID sessionId) throws DoNotSend { System.out.println("发送业务消息时候调用此方法");
}
@Override public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon { System.out.println("接收会话类型消息时调用此方法"); try { crack(message, sessionId); } catch (UnsupportedMessageType | FieldNotFound | IncorrectTagValue e) { e.printStackTrace(); }
}
@Override public void fromApp(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { System.out.println("接收业务消息时调用此方法"); crack(message, sessionId);
}
}
复制代码


  • FixClient


package com.app.fix;
import quickfix.*;import quickfix.field.*;import quickfix.fix42.NewOrderSingle;
import java.io.FileNotFoundException;import java.util.Date;
public class FixClient implements Application {
private static volatile SessionID sessionID;
@Override public void onCreate(SessionID sessionID) { System.out.println("OnCreate"); }
@Override public void onLogon(SessionID sessionID) { System.out.println("OnLogon"); FixClient.sessionID = sessionID; }
@Override public void onLogout(SessionID sessionID) { System.out.println("OnLogout"); FixClient.sessionID = null; }
@Override public void toAdmin(Message message, SessionID sessionID) { System.out.println("ToAdmin"); }
@Override public void fromAdmin(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon { System.out.println("FromAdmin"); }
@Override public void toApp(Message message, SessionID sessionID) throws DoNotSend { System.out.println("ToApp: " + message); }
@Override public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { System.out.println("FromApp"); }
public static void main(String[] args) throws ConfigError, FileNotFoundException, InterruptedException, SessionNotFound { SessionSettings settings = new SessionSettings("res/initiator.config");
Application application = new FixClient(); MessageStoreFactory messageStoreFactory = new FileStoreFactory(settings); LogFactory logFactory = new ScreenLogFactory(true, true, true); MessageFactory messageFactory = new DefaultMessageFactory();
Initiator initiator = new SocketInitiator(application, messageStoreFactory, settings, logFactory, messageFactory); initiator.start();
while (sessionID == null) { Thread.sleep(1000); }
final String orderId = "342"; NewOrderSingle newOrder = new NewOrderSingle(new ClOrdID(orderId), new HandlInst('1'), new Symbol("YRD"), new Side(Side.BUY), new TransactTime(new Date()), new OrdType(OrdType.MARKET)); Session.sendToTarget(newOrder, sessionID); Thread.sleep(5000); }}
复制代码


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/186


2020-02-13 21:45804

评论

发布
暂无评论
发现更多内容

搞懂 ZooKeeper 集群的数据同步

HelloGitHub

Java zookeeper ZooKeeper原理

Datadog 能成为最大的云监控厂商吗

睿象云

运维 运维平台 Datadog 云监控

区块链中药溯源--区块链为中医药溯源认证

13530558032

QCon全球软件开发大会:推动创新,实现技术落地

博文视点Broadview

区块链BaaS应用平台搭建,助力企业运用区块链解决业务问题

13828808769

区块链 区块链+ 区块链发展 #区块链#

推荐 2 款必备的 Django 开发神器

星安果

Python django Web 后端

主数据建设的挑战与发展

EAWorld

镜像仓库学习笔记

lenka

3月日更

Gas费用持续攀升!NA公链NAC公链如何破解高额Gas费用的困局?

区块链第一资讯

​Autonomous Dream Works的独创力杰作EGGNetwork EFTalk

币圈那点事

电子证照上链--助推智慧政务

13530558032

Rust从0到1-基础概念-数据类型

rust 数据类型

一段java代码执行旅程

华为云开发者联盟

JVM class 指令 java代码 java栈

如何正确使用Python临时文件

华为云开发者联盟

Python 安全 临时文件 tempfile 库函数

能源绿色管控:天然气站启动数字化转型,工业企业该如何突围?

一只数据鲸鱼

物联网 数据可视化 智慧城市 能源管理 天然气

设计与思考,关于资源和生命周期

程序员架构进阶

设计实践 生命周期 28天写作 3月日更 池化技术

网络连接之协议栈

Kylin

协议栈 3月日更 21天挑战 网络连接

【LeetCode】删除排序链表中的重复元素 IIJava题解

Albert

算法 LeetCode 3月日更

区块链六大应用场景,推动政府信息化发展

13828808769

区块链+ #区块链#

通俗讲解分布式锁,看完不懂算我输

Java小咖秀

Java 分布式 多线程 并发

Python基础之:Python中的模块

程序那些事

Python Python3 程序那些事

华为云PB级数据库GaussDB(for Redis)揭秘第六期:Feed流场景中的应用

华为云开发者联盟

数据库 redis 华为云 GaussDB Feed流

智慧公安信息化管理系统,重点人员管控系统的搭建

13828808769

智慧交通

困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

不脱发的程序猿

28天写作 硬件设计 嵌入式软件 单片机 3月日更

异步机制和CPU架构对 Redis 性能的影响

escray

redis 学习 极客时间 3月日更 Redis 核心技术与实战

Worktile 前端工程化之路

PingCode研发中心

大前端

分布式锁的实现方案

360技术

初识Golang之声明函数

Kylin

3月日更 21天挑战 Go 语言

基于深度学习的两种信源信道联合编码

华为云开发者联盟

深度学习 通信 编码 信源编码 信道编码

Golang号称最快的Json解析器速度可达5623ns/op

happlyfox

学习 3月日更 Go 语言

低代码是什么?低代码价值主要体现在哪?

优秀

低代码

FIX协议介绍_文化 & 方法_姜永念_InfoQ精选文章