FixAlchemy.Parser (FIXAlchemy v0.3.0)
View SourceFIX protocol framing and decoding built on binary pattern matching.
parse/2 extracts complete messages from a TCP buffer using the declared
BodyLength (tag 9), returning each message as a zero-copy sub-binary of the
original wire bytes. Framing is verified against the checksum trailer
position: a message whose BodyLength does not land on 10= is treated as
garbled and skipped, resynchronizing on the next 8=FIX header, per the FIX
session protocol's garbled-message rule.
FIX Version Support
Any begin string starting with FIX is accepted: FIX.4.x, FIXT.1.1
(the wire begin string for FIX 5.0+), and vendor variants.
Limits
BodyLength is accepted up to 10 digits, capped at 100MB per message. Anything beyond that is treated as garbled data.
Examples
iex> FixAlchemy.Parser.init()
iex> {buffer, messages} = FixAlchemy.Parser.parse(data)
iex> message_map = FixAlchemy.Parser.process_message(Enum.at(messages, 0), spec_name)
Summary
Functions
Calculate checksum for a FIX message body.
Validate a framed FIX message against its checksum trailer.
Cleanup is no longer needed with generated modules.
Extract just the MsgType (tag 35) from a raw FIX message via binary scan.
Initialize generated parser modules from the session's FIX dictionaries.
Parse FIX message data from a buffer.
Convert a raw FIX message to a structured map using generated parsers.
Split a raw FIX message into {tag, value} string pairs.
Functions
Calculate checksum for a FIX message body.
Sums raw bytes modulo 256 and returns a 3-digit zero-padded string.
Validate a framed FIX message against its checksum trailer.
The checksum is the byte sum modulo 256 of every byte before the 10=
trailer, per the FIX specification.
@spec cleanup(term()) :: :ok
Cleanup is no longer needed with generated modules.
Generated modules are compiled .beam files that persist across sessions. This function is kept for backward compatibility but does nothing.
Extract just the MsgType (tag 35) from a raw FIX message via binary scan.
Avoids full field decoding — intended for fast routing decisions. Returns the msg_type string or nil if not found.
Examples
iex> FixAlchemy.Parser.extract_msg_type("8=FIX.4.4" <> <<1>> <> "9=5" <> <<1>> <> "35=A" <> <<1>> <> "10=000" <> <<1>>)
"A"
Initialize generated parser modules from the session's FIX dictionaries.
Parses the dictionary XML and generates the modules used for field and
message type lookups. A FIX 5.0 or later session splits its dictionary in
two: :spec_file is then the FIXT transport dictionary, which defines the
session layer only, and :app_spec_file the application dictionary that
defines the business messages. Both are generated into one module set, the
transport dictionary defining the session layer and the application
dictionary everything else.
Dictionaries belong to the session that uses them, not to the application, so connections to venues speaking different dialects run side by side.
Options
:spec_file- Path to the FIX dictionary XML. Required.:app_spec_file- Path to the application dictionary XML, required when:spec_fileis a FIXT transport dictionary.
Returns
{spec_name, modules}- Spec name for lookups and generated modules
Raises
- Raises if no dictionary is configured, if a configured file is missing, or if parsing fails
Examples
iex> {spec_name, modules} = FixAlchemy.Parser.init(spec_file: "FIX44.xml")
iex> {spec_name, modules} =
...> FixAlchemy.Parser.init(spec_file: "FIXT1.1.xml", app_spec_file: "FIX50SP2.xml")
Parse FIX message data from a buffer.
Returns a tuple of {remaining_buffer, [complete_messages]}. Messages are
returned as raw binaries, byte-identical to the wire data. Garbled data is
skipped. Use process_message/2 to decode a message and checksum_valid?/1
to validate one.
Examples
iex> FixAlchemy.Parser.parse(data)
{"", ["8=FIX.4.4|9=...|10=123|"]}
Convert a raw FIX message to a structured map using generated parsers.
Uses generated modules from the spec for:
- Field name resolution (Fields module)
- Message structure parsing (Messages module)
- Repeating group handling (Groups module)
Unknown tags are kept under their tag string (e.g. "9999"), known tags
under their spec-derived atom name.
Parameters
message- Raw FIX message binaryspec_name- Spec name from init/1 (e.g., "fix44")
Examples
iex> Parser.process_message(msg, "fix44")
%{
raw: <<...>>,
msg_type: "X",
symbol: "EUR/USD",
no_md_entries: [
%{md_entry_type: "0", md_entry_px: "1.0828"},
%{md_entry_type: "1", md_entry_px: "1.0829"}
]
}
Split a raw FIX message into {tag, value} string pairs.
Tolerant of malformed segments: chunks without a = are skipped. Intended
for fast handlers that read a few raw tags without full spec decoding.
Examples
iex> FixAlchemy.Parser.split_fields("55=EUR/USD" <> <<1>> <> "270=1.0828" <> <<1>>)
[{"55", "EUR/USD"}, {"270", "1.0828"}]