[Banking-pm] Parsing FIX messages

Holzman, Benjamin BHolzman at ise.com
Wed Dec 19 06:38:58 PST 2007


banking-pm-bounces+bholzman=iseoptions.com at pm.org wrote:
> Does anyone know if a module is available for parsing FIX
> messages? I didnt see any on cpan just wondering if anyone
> here did one internally?

Here's what I posted the last time this came up:

	> I would have assumed that FIX is so large that any generic 
	> implementation of it is likely to be incomplete.
	
	Yes and no, I think.  My experience with FIX has been that the
	application-level messages tend to be domain-specific, but the
	protocol-level is quite stable.  I have built FIX interfaces to
allow 
	order entry and market data for our parimutuel matching engine.
I did
	it using the quickfix open source FIX engine (actually C++
libraries) to
	handle the protocol and wrote a minimal C++ bridge that shuttles
FIX 
	application messages back and forth to a perl process over a
socket.
	
	I then parse the FIX messages in perl with a custom FixMessage
base
	class, run all of my application logic there, creating
FixMessage
	objects as responses and then turn them back into a string to
send back 
	to the C++ bridge.  I store the FIX messages as a hash mapping
the fix
	tag number to the value.  I then have accessor methods named
after the
	mnemonic for each tag number.  I actually just have a hash
(%tagMapping) 
	in my base class with the mapping and use an AUTOLOAD to create
the
	accessors on demand.  Parsing the FIX message is as simple as
this code:
	
	
	    sub fromString {
	        my $string = shift;
	
	        my($class, %tags); 
	        foreach my $field (split /\001/, $string) {
	          my($tag, $value) = split /=/, $field, 2;
	          if ($tag == $tagMapping{'MsgType'}) {
	            $class = $msgType_2_class{$value};
	            next; 
	          }
	
	          next if defined $isHeaderTag{$tag};
	
	          $tags{$tag} = $value;
	        }
	
	        return $class->new(\%tags);
	    }
	
	I have sub-classes of FixMessage for each MsgType that I handle;
the 
	%msgType_2_class hash has the mapping.
	
	Actually, there's an additional complication to handle repeating
groups;
	the value of a repeating group is an array ref with one element
for each
	instance of the group; because tag order in repeating groups
matters, 
	each instance is represented with an array consisting of tag
	number/value pairs.  Something like this: [ [ 42 => 'value', 165
=>
	'another value' ], [ 42 => 'value2', 165 => 'yet another' ], ...
].  So 
	my actual fromString function has more logic to handle this.
	
	Anyway, converting an object back to a string isn't too hard;
the only
	tricky parts are including the body length in the header and
computing
	the checksum for the trailer.  My code looks like this: 
	
	    sub toString {
	        my $this = shift;
	
	        my $header = "8=FIX.4.4\0019=";
	        my $body = join("\001", "35=$class_2_msgType{ref
$this}",
	                         map _toString($_, $this->{$_}), keys
%$this) . 
	"\001";
	
	        my $msg = $header . length($body) . "\001$body";
	
	        my $cksum = 0;
	        $cksum += ord($_) for split //, $msg;
	
	        $cksum = sprintf "%03d", $cksum %256; 
	
	        return $msg . "10=$cksum\001";
	    }
	
	    sub _toString {
	        my($key, $value) = @_;
	        if (ref $value eq 'ARRAY') {
	          return unless @$value;
	
	          return join "\001", 
	                        "$key=" . @$value,
	                        map { my $val = $_;
	                                my @data;
	                                for (my $i = 0; $i < $#$val;
$i+=2) { 
	                                  push @data,
"$tagMapping{$val->[$i]}="
	.
	                                                  $val->[$i +
1];
	                                }
	                                @data; 
	                            } @$value;
	        } elsif ($value ne '') {
	          return "$key=$value";
	        } else {
	          return;
	        }
	    }
	
	That's pretty much my whole FIX message base class.  The
constructor 
	allows objects to be constructed from a string or from tag
mnemonic =>
	value pairs.
	
	I don't know if this helps you, but at least you see how simple
it is to
	handle parsing and generation of FIX messages. 
	
	Benjamin Holzman


More information about the Banking-pm mailing list