NAME
FIX::Lite - Simple FIX (Financial Information eXchange) protocol module
VERSION
Version 0.05
SYNOPSIS
use FIX::Lite; my $fix = FIX::Lite->new( Host => 'somefixserver.com', Port => 5201, Debug => 0, Timeout => 60 ) or die "Cannot connect to server: $!";
# Then we usually need to login
$fix->logon( SenderCompID => 'somevalue1', TargetCompID => 'somevalue2', TargetSubID => 'somevalue3', Username => 'somevalue4', Password => 'somevalue5', Debug => 0 );
# To check the login results we can use method loggedIn()
die "Cannot logon: $!" unless $fix->loggedIn()
# After logon we can make some market request
$fix->request( MsgType => 'MarketDataRequest', SubscriptionRequestType => 'SNAPSHOT_PLUS_UPDATES', MarketDepth => 1, MDUpdateType => 'INCREMENTAL_REFRESH', NoRelatedSym => [ { Instrument => { Symbol => 'EUR/USD' }, }, { Instrument => { Symbol => 'GBP/CHF' }, } ], NoMDEntryTypes => [ { MDEntryType => 'BID' }, { MDEntryType => 'OFFER' } ], Debug => $debug ) or die "Cannot send request: $!";
# We then use lastRequest() method to get the parsed answer
if ( $fix->lastRequest('MsgType') eq "REJECT" ) { print "Request was rejected\n"; print "Reason: ".$fix->lastRequest('SessionRejectReason')."\n"; print "RefTag: ".FIX::Lite->getTagById($fix->lastRequest('RefTagID'))."\n"; }
# And yup, we can use FIX::Lite->getTagById() method to resolve tag codes into # human-readable values # After sending some subscriptions we can relax and wait for the quotes
$fix->listen( \&handler, HeartBtInt => 30, Debug => 0 );
# Every incoming message (except Heartbeats and TestRequests) will call some handler function, # we need to just pass its reference as an argument. As for the hearbeats then # module will send them every HeartBtInt seconds (default is 30). And also the module will automatically answer # the test requests
# To explicitly close the connection we can use quit() method
$fix->quit();
# And a simple example of the handler function:
sub handler { my $resp = shift; print "Received message ".$resp->{MsgType}."\n"; if ( $resp->{MsgType} eq 'W' ) { if ( defined $resp->{NoMDEntries} ) { print "Received Prices for symbol ".$resp->{Symbol}."\n"; foreach ( @{$resp->{NoMDEntries}} ) { print "Price ".$_->{MDEntryPx}.", type ".$_->{MDEntryType}."\n"; } } else { print "Received Price ".$resp->{MDEntryPx}." for symbol ".$resp->{Symbol}."\n"; } } return 1; }
SERVER MODE
FIX::Lite can also help you to create an own simple FIX feeder. Please see the example below to get an idea.
use FIX::Lite;
my $fix = FIX::Lite->new(
Host => '0.0.0.0',
Port => 5201,
Feed => 1
);
# Notice the Feed => 1. This creates a server instance.
# The only available method for this instance is startServer which starts listening the defined socket
$fix->startServer(
\&msgHandler,
\&periodicHandler,
SenderCompID => 'MySenderCompID',
Period => 1000, # ms
AutoLogon => 1,
HeartBtInt => 30,
Debug => 0
);
# Period is the time period between executions of the &periodicHandler function.
# AutoLogon enables the automatic answering the Logon request. All logons will be successful
# if providing the right TargetCompID. If AutoLogon is 0 (which is the default value) then you will need
# to implement the handling of 35=A requests in msgHandler.
# These are the examples for &msgHandler and &periodicHandler functions
# msgHandler receives the parsed incoming messages from the clients (except for Hearbeats, TestRequests
# and Logons if AutoLogon is enabled
# msgHandler can return the hash reference with the description of the message to send back to client.
our %subscriptions;
sub msgHandler {
my $resp = shift;
print "Start handling message ".$resp->{MsgType}."\n";
if ( $resp->{MsgType} eq 'V' ) {
print 'Got MARKET DATA REQUEST for symbol '.$resp->{MDReqID}.' from SenderCompID '.$resp->{SenderCompID}."\n";
push @{$subscriptions{$resp->{SenderCompID}}}, $resp->{MDReqID};
}
}
# periodicHandler is called priodically and it can return the list of message to be sent to several cliens
sub periodicHandler {
my $MD;
# Iterate over all clients with subscriptions
foreach my $client (keys %subscriptions) {
# Iterate over all subscriptions of each client
foreach my $symbol (@{$subscriptions{$client}}) {
my %msg = (
MsgType => 'MarketDataIncrementalRefresh',
TargetSubID => 'price',
NoMDEntries => [
{
MDUpdateAction => 'NEW',
Instrument => { Symbol => $symbol },
MDEntryType => 'BID',
MDEntryPx => '1.1234',
MDEntrySize => 50000,
MDEntryID => 1
},
{
MDUpdateAction => 'NEW',
Instrument => { Symbol => $symbol },
MDEntryType => 'OFFER',
MDEntryPx => '1.1232',
MDEntrySize => 50000,
MDEntryID => 2
}
]
);
push @{$MD->{$client}}, \%msg;
}
}
return $MD;
}
INSTANCE METHODS
new
Open a socket to the FIX server
logon
Send the logon (35=A) message and wait for the response
heartbeat
Send the heartbeat (35=0) message and get back
request
Send the FIX request of any type and wait for the response
listen
Wait for the incoming messages. This method will return after the socket is closed. Heartbeats are sent automatically.
loggedIn
Returns true if FIX server has answered with Logon message
lastRequest
Returns hash with parsed response for the last request sent.
getTagById
Resolve tag name by its code
getMsgByType
Resolve message name by its type code
quit
Explicitly close the socket to the FIX server.
startServer
Start the FIX server
AUTHOR
Vitaly Agapov, <agapov.vitaly@gmail.com>
LICENSE AND COPYRIGHT
Copyright 2015-2017 "Vitaly Agapov".
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.