コード例 #1
0
ファイル: protocol.py プロジェクト: speedyyellow/fixtest
    def on_timer_tick_received(self):
        """ This is the Twisted timer callback when the heartbeat interval
            has elapsed.
        """
        if self.heartbeat <= 0:
            return

        now = datetime.datetime.now()

        # Have we received a testrequest response before we timed out?
        if (self._testrequest_id is not None and
                (now - self._testrequest_time).seconds > 2*self.heartbeat):
            raise FIXTimeoutError('testrequest response timeout')

        # if heartbeat seconds/2 have elapsed since the last time
        # a message was sent, send a heartbeat
        if (now - self._last_send_time).seconds > (self.heartbeat/2):
            self.transport.send_message(
                FIXMessage(source=[(35, FIX.HEARTBEAT),
                                   (49, self.link_config['sender_compid']),
                                   (56, self.link_config['target_compid'])]))

        # if heartbeat seconds + "some transmission time" have elapsed
        # since a message was received, send a TestRequest
        if (now - self._last_received_time).seconds > self.heartbeat:
            testrequest_id = "TR{0}".format(format_time(now))
            self._testrequest_time = now
            self._testrequest_id = testrequest_id
            self.transport.send_message(
                FIXMessage(source=[(35, FIX.TEST_REQUEST),
                                   (112, testrequest_id),
                                   (49, self.link_config['sender_compid']),
                                   (56, self.link_config['target_compid'])]))
コード例 #2
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_to_binary(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[34] = 177
        mess[52] = '20090107-18:15:16'
        mess[98] = 0
        mess[108] = 30
        mess[10] = '---'

        data = mess.to_binary()

        # BodyLength(9) and Checksum(10) should be updated after
        # the to_binary() was called.
        self.assertEquals('65', mess[9])
        self.assertEquals('062', mess[10])

        self.assertEquals(to_fix('8=FIX.4.2',
                                 '9=65',
                                 '35=A',
                                 '49=SERVER',
                                 '56=CLIENT',
                                 '34=177',
                                 '52=20090107-18:15:16',
                                 '98=0',
                                 '108=30',
                                 '10=062'),
                          data)
コード例 #3
0
 def test_nested_group_from_list(self):
     """ Call to_binary() on a nested grouped message from a list """
     # As its difficult to test this, convert the (unordered)
     # dict into an OrderedDict() before inserting (sorting by tag).
     # This makes it easier to do the comparison.
     mess = FIXMessage(header_fields=[8, 9],
                       source=to_ordered_dict([(8, 'FIX.4.2'),
                                               (100, [{
                                                   101: 'abc',
                                                   102: 'def'
                                               }, {
                                                   101: 'ghi',
                                                   103: 'jkl'
                                               }, {
                                                   101:
                                                   'mno',
                                                   200: [{
                                                       201: 'aaa',
                                                       202: 'bbb'
                                                   }]
                                               }]), (99, 'X')]))
     self.assertEquals(
         to_fix('8=FIX.4.2', '9=73', '100=3', '101=abc', '102=def',
                '101=ghi', '103=jkl', '101=mno', '200=1', '201=aaa',
                '202=bbb', '99=X', '10=034'), mess.to_binary())
コード例 #4
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_header_fields(self):
        mess = FIXMessage()
        self.assertEquals(5, len(mess))

        self.assertTrue(8 in mess)
        self.assertTrue(9 in mess)
        self.assertTrue(35 in mess)
        self.assertTrue(49 in mess)
        self.assertTrue(56 in mess)

        items = [(k, v) for k, v in mess.items()]
        # 8,9 are required to be first and second fields, respectively
        self.assertEquals(8, items[0][0])
        self.assertEquals(9, items[1][0])

        # Custom required fields
        mess = FIXMessage(header_fields=[1024, 8, 9])
        self.assertTrue(8 in mess)
        self.assertTrue(9 in mess)
        self.assertTrue(35 not in mess)
        self.assertTrue(1024 in mess)

        items = [(k, v) for k, v in mess.items()]
        self.assertEquals(1024, items[0][0])
        self.assertEquals(8, items[1][0])
        self.assertEquals(9, items[2][0])
コード例 #5
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
 def test_nested_group_from_list(self):
     """ Call to_binary() on a nested grouped message from a list """
     # As its difficult to test this, convert the (unordered)
     # dict into an OrderedDict() before inserting (sorting by tag).
     # This makes it easier to do the comparison.
     mess = FIXMessage(
         header_fields=[8, 9],
         source=to_ordered_dict([(8, 'FIX.4.2'),
                                 (100, [{101: 'abc', 102: 'def'},
                                        {101: 'ghi', 103: 'jkl'},
                                        {101: 'mno', 200: [
                                            {201: 'aaa', 202: 'bbb'}]}]),
                                 (99, 'X')]))
     self.assertEquals(to_fix('8=FIX.4.2',
                              '9=73',
                              '100=3',
                              '101=abc',
                              '102=def',
                              '101=ghi',
                              '103=jkl',
                              '101=mno',
                              '200=1',
                              '201=aaa',
                              '202=bbb',
                              '99=X',
                              '10=034'),
                       mess.to_binary())
コード例 #6
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_msg_type(self):
        mess = FIXMessage()
        self.assertEquals('', mess[35])
        self.assertEquals('', mess.msg_type())

        mess[35] = FIX.LOGON
        self.assertEquals(FIX.LOGON, mess[35])
        self.assertEquals(FIX.LOGON, mess.msg_type())
コード例 #7
0
    def test_msg_type(self):
        mess = FIXMessage()
        self.assertEquals('', mess[35])
        self.assertEquals('', mess.msg_type())

        mess[35] = FIX.LOGON
        self.assertEquals(FIX.LOGON, mess[35])
        self.assertEquals(FIX.LOGON, mess.msg_type())
コード例 #8
0
 def test_group_from_list(self):
     """ Call to_binary() on a grouped message from a list """
     mess = FIXMessage(header_fields=[8, 9],
                       source=[(8, 'FIX.4.2'), (9, '25'), (49, 'SERVER'),
                               (56, 'CLIENT'), (99, 'X')])
     self.assertEquals(
         to_fix('8=FIX.4.2', '9=25', '49=SERVER', '56=CLIENT', '99=X',
                '10=239'), mess.to_binary())
コード例 #9
0
    def test_to_binary_include(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[177] = 'hello'

        data = mess.to_binary(include=[8, 9, 35, 177])
        self.assertEquals(
            to_fix('8=FIX.4.2', '9=15', '35=A', '177=hello', '10=212'), data)
コード例 #10
0
    def test_to_binary_binarydata(self):
        mess = FIXMessage(header_fields=[8, 9])
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[110] = 2
        mess[111] = '\x01\x02a\xbbbcd'

        data = mess.to_binary()

        self.assertEquals(
            to_fix('8=FIX.4.2', '9=18', '110=2', '111=\x01\x02a\xbbbcd',
                   '10=026'), data)
コード例 #11
0
    def test_to_binary_exclude(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[99] = 'X'
        mess[177] = 'hello'

        data = mess.to_binary(exclude=[35, 177])
        self.assertEquals(
            to_fix('8=FIX.4.2', '9=25', '49=SERVER', '56=CLIENT', '99=X',
                   '10=239'), data)
コード例 #12
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
 def test_group_from_list(self):
     """ Call to_binary() on a grouped message from a list """
     mess = FIXMessage(header_fields=[8, 9],
                       source=[(8, 'FIX.4.2'),
                               (9, '25'),
                               (49, 'SERVER'),
                               (56, 'CLIENT'),
                               (99, 'X')])
     self.assertEquals(to_fix('8=FIX.4.2',
                              '9=25',
                              '49=SERVER',
                              '56=CLIENT',
                              '99=X',
                              '10=239'),
                       mess.to_binary())
コード例 #13
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_to_binary_binarydata(self):
        mess = FIXMessage(header_fields=[8, 9])
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[110] = 2
        mess[111] = '\x01\x02a\xbbbcd'

        data = mess.to_binary()

        self.assertEquals(to_fix('8=FIX.4.2',
                                 '9=18',
                                 '110=2',
                                 '111=\x01\x02a\xbbbcd',
                                 '10=026'),
                          data)
コード例 #14
0
def logout_message(client):
    """ Generates a FIX logout message """
    return FIXMessage(
        source=[(35,
                 FIX.LOGOUT), (49,
                               client.sender_compid), (56,
                                                       client.target_compid)])
コード例 #15
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_to_binary_include(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[177] = 'hello'

        data = mess.to_binary(include=[8, 9, 35, 177])
        self.assertEquals(to_fix('8=FIX.4.2',
                                 '9=15',
                                 '35=A',
                                 '177=hello',
                                 '10=212'),
                          data)
コード例 #16
0
def new_order_message(client, **kwargs):
    """ Generates a new order message.

        Arguments:

        Returns:

        Raises:
            ValueError
    """
    # Required parameters
    for sym in ['symbol', 'side', 'order_type']:
        if sym not in kwargs:
            raise ValueError("{0} must have a value".format(sym))

    # optional parameters
    extra_tags = kwargs.get('extra_tags', [])

    return FIXMessage(source=[
        (35, FIX.NEWORDER_SINGLE),
        (49, client.sender_compid),
        (56, client.target_compid),
        (11, client.get_next_orderid()),
        (21, '1'),  # handlInst
        (55, kwargs['symbol']),
        (54, kwargs['side']),
        (60, format_time(datetime.datetime.now())),
        (40, kwargs['order_type']),
    ] + extra_tags)
コード例 #17
0
    def test_to_binary_group(self):
        """ Call to_binary() on a grouped message """
        mess = FIXMessage(header_fields=[8, 9])
        tags = collections.OrderedDict()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        tags[110] = 2
        tags[111] = 'abcd'

        mess[100] = [
            tags,
        ]
        data = mess.to_binary()

        self.assertEquals(
            to_fix('8=FIX.4.2', '9=21', '100=1', '110=2', '111=abcd',
                   '10=086'), data)
コード例 #18
0
def execution_report(client, prev_message, **kwargs):
    """ Generates an execution report

        Arguments:
            client
            prev_message
            exec_trans_type:
            exec_type:
            ord_status:
            leaves_qty:
            cum_qty:
            avg_px:

        Returns:
        Raises:
            ValueError
    """
    # Required parameters
    for sym in [
            'exec_trans_type', 'exec_type', 'ord_status', 'leaves_qty',
            'cum_qty', 'avg_px'
    ]:
        if sym not in kwargs:
            raise ValueError("{0} must have a value".format(sym))

    # optional parameters
    extra_tags = kwargs.get('extra_tags', [])
    exec_id = kwargs.get('exec_id', None) or client.get_next_orderid()

    message = FIXMessage(source=prev_message)
    message.update([
        (35, FIX.EXECUTION_REPORT),
        (49, client.sender_compid),
        (56, client.target_compid),
        (11, prev_message[11]),
        (37, client.get_next_orderid()),
        (17, exec_id),
        (20, kwargs['exec_trans_type']),
        (150, kwargs['exec_type']),
        (39, kwargs['ord_status']),
        (151, kwargs['leaves_qty']),
        (14, kwargs['cum_qty']),
        (6, kwargs['avg_px']),
    ] + extra_tags)
    return message
コード例 #19
0
 def test_simple_send(self):
     """ test simple sending """
     self.assertEquals(0, self.transport.message_sent_count)
     self.transport.send_message(
         FIXMessage(source=[
             (8, 'FIX.4.2'),
             (35, 'A'),
         ]))
     self.assertEquals(1, self.transport.message_sent_count)
コード例 #20
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_to_binary_exclude(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[99] = 'X'
        mess[177] = 'hello'

        data = mess.to_binary(exclude=[35, 177])
        self.assertEquals(to_fix('8=FIX.4.2',
                                 '9=25',
                                 '49=SERVER',
                                 '56=CLIENT',
                                 '99=X',
                                 '10=239'),
                          data)
コード例 #21
0
ファイル: messages.py プロジェクト: greenpau/fixtest
def execution_report(client, prev_message, **kwargs):
    """ Generates an execution report

        Arguments:
            client
            prev_message
            exec_trans_type:
            exec_type:
            ord_status:
            leaves_qty:
            cum_qty:
            avg_px:

        Returns:
        Raises:
            ValueError
    """
    # Required parameters
    for sym in ['exec_trans_type', 'exec_type', 'ord_status',
                'leaves_qty', 'cum_qty',
                'avg_px']:
        if sym not in kwargs:
            raise ValueError("{0} must have a value".format(sym))

    # optional parameters
    extra_tags = kwargs.get('extra_tags', [])
    exec_id = kwargs.get('exec_id', None) or client.get_next_orderid()

    message = FIXMessage(source=prev_message)
    message.update([
        (35, FIX.EXECUTION_REPORT),
        (49, client.sender_compid),
        (56, client.target_compid),
        (11, prev_message[11]),
        (37, client.get_next_orderid()),
        (17, exec_id),
        (20, kwargs['exec_trans_type']),
        (150, kwargs['exec_type']),
        (39, kwargs['ord_status']),
        (151, kwargs['leaves_qty']),
        (14, kwargs['cum_qty']),
        (6, kwargs['avg_px']),
        ] + extra_tags)
    return message
コード例 #22
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_to_binary_group(self):
        """ Call to_binary() on a grouped message """
        mess = FIXMessage(header_fields=[8, 9])
        tags = collections.OrderedDict()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        tags[110] = 2
        tags[111] = 'abcd'

        mess[100] = [tags, ]
        data = mess.to_binary()

        self.assertEquals(to_fix('8=FIX.4.2',
                                 '9=21',
                                 '100=1',
                                 '110=2',
                                 '111=abcd',
                                 '10=086'),
                          data)
コード例 #23
0
 def test_send_seqno(self):
     """ test send sequence numbering """
     seqno = self.protocol._send_seqno
     self.assertEquals(0, self.transport.message_sent_count)
     self.transport.send_message(
         FIXMessage(source=[
             (8, 'FIX.4.2'),
             (35, 'A'),
         ]))
     self.assertEquals(1, self.transport.message_sent_count)
     self.assertEquals(seqno + 1, self.protocol._send_seqno)
コード例 #24
0
    def test_header_fields(self):
        mess = FIXMessage()
        self.assertEquals(5, len(mess))

        self.assertTrue(8 in mess)
        self.assertTrue(9 in mess)
        self.assertTrue(35 in mess)
        self.assertTrue(49 in mess)
        self.assertTrue(56 in mess)

        items = [(k, v) for k, v in mess.items()]
        # 8,9 are required to be first and second fields, respectively
        self.assertEquals(8, items[0][0])
        self.assertEquals(9, items[1][0])

        # Custom required fields
        mess = FIXMessage(header_fields=[1024, 8, 9])
        self.assertTrue(8 in mess)
        self.assertTrue(9 in mess)
        self.assertTrue(35 not in mess)
        self.assertTrue(1024 in mess)

        items = [(k, v) for k, v in mess.items()]
        self.assertEquals(1024, items[0][0])
        self.assertEquals(8, items[1][0])
        self.assertEquals(9, items[2][0])
コード例 #25
0
    def __init__(self, receiver, **kwargs):
        """ FIXParser initialization

            Args:
                receiver: This is an observer that receives the message and
                    error notifications from the parser.  There are two
                    callbacks:
                        on_message_received(message)
                        on_error_received(error)
                header_fields: A list of header tags.  This only affects
                    the sending of the message. The order of the input
                    fields is not validated.
                binary_fields: A list of tags indicating binary fields.
                    Note that binary fields come in pairs.  The first
                    field contains the length of the data and the second
                    field contains the actual data.  The convention is that
                    the IDs are sequential.  For example, if the length field
                    is tag 123, then tag 124 contains the data.  Note that
                    only the first field should be included in this list.
                group_fields: A dictionary of fields that belong to a group.
                    The key is the group ID field that maps to a list of
                    IDs that belong to the group.  When specifying the
                    field list for a group, include BOTH fields of a
                    binary field.
                max_length: Maximum length of a FIX message supported
                    (Default: 2048).
                debug: Set to True for more debugging output
        """
        self.is_parsing = False

        self._receiver = receiver
        self._header_fields = kwargs.get('header_fields', [8, 9, 35, 49, 56])
        self._binary_fields = kwargs.get('binary_fields', list())
        self._group_fields = kwargs.get('group_fields', list())
        self._max_length = kwargs.get('max_length', 2048)
        self._debug = kwargs.get('debug', False)

        self._buffer = b''
        self.is_receiving_data = False

        self._message = FIXMessage(header_fields=self._header_fields)
        self._checksum = 0
        self._message_length = 0

        # used for binary field processing
        self._binary_length = -1
        self._binary_tag = 0

        # used for groups processing
        self._level_stack = list()

        self._logger = logging.getLogger(__name__)
コード例 #26
0
    def test_to_binary(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[34] = 177
        mess[52] = '20090107-18:15:16'
        mess[98] = 0
        mess[108] = 30
        mess[10] = '---'

        data = mess.to_binary()

        # BodyLength(9) and Checksum(10) should be updated after
        # the to_binary() was called.
        self.assertEquals('65', mess[9])
        self.assertEquals('062', mess[10])

        self.assertEquals(
            to_fix('8=FIX.4.2', '9=65', '35=A', '49=SERVER', '56=CLIENT',
                   '34=177', '52=20090107-18:15:16', '98=0', '108=30',
                   '10=062'), data)
コード例 #27
0
ファイル: protocol.py プロジェクト: speedyyellow/fixtest
    def on_message_received(self, message, message_length, checksum):
        """ This is the callback from the parser when a message has
            been received.
        """
        # verify required tags
        for tag in self.link_config['required_fields']:
            if tag not in message or len(str(message[tag])) == 0:
                raise FIXDataError(tag, 'missing field: id:{0}'.format(tag))

        # verify the protocol version
        if 'protocol_version' in self.link_config:
            if self.link_config['protocol_version'] != message[8]:
                raise FIXDataError(
                    8, 'version mismatch: expect:{0} received:{1}'.format(
                        self.link_config['protocol_version'],
                        message[8]
                        ))

        # verify the length and checksum
        if message_length != int(message[9]):
            raise FIXDataError(
                9, 'length mismatch: expect:{0} received:{1}'.format(
                    message_length, int(message[9])))

        if checksum != int(message[10]):
            raise FIXDataError(
                10, 'checksum mismatch: expect:{0} received:{1}'.format(
                    checksum, message[10]))

        self._last_received_time = datetime.datetime.now()

        # Have we received our testrequest response?
        if (message.msg_type() == FIX.HEARTBEAT and
                message.get(112, '') == self._testrequest_id):
            self._testrequest_time = None
            self._testrequest_id = None

        # We have received a testrequest and need to send a response
        if message.msg_type() == FIX.TEST_REQUEST:
            self.transport.send_message(
                FIXMessage(source=[(35, FIX.HEARTBEAT),
                                   (112, message[112]),
                                   (49, self.link_config['sender_compid']),
                                   (56, self.link_config['target_compid'])]))

        if (not self.filter_heartbeat or
                (message.msg_type() not in {FIX.HEARTBEAT, FIX.TEST_REQUEST})):
            self.transport.on_message_received(message)
コード例 #28
0
    def test_send_with_missing_fields(self):
        """ send with missing fields """
        self.assertEquals(0, self.transport.message_sent_count)

        message = FIXMessage(source=[
            (8, 'FIX.4.2'),
            (35, 'A'),
        ])
        self.assertTrue(34 not in message)
        self.assertTrue(52 not in message)
        self.transport.send_message(message)
        self.assertEquals(1, self.transport.message_sent_count)

        # check for seqno(34) and sendtime(52)
        self.assertTrue(34 in self.transport.last_message_sent)
        self.assertTrue(52 in self.transport.last_message_sent)
コード例 #29
0
    def test_verify(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[99] = 'X'
        mess[177] = 'hello'

        self.assertTrue(mess.verify(fields=[(8, 'FIX.4.2'), (35, 'A')]))
        self.assertFalse(mess.verify(fields=[(8, 'NOFIX')]))

        self.assertTrue(mess.verify(exists=[8, 35, 177]))
        self.assertFalse(mess.verify(exists=[9, 8, 2000]))

        self.assertTrue(mess.verify(not_exists=[2000, 20001]))
        self.assertFalse(mess.verify(not_exists=[177]))

        self.assertTrue(
            mess.verify(fields=[(99, 'X')],
                        exists=[56, 99, 177],
                        not_exists=[2001, 2002, 2003]))
コード例 #30
0
    def reset(self, flush_buffer=False):
        """ Reset the protocol state so that it is ready to accept a
            new message.
        """
        self.is_parsing = False
        self._message = FIXMessage(header_fields=self._header_fields)
        self._checksum = 0
        self._message_length = 0

        # used for binary field processing
        self._binary_length = -1
        self._binary_tag = 0

        # used for groups processing
        self._level_stack = list()

        if flush_buffer:
            self._buffer = b''
コード例 #31
0
ファイル: fix_message_test.py プロジェクト: greenpau/fixtest
    def test_verify(self):
        mess = FIXMessage()
        mess[8] = 'FIX.4.2'
        mess[9] = '---'
        mess[35] = 'A'
        mess[49] = 'SERVER'
        mess[56] = 'CLIENT'
        mess[99] = 'X'
        mess[177] = 'hello'

        self.assertTrue(mess.verify(fields=[(8, 'FIX.4.2'), (35, 'A')]))
        self.assertFalse(mess.verify(fields=[(8, 'NOFIX')]))

        self.assertTrue(mess.verify(exists=[8, 35, 177]))
        self.assertFalse(mess.verify(exists=[9, 8, 2000]))

        self.assertTrue(mess.verify(not_exists=[2000, 20001]))
        self.assertFalse(mess.verify(not_exists=[177]))

        self.assertTrue(mess.verify(fields=[(99, 'X')],
                                    exists=[56, 99, 177],
                                    not_exists=[2001, 2002, 2003]))
コード例 #32
0
def logon_message(client):
    """ Generates a FIX logon message """
    return FIXMessage(source=[(35, FIX.LOGON), (
        49, client.sender_compid), (56, client.target_compid), (
            98, 0), (108, client.protocol.heartbeat)])