本系列导航
FIX 协议开发(1):协议介绍及开发方案(本文)
FIX 协议开发(2):QuickFIX/J 入门
FIX 协议开发(3):QuickFIX/J 实战经验小结
本文背景
公司因业务需要,准备接入 FIX 协议。在调研过程中,我发现中文的 FIX 协议相关资料不太多,准备边学边记录,预计会写 3 篇左右。
FIX 协议简介
FIX(Financial Information eXchange Protocol,金融信息交换协议)是由国际FIX协会组织提供的一个开放式协议,目的是推动国际贸易电子化进程,在各类参与者之间,包括投资经理、经纪人、买方、卖方建立起实时的电子化通讯协议。
FIX协议的目标是把各类证券金融业务需求流程格式化,成为一个可用计算机语言描述的功能流程,并在每个业务功能接口上统一交换格式,方便各个功能模块的连接。
消息格式
FIX 协议消息均由多个 “key=value” 组成。其中 key 可以是协议规定的字段,或自定义字段。协议规定的key可查询 FIX 协议字典,【不同版本的 FIX 协议均有其字典,用于开发的库一般也有自带;也可参考第三方,如 wireshark】例如 8 代表 begin string,34 代表消息的序列号,52 代表时间戳等。自定义字段不与规定的 key 重复,供金融机构定制,开发时需要向对应金融机构获取其专有字段的字典。只要有了对应的字典,就可以读懂 FIX 数据包的内容。
一般来说,一个 消息由“头部 + 消息体 + 尾部”构成。头部包含一些必要的字段,例如 BeginString (8)、BodyLength (9)、MsgType (35)、MsgSeqNum (34)、SenderCompID (49) 等,尾部包含的必要字段是 CheckSum (10)。
FIX 登陆消息示例(假设”^”是分隔符):
8=FIX.4.3^9=65^35=A^34=1^49=TESTACC^52=20130703-15:55:08.609^56=EXEC^98=0^108=30^10=225^
对照字典可知,BeginString (8) 是 FIX.4.3;BodyLength (9) 是 65 字节;MsgType (35) 是 A,A 对应 logon 操作;MsgSeqNum (34) 是 1,即这是我方发送的第 1 个消息。
有关更详细的协议介绍,可参考 https://blog.51cto.com/9291927/2536105
开发方案
不使用库
由上面的示例可以发现,FIX 协议十分简单。可以不需要依赖第三方库,手动查字典构造消息8=FIX.4.3^9=65^35=A^34=1<省略>
再通过标准的 socket 通信,即可完成交互。
这个方案自由度最高,不依赖底层开发语言,但开发流程与查字典较为繁琐,后续维护也不太方便。
Python 库 simplefix
simplefix 是一个 FIX 协议的简易实现。它使用户可以方便地任意构造 FIX 消息,非常适合学习、测试协议。但这个库不包含任何网络收发、FIX 异常处理等功能模块。因此,开发 FIX 客户端时,我使用该库构造数据包,然后通过标准 socket 发送,再分析其网络底层交互。
示例:发送 logon 消息的代码
import socket import time import simplefix from simplefix.constants import (ENCRYPTMETHOD_NONE, MSGTYPE_LOGON, TAG_BEGINSTRING, TAG_CLIENTID, TAG_ENCRYPTMETHOD, TAG_HEARTBTINT, TAG_MSGSEQNUM, TAG_MSGTYPE, TAG_SENDER_COMPID, TAG_SENDING_TIME, TAG_TARGET_COMPID) HOST = '1.2.3.45' PORT = 9000 CLIENT_ID = 12345678 PASSWORD = 'mypassword' seq_num = 1 # 需维护msg sequence number,每次发送后加1 if __name__ == "__main__": sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # 长连接 sock.connect((HOST, PORT)) # logon msg_logon = simplefix.FixMessage() msg_logon.append_pair(TAG_BEGINSTRING, 'FIX.4.2') msg_logon.append_pair(TAG_MSGSEQNUM, seq_num) # 需维护msg sequence number,每次发送后加1 msg_logon.append_pair(TAG_SENDER_COMPID, 'FIXTEST001') msg_logon.append_utc_timestamp(TAG_SENDING_TIME) msg_logon.append_pair(TAG_TARGET_COMPID, 'TESTENV') msg_logon.append_pair(TAG_MSGTYPE, MSGTYPE_LOGON) # 类型 msg_logon.append_pair(TAG_ENCRYPTMETHOD, ENCRYPTMETHOD_NONE) msg_logon.append_pair(TAG_HEARTBTINT, 30) msg_logon_buffer = msg_logon.encode() sock.send(msg_logon_buffer) print('seq', seq_num, 'sent') seq_num += 1 time.sleep(1) sock.close()
多平台 QuickFix 引擎
QuickFix 是全功能的 FIX 开源引擎,目前很多 Fix 解决方案都是根据或参考 QuickFix 实现的。目前(2020年10月)它有 C++、Python、Java、.NET、Go 和 Ruby 共 6 种语言的实现/接口。
根据我司的情况,选择其中的 Java 实现 QuickFIX/J 进行下一步开发。其使用方法,将在下一篇文章继续。
发表评论