Search code examples
pythonbinaryquantitative-financealgorithmic-trading

Python: how to make a struct.calcsize integer with a standard size 6?


If I look here: https://docs.python.org/2/library/struct.html at section 7.3.2.2. Format Characters, there are no Format letter for a Python Type Integer with standard size 6. I have tried '6p' or even '3H' but that doesn't work for instance in:

import struct
struct.calcsize('!6p')

Sorry if this sounds dumb... I am learning how to convert strings as packed binary data for the first time for a string message that has a length of 6 with integer as a value. So what is the proper letter format to get a standard size 6 for an integer?

UPDATE

My task is to convert the binary messages contained in NASDAQ TotalVIEW-ITCH 5.0 specification document, here

So for instance, if you look at Section 4.1: System Event Message (Page 3), I would convert the message of type 'S' as follow:

class SystemEventMessage(Message): 
    type = 'S'
    description = "System Event Message"
    message_size = struct.calcsize("!HH6pc") + 1
def __init__(self, message):
    (self.locate,self.tracking,self.timestamp, self.code) = struct.unpack("!HH6pc", message[1:])

def pack(self):
    return struct.pack("!cHH6pc", self.type,self.locate,self.tracking, self.timestamp, self.code)

I get this error:

struct.error: unpack requires a string argument of length 11

So I am assuming my error has to do with the '6p' since I can't find any integer with standard size 6.

UPDATE 2

So I use the below suggestion of using 6s rather than 6p, for the following message type "I" in the documentation Section 4.6: Net Order Imbalance Indicator (NOII) Message, I do:

class NoiiMessage(ITCH41MarketMessage):
    type = 'I'
    description = "NOII Message"
    message_size = struct.calcsize("!HH6sQQc8sIIIcc") + 1

    def __init__(self, message):
        (self.locate,self.tracking,self.timestamp, self.pairedShares, self.imbalance,
         self.imbalanceDirection, self.stock, self.farPrice, self.nearPrice,
         self.currentRefPrice, self.crossType, self.priceVariationbsindicator
         ) = struct.unpack("!HH6sQQc8sIIIcc", message[1:])

    def pack(self):
        return struct.pack("!cHH6sQQc8sIIIcc", self.type,self.locate,
                           self.tracking, self.timestamp,
                           self.pairedShares, self.imbalance,
                           self.imbalanceDirection, self.stock,
                           self.farPrice, self.nearPrice,
                           self.currentRefPrice, self.crossType,
                           self.priceVariationbsindicator)

I get this error:

struct.error: unpack requires a string argument of length 49

Now that's strange since !HH6sQQc8sIIIcc is of length 49...


Everyone thank you for the help!


Solution

  • NASDAQ TotalView-ITCH 5.0

    [S0099123456Q]________________________________ wireline SEQ _____________
     | | |     ||
     | | |     |+---------------[[ Event Code   ]]
     | | |     +----------------[[ Timestamp ns ]]
     | | +----------------------[[ Tracking NUM ]]
     | +------------------------[[ Stock Locate ]]
     +--------------------------[[ Message Type ]]
    
    Name           | Offset | Length | Value   | Notes
    ---------------|--------|--------|---------|-------------------------------------------------------------
    Message Type   | 0      | 1      | “S”     | System Event Message.
    Stock Locate   | 1      | 2      | Integer | == 0 Always
    Tracking Number| 3      | 2      | Integer | NASDAQ OMX internal tracking number
    Timestamp      | 5      | 6      | Integer | Nanoseconds since midnight.
    Event Code     |11      | 1      | Alpha   | == { 0 | S | Q | M | E | C } See System Event Codes below.
    

    In order to get NASDAQ_Timestamp,
    grab 6-uchar-s using 6B in the mask or char[] 6s
    and postprocess them into int() only if needed on the consumer side
    which defers latency and unblocks destreaming engine wireline performance.

    + also enjoy the Python 7.3.2.1. notes on BigEndian / network ordering once using "!" mask-prefix


    >>> struct.pack(   ">c2H6sc", "S", 0, 99, "123456", "Q" )
    'S\x00\x00\x00c123456Q'
    
    >>> struct.unpack( ">c2H6sc", "S\x00\x00\x00c123456Q" )
    ('S', 0, 99, '123456', 'Q')
      |   |   |        |    |
      |   |   |        |    +---------------[[ Event Code   ]]
      |   |   |        +--------------------[[ Timestamp ns ]]
      |   |   +-----------------------------[[ Tracking NUM ]]
      |   +---------------------------------[[ Stock Locate ]]
      +-------------------------------------[[ Message Type ]]
    

    Ad another question in UPDATE2

    "!HH6sQQc8sIIIcc"                              _
     +||-||||-||||||----------------------------1 |_|_ "!"   a "Network"-Byte-order
      +|-||||-||||||----------------------------2 |_|   H as a 2 Byte unsigned short
       | |||| ||||||                            3 |_|_ 
       +-||||-||||||----------------------------4-|_|   H as a 2 Byte unsigned short                                
         |||| ||||||                            5 |_|_ 
         +|||-||||||----------------------------6-|_|  6s as a 6 Byte char[]
          ||| ||||||                            7 |_|  
          ||| ||||||                            8 |_|  
          ||| ||||||                            9 |_|  
          ||| ||||||                           10 |_|  
          ||| ||||||                            1 |_|_ 
          +||-||||||--------------------------- 2-|_|   Q as a 8 Byte unsigned long long
           || ||||||                            3 |_|  
           || ||||||                            4 |_|  
           || ||||||                            5 |_|  
           || ||||||                            6 |_|  
           || ||||||                            7 |_|  
           || ||||||                            8 |_|  
           || ||||||                            9 |_|_ 
           +|-||||||---------------------------20-|_|   Q as a 8 Byte unsigned long long
            | ||||||                            1 |_|  
            | ||||||                            2 |_|  
            | ||||||                            3 |_|  
            | ||||||                            4 |_|  
            | ||||||                            5 |_|  
            | ||||||                            6 |_|  
            | ||||||                            7 |_|_ 
            +-||||||----------------------------8-|_|_  c as a 1 Byte char
              +|||||----------------------------9-|_|  8s as a 8 Byte char[]
               |||||                           30 |_|  
               |||||                            1 |_|  
               |||||                            2 |_|  
               |||||                            3 |_|  
               |||||                            4 |_|  
               |||||                            5 |_|  
               |||||                            6 |_|_ 
               +||||----------------------------7-|_|   I as a 4 Byte unsigned int
                ||||                            8 |_|                                     
                ||||                            9 |_|                                     
                ||||                           40 |_|_ 
                +|||----------------------------1-|_|   I as a 4 Byte unsigned int
                 |||                            2 |_|                             
                 |||                            3 |_|                             
                 |||                            4 |_|_ 
                 +||----------------------------5-|_|   I as a 4 Byte unsigned int
                  ||                            6 |_|                             
                  ||                            7 |_|                             
                  ||                            8 |_|_ 
                  +|----------------------------9-|_|_  c as a 1 Byte char
                   +---------------------------50-|_|_  c as a 1 Byte char
    

    Where:

    Format  | C-type               | Python-type        | Standard size
    ========|======================|====================|===============
         x  | pad byte             | no value           |     
         c  | char                 | string of length 1 | 1 
         b  | signed char          | integer            | 1 
         B  | unsigned char        | integer            | 1 
         ?  | _Bool                | bool               | 1 
         h  | short                | integer            | 2 
         H  | unsigned short       | integer            | 2 
         i  | int                  | integer            | 4 
         I  | unsigned int         | integer            | 4 
         l  | long                 | integer            | 4 
         L  | unsigned long        | integer            | 4 
         q  | long long            | integer            | 8 
         Q  | unsigned long long   | integer            | 8 
         f  | float                | float              | 4 
         d  | double               | float              | 8 
         s  | char[]               | string             | 
         p  | char[]               | string             |  
         P  | void *               | integer            |