The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

FIX::Lite - Simple FIX (Financial Information eXchange) protocol module

VERSION

Version 0.08

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 'A' ) {
            print 'Got LOGON from SenderCompID '.$resp->{SenderCompID}."\n";
            my %msg = (
                MsgType => 'Logon'
            );
            undef $subscriptions{$resp->{SenderCompID}};
            return \%msg;
        }
        elsif ( $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-2018 "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.