#data-stream #fix #protocols #data-encoding #performance #financial-data #parser

fastlib

FAST (FIX Adapted for STreaming protocol) 是一种用于面向消息的数据流的节省空间和处理效率的编码方法

5个不稳定版本

0.3.1 2024年7月29日
0.3.0 2024年7月23日
0.2.1 2024年7月11日
0.2.0 2024年7月6日
0.1.0 2024年7月3日

#431解析器实现

Download history 89/week @ 2024-06-28 202/week @ 2024-07-05 76/week @ 2024-07-12 98/week @ 2024-07-19 192/week @ 2024-07-26 19/week @ 2024-08-02

每月443次下载

MIT 协议

325KB
8K SLoC

FIX/FAST协议解码器/编码器

Crates.io Build Status License

FAST (FIX ASTreaming protocol) 是一种用于面向消息的数据流的节省空间和处理效率的编码方法。

FAST协议是作为FIX市场数据优化工作组的一部分开发的。FAST数据压缩算法旨在优化金融数据的电子交换,尤其是针对高容量、低延迟的数据分发。它显著降低了发送者和接收者之间的带宽需求和延迟。FAST在高峰消息率期间尤其擅长提高性能。

技术规范: https://www.fixtrading.org/standards/fast-online/
支持版本: 1.x.1

使用方法

添加到您的 Cargo.toml

[dependencies]
fastlib = "0.3"

使用serde序列化/反序列化

例如,对于在XML中定义的模板:

<?xml version="1.0" encoding="UTF-8" ?>
<templates xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
    <template name="MsgHeader">
        <uInt32 id="34" name="MsgSeqNum"/>
        <uInt64 id="52" name="SendingTime"/>
    </template>
    <template id="1" name="MDHeartbeat">
        <templateRef name="MsgHeader"/>
    </template>
    <template id="2" name="MDLogout">
        <templateRef name="MsgHeader"/>
        <string id="58" name="Text" presence="optional"/>
    </template>
</templates>

在Rust中定义消息类型

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
enum Message {
    MDHeartbeat(Heartbeat),
    MDLogout(Logout),
}

#[derive(Serialize, Deserialize)]
struct MsgHeader {
    #[serde(rename = "MsgSeqNum")]
    msg_seq_num: u32,
    #[serde(rename = "SendingTime")]
    sending_time: u64,
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Heartbeat {
    #[serde(flatten)]
    msg_header: MsgHeader,
}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct Logout {
    #[serde(flatten)]
    msg_header: MsgHeader,
    text: Option<String>,
}

一些实现指南

  • <templates> 必须实现为 enum;
  • <decimal> 可以反序列化为 f64fastlib::Decimal (如果需要保留原始缩放比例);
  • <byteVector> 是一个 Vec<u8>,并且必须以 #[serde(with = "serde_bytes")] 前缀;
  • <sequence> 是一个 Vec<SequenceItem>,其中 SequenceItem 是一个 struct
  • <group> 是一个嵌套的 struct
  • 可选存在的字段是 Option<...>
  • 静态模板引用可以是模板的普通字段或展平的 struct
  • 动态模板引用必须是带有 #[serde(rename = "templateRef:N")]Box<Message>,其中 N 是其组中 <templateRef> 的0基于索引。

要反序列化消息,请调用 fastlib::from_vecfastlib::from_bytesfrom_stream

use fastlib::Decoder;

// Create a decoder from XML templates.
let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;

// Raw data that contains one message.
let raw_data: Vec<u8> = vec![ ... ];

// Deserialize a message.
let msg: Message = fastlib::from_vec(&mut decoder, raw_data)?;

要序列化消息,请调用 fastlib::to_vecfastlib::to_bytesto_stream

use fastlib::Encoder;

// Create a encoder from XML templates.
let mut encoder = Encoder::new_from_xml(include_str!("templates.xml"))?;

// Message to serialize.
let msg = Message::MDHeartbeat{
    Heartbeat {
        ...
    }
};

// Serialize a message.
let raw: Vec<u8> = fastlib::to_vec(&mut encoder, &msg)?;

解码为JSON;

use fastlib::Decoder;
use fastlib::JsonMessageFactory;

// Create a decoder from XML templates.
let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;

// Raw data that contains one message.
let raw_data: Vec<u8> = vec![ ... ];

// Create a JSON message factory.
let mut msg = JsonMessageFactory::new();

// Decode the message.
decoder.decode_vec(raw_data, &mut msg)?;

println!("{}", msg.json);

使用自己的消息工厂解码;

创建一个新的实现 fastlib::MessageFactory 特性的结构体;

use fastlib::{MessageFactory, Value};

pub struct MyMessageFactory {
}

impl MessageFactory for MyMessageFactory {
    // ... your implementation here ...
}

您必须实现消息解码期间将被调用的回调函数;

pub trait MessageFactory {
    // Process template id
    fn start_template(&mut self, id: u32, name: &str);
    fn stop_template(&mut self);
    
    // Process field value
    fn set_value(&mut self, id: u32, name: &str, value: Option<Value>);
    
    // Process sequence
    fn start_sequence(&mut self, id: u32, name: &str, length: u32);
    fn start_sequence_item(&mut self, index: u32);
    fn stop_sequence_item(&mut self);
    fn stop_sequence(&mut self);
    
    // Process group
    fn start_group(&mut self, name: &str);
    fn stop_group(&mut self);
    
    // Process template ref
    fn start_template_ref(&mut self, name: &str, dynamic: bool);
    fn stop_template_ref(&mut self);
}

有关示例,请参阅 fastlib::text::TextMessageFactoryfastlib::text::JsonMessageFactory 的实现,但更有可能的是,您将想要构建自己的消息结构体;

然后从模板XML文件创建解码器并解码消息;

use fastlib::Decoder;

// Create a decoder from XML templates.
let mut decoder = Decoder::new_from_xml(include_str!("templates.xml"))?;

// Raw data that contains one message.
let raw_data: Vec<u8> = vec![ ... ];

// Create a message factory.
let mut msg = MyMessageFactory{};

// Decode the message.
decoder.decode_vec(raw_data, &mut msg)?;

示例

许可证

本项目受MIT许可证许可;

依赖项

~2–3MB
~50K SLoC