详解FIX协议的原理消息格式及配置开发.docx
- 文档编号:14099396
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:28
- 大小:1.62MB
详解FIX协议的原理消息格式及配置开发.docx
《详解FIX协议的原理消息格式及配置开发.docx》由会员分享,可在线阅读,更多相关《详解FIX协议的原理消息格式及配置开发.docx(28页珍藏版)》请在冰点文库上搜索。
详解FIX协议的原理消息格式及配置开发
详解FIX协议的原理、消息格式及配置开发
一、定义
FIX协议是由国际FIX协会组织提供的一个开放式协议,目的是推动国际贸易电子化的进程,在各类参与者之间,包括投资经理、经纪人,买方、卖方建立起实时的电子化通讯协议。
FIX协议的目标是把各类证券金融业务需求流程格式化,使之成为一个个可用计算机语言描述的功能流程,并在每个业务功能接口上统一交换格式,方便各个功能模块的连接。
二、协议工作原理
2.1通信模型及基本概念
通信模型
·Initiator:
发起者,建立通信连路,通过发送初始Logon消息发起会话的参与方。
·Acceptor:
接收方FIX会话的接收方。
负责执行第一层次的认证和通过传输Logon消息的确认正式声明连接请求被接受。
·原则:
先发起者为Initiator,接受者为Acceptor。
·标准模式以网关为Acceptor,客户端为Initiator做为常用模式。
Fixconnection
FIX连接由3部分组成:
logon登录,messageexchange消息传输,logout注销。
logon登录
logout注销
Fixsession
FIX会话由一个或多个FIXConnectionFIX连接组成。
一个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=208
1、消息长度:
9=73
35=A34=149=CLIENT52=20181119-10:
42:
48.76856=SERVER98=0108=30141=Y(这段长度)
2、效验码检查
char*GenerateCheckSum(char*buf,longbufLen){
staticchartmpBuf[4];longidx;
unsignedintcks;
for(idx=0L,cks=0;idx return(tmpBuf); } 消息确认 ·FIX协议不支持单个消息的确认。 采用的是监控消息时隙的方法来进行消息恢复和验证。 ·普通的数据传送(无单个消息确认)通过消息序列间隙进行错误识别。 每个消息由一个唯一的序列号进行标示。 接收端应用程序负责监控接收消息序列号以识别消息间隙并产生重传请求。 ·每个FIX参与方必须为FIX会话维护两个序列号,一个是接收序列号,一个是发送序列号,两者都在建立FIX会话开始时初始化为1。 每个消息被赋予一个唯一的序列号值,并在消息发送后递增。 此外,每个收到的消息都有一个唯一的序列号,接收序列号计数器在收到每个消息后将会被递增。 ·当接收序列号与所希望得到的的正确序列号不必配时,必须采取纠错处理。 加密 ·加密算法由连接双方共同协商。 ·一个消息的任何一个域可以被加密并放在SecureData域中。 然而,一些显示的标志域必须采用明文进行传输。 为确保完整性,明文域可以在SecureData域中重复。 ·当使用加密时,建议但不是必须,所有的消息体都进行加密。 如果一个消息中的重复组数据中的部分数据要加密,这个重复组必须全部进行加密。 ·预先协商好的加密算法在Logon消息中进行声明。 自定义域 ·FIX为给用户提供最大的灵活性,FIX协议允许用户自定义域。 这些域在认同的参与者之间实现、应用,并且应注意避免冲突。 ·Tag数在5000到9999保留用于用户自定义域。 这些tag值用于企业联盟的信息交换。 可以通过FIX网站进行注册。 ·10000以上保留用于单一企业内部使用。 不用注册。 三、消息格式 3.1数据类型 整数int,浮点数float,单个字符char,布尔Boolean,字符串String,数据data 3.2域 常见域 域语法 ·开始部分应是消息头,随后是正文,最后是消息尾; ·消息头的前3个域的次序不能改变: 起始串(Tag=8)、消息体长度(Tag=9)、消息类型(Tag=35); ·消息尾的最后一个域应是校验和域(Tag=10); ·重复组中,域出现的顺序应遵循该重复组在消息或组件中定义时的次序; ·在一条消息中,除重复组域外任何其他域不能重复出现。 安全与加密 ·由于消息有可能在公网或不安全的网络上传输交换,因此需要对相关的敏感数据加密处理。 ·具体加密的方法由连接双方达成的协议而定。 ·消息内除某些需要公开识别的域以明文传输外其他任何域都可以加密放置密文数据域(SecureData)内。 当然,这些被加密的域也可以同时保留明文的表示方式。 ·当决定使用加密方案时,可以对消息正文内所有的域加密。 如果消息的重复组内有部分需要加密的,那么要求对整个重复组加密。 ·本协议还提供的一些域用以支持数字签名、密钥交换和正文加密等安全技术。 3.3消息 消息头 每一个会话或应用消息有一个消息头,该消息头指明消息类型、消息体长度、发送目的地、消息序号、发送起始点和发送时间。 消息尾 每一个消息(会话或应用消息)有一个消息尾,并以此终止。 消息尾可用于分隔多个消息,包含有3位数的校验和值。 新订单消息(MsgType=D) 对于在消息头中设置了PossResend标志的订单消息,应当使用交易客户方订单编号(ClOrdID)核实是否已收到该订单,具体实现时还应检查订单参数(买卖方向、证券代码、数量等)进行核实。 如果之前收到该订单,应以执行报告消息回应订单状态。 如果之前未收到,则以执行报告消息回应订单确认。 执行报告消息(MsgType=8) ·订单确认 ·订单状态变化确认(如撤单确认) ·发送订单的成交回报 ·订单拒绝 订单状态请求消息(MsgType=H) 订单状态请求用于向交易服务方请求某订单的状态,交易服务方通过执行报告消息返回订单状态。 撤单消息(MsgType=F) 撤单消息用以撤消订单的全部订单剩余数量。 撤单消息也被赋予一个ClOrdID,可视作另外一个订单。 如果被拒绝,撤单拒绝消息的ClOrdID放置撤单消息的ClOrdID,而原始订单的ClOrdID则放入OrigClOrdID域。 ClOrdID要保证唯一。 撤单拒绝消息(MsgType=9) 本消息用于撤单消息的拒绝。 交易服务方接收到撤单发现无法执行(已成交订单不可更改等),将发送撤单拒绝。 拒绝撤单时,撤单拒绝消息应用ClOrdID指示撤单的ClOrdID,用OrigClOrdID指示之前最后接受的订单(除非拒绝原因是“未知订单”)。 四、FIX配置 4.1 会话配置(SESSION) 4.2验证配置 4.3Initiator 4.4Acceptor 4.5Storage 4.6FileStorage 4.7Logging 五、FIX开发 5.1FIX引擎 官网: FIX引擎(http: //www.quickfixengine.org/) github: QFJGitHubRepository( 5.2DEMO Acceptor配置文件 #定义会话的默认配置(default节点) [DEFAULT] FileStorePath=store FileLogPath=log ConnectionType=acceptor ReconnectInterval=60 SenderCompID=SERVER ResetOnDisconnect=Y ResetOnLogout=Y ResetOnLogon=Y [SESSION] BeginString=FIX.4.2 TargetCompID=CLIENT StartTime=00: 00: 00 EndTime=23: 59: 59 HeartBtInt=30 SocketAcceptHost=127.0.0.1 SocketAcceptPort=6666 DataDictionary=FIX42.xml Initiator配置文件 [DEFAULT] ConnectionType=initiator ReconnectInterval=60 FileLogPath=log FileStorePath=store StartTime=00: 00: 00 EndTime=23: 59: 59 HeartBtInt=30 ResetOnDisconnect=Y ResetOnLogout=Y ResetOnLogon=Y [SESSION] BeginString=FIX.4.2 SenderCompID=CLIENT TargetCompID=SERVER SocketConnectPort=6666 SocketConnectHost=127.0.0.1 DataDictionary=FIX42.xml FixServer packagecom.app.fix; importquickfix.*; /** *服务启动主类(线程) */ publicclassFixServer{ privatestaticThreadedSocketAcceptoracceptor=null; /** *指定配置文件启动 * *@parampropFile *@throwsConfigError *@throwsFieldConvertError */ publicFixServer(StringpropFile)throwsConfigError,FieldConvertError{ //设置配置文件 SessionSettingssettings=newSessionSettings(propFile); //设置一个APPlication Applicationapplication=newFixServerApplication(); /** * *quickfix.MessageStore有2种实现。 quickfix.JdbcStore,quickfix.FileStore. *JdbcStoreFactory负责创建JdbcStore,FileStoreFactory负责创建FileStorequickfix *默认用文件存储,因为文件存储效率高。 */ MessageStoreFactorystoreFactory=newFileStoreFactory(settings); LogFactorylogFactory=newFileLogFactory(settings); MessageFactorymessageFactory=newDefaultMessageFactory(); acceptor=newThreadedSocketAcceptor(application,storeFactory,settings,logFactory,messageFactory); } privatevoidstartServer()throwsRuntimeError,ConfigError{ acceptor.start(); } /** *测试本地使用的main方法 * *@paramargs *@throwsFieldConvertError *@throwsConfigError */ publicstaticvoidmain(String[]args)throwsConfigError,FieldConvertError{ FixServerfixServer=newFixServer("res/acceptor.config"); fixServer.startServer(); } } FixServerApplication packagecom.app.fix; importquickfix.Application; importquickfix.DoNotSend; importquickfix.FieldNotFound; importquickfix.IncorrectDataFormat; importquickfix.IncorrectTagValue; importquickfix.Message; importquickfix.MessageCracker; importquickfix.RejectLogon; importquickfix.Session; importquickfix.SessionID; importquickfix.UnsupportedMessageType; importquickfix.field.MsgType; /** * */ publicclassFixServerApplicationextendsMessageCrackerimplementsApplication{ @Override protectedvoidonMessage(Messagemessage,SessionIDsessionID){ try{ StringmsgType=message.getHeader().getString(35); Sessionsession=Session.lookupSession(sessionID); switch(msgType){ caseMsgType.LOGON: //登陆 session.logon(); session.sentLogon(); break; caseMsgType.HEARTBEAT: //心跳 session.generateHeartbeat(); break; } }catch(FieldNotFounde){ e.printStackTrace(); } } @Override publicvoidonCreate(SessionIDsessionId){ System.out.println("服务器启动时候调用此方法创建"); } @Override publicvoidonLogon(SessionIDsessionId){ System.out.println("客户端登陆成功时候调用此方法"); } @Override publicvoidonLogout(SessionIDsessionId){ System.out.println("客户端断开连接时候调用此方法"); } @Override publicvoidtoAdmin(Messagemessage,SessionIDsessionId){ System.out.println("发送会话消息时候调用此方法"); } @Override publicvoidtoApp(Messagemessage,SessionIDsessionId)throwsDoNotSend{ System.out.println("发送业务消息时候调用此方法"); } @Override publicvoidfromAdmin(Messagemessage,SessionIDsessionId) throwsFieldNotFound,IncorrectDataFormat,IncorrectTagValue,RejectLogon{ System.out.println("接收会话类型消息时调用此方法"); try{ crack(message,sessionId); }catch(UnsupportedMessageType|FieldNotFound|IncorrectTagValuee){ e.printStackTrace(); } } @Override publicvoidfromApp(Messagemessage,SessionIDsessionId) throwsFieldNotFound,IncorrectDataFormat,IncorrectTagValue,UnsupportedMessageType{ System.out.println("接收业务消息时调用此方法"); crack(message,sessionId); } } FixClient packagecom.app.fix; importquickfix.*; importquickfix.field.*; importquickfix.fix42.NewOrderSingle; importjava.io.FileNotFoundException; importjava.util.Date; publicclassFixClientimplementsApplication{ privatestaticvolatileSessionIDsessionID; @Override publicvoidonCreate(SessionIDsessionID){ System.out.println("OnCreate"); } @Override publicvoidonLogon(SessionIDsessionID){ System.out.println("OnLogon"); FixClient.sessionID=sessionID; } @Override publicvoidonLogout(SessionIDsessionID){ System.out.println("OnLogout"); FixClient.sessionID=null; } @Override publicvoidtoAdmin(Messagemessage,SessionIDsessionID){ System.out.println("ToAdmin"); } @Override publicvoidfromAdmin(Messagemessage,SessionIDsessionID)throwsFieldNotFound,IncorrectDataFormat,IncorrectTagValue,RejectLogon{ System.out.println("FromAdmin"); } @Override publicvoidtoApp(Messagemessage,SessionIDsessionID)throwsDoNotSend{ System.out.println("ToApp: "+message); } @Override publicvoidfromApp(Messagemessage,SessionIDsessionID)throwsFieldNotFound,IncorrectDataFormat,IncorrectTagValue,UnsupportedMessageType{ System.out.println("FromApp"); } publicstaticvoidmain(String[]args)throwsConfigError,FileNotFoundException,InterruptedException,SessionNotFound{ SessionSettingssettings=newSessionSettings("res/initiator.config"); Applicationapplication=newFixClient(); MessageStoreFactorymessageStoreFactory=newFileStoreFactory(settings); LogFactorylogFactory=newScreenLogFactory(true,true,true); MessageFactorymessageFactory=newDefaultMessageFactory(); Initiatorinitiator=ne
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详解 FIX 协议 原理 消息 格式 配置 开发