QuickFIX/Go Documentation

repository·main·Indexed 21 days ago

https://github.com/quickfixgo/quickfix

An open-source implementation of the FIX (Financial Information eXchange) Protocol for Go. It features spec-driven message validation, type-safe code generation via the generate-fix tool, and support for SQL and MongoDB session state storage. The library provides core components for handling FIX tags, fields, and enums, along with an Application interface for processing session lifecycle events and messages.

Tokens
22.9K
Snippets
88
Records
108
Agent score
72%

What's inside QuickFIX/Go

  1. Understand the FIX Messaging Model

    main

    QuickFIX/Go uses a modular approach for FIX messaging. While the core engine is in the quickfix package, sending and receiving messages requires additional auto-generated packages for specific FIX versions and components. These packages provide type-safe messages, fields, tags, and enums based on the FIX XML specifications.

    Core Components:

    • tag: FIX tags
    • field: FIX fields
    • enum: FIX enumerations
    • message: Specific FIX version packages (e.g., fix44, fix50sp2) containing type-safe message structures.

    Custom FIX Specifications: If you are using a custom FIX specification, you can use the generate-fix tool (installed to $GOPATH/bin/generate-fix) to generate the necessary Go source code.

  2. Install QuickFIX/Go

    main

    You can install QuickFIX/Go using Go modules by adding the import to your code. Alternatively, you can use the go get command to install the package directly.

    Requirements:

    • Go 1.21 or higher
    import "github.com/quickfixgo/quickfix"

    OR

    go get -u github.com/quickfixgo/quickfix
  3. Configure session reset behavior

    main

    The session can be configured to reset sequence numbers automatically during specific lifecycle events. This is controlled by the following session settings:

    • ResetOnLogon: Resets sequence numbers to 1 upon a successful logon.
    • ResetOnDisconnect: Resets sequence numbers when the session disconnects.
    • ResetOnLogout: Resets sequence numbers when a logout is processed.

    Additionally, if a Logon message is received with the ResetSeqNumFlag set to true, the session will reset its store if ResetOnLogon is enabled.

  4. The Message structure: Header, Body, and Trailer

    main

    A FIX Message is logically divided into three sections, each inheriting from FieldMap:

    1. Header: Contains session-level information (e.g., BeginString [8], BodyLength [9], MsgType [35]).
    2. Body: The primary application data section containing business-specific fields and repeating groups.
    3. Trailer: Contains session-level metadata, specifically the CheckSum [10], which must always be the final field.

    When building a message, the Message object manages the ordering requirements for these sections automatically.

  5. Understand the FieldValue interfaces for raw data conversion

    main

    QuickFIX/Go uses two core interfaces to handle the conversion between typed data and raw byte slices:

    1. FieldValueWriter: Provides the Write() []byte method to convert a value into its wire-format byte representation.
    2. FieldValueReader: Provides the Read([]byte) error method to parse raw bytes into a typed value.

    The FieldValue interface is the union of these two, representing any type that can be both read from and written to the FIX wire format.

  6. How dynamic sessions work

    main

    If the DynamicSessions setting is enabled in the global configuration, the Acceptor can create new sessions on-the-fly when it receives a connection that doesn't match an existing pre-configured session.

    If DynamicQualifier is also enabled, the Acceptor will assign a unique numeric qualifier to these dynamic sessions to distinguish them. This allows the engine to handle a flexible number of incoming client connections without requiring every session to be explicitly defined in the configuration file.

  7. How FIX session validation works

    main

    The session automatically validates incoming messages against the FIX protocol and your application implementation. The validation process includes:

    1. Protocol Checks: Verifies BeginString, SenderCompID, and TargetCompID match the session configuration.
    2. Sequence Number Checks: Ensures MsgSeqNum is not too low (replayed) or too high (gap detected).
    3. Latency Checks: Validates the SendingTime against MaxLatency (unless SkipCheckLatency is enabled).
    4. Application Validation: If a Validator is provided, it calls Validator.Validate(msg). Finally, it calls the application's FromAdmin or FromApp callbacks.

    If validation fails, the session automatically generates a Reject message (or BusinessReject if applicable) and sends it back to the peer using doReject.

  8. How Settings inheritance works

    main

    QuickFIX/Go uses a hierarchical configuration model.

    1. Global Settings: Defined under the [DEFAULT] section. These are the baseline values for every session.
    2. Session Settings: Defined under [SESSION] sections. These contain values specific to a single connection.
    3. Overlay Logic: When you call SessionSettings(), the engine provides a view of each session where the GlobalSettings have been cloned and then overlaid with the specific SessionSettings. This means if a key exists in both, the session-specific value takes precedence. If a key only exists in GlobalSettings, it is still available in the session.

    This allows you to define common parameters (like HeartBtInt) once in the [DEFAULT] section and only specify unique identifiers (like TargetCompID) in individual [SESSION] blocks.

  9. Define and use FIX Repeating Groups

    main

    In FIX messaging, a Repeating Group is a collection of repeating sets of fields. To work with them in QuickFIX/Go, you must define a GroupTemplate that specifies the order of fields within each group instance, and then use a RepeatingGroup to manage the collection.

    Core Components

    1. GroupItem: An interface representing a single field or a nested group within a template. Most items are created using GroupElement(tag).
    2. GroupTemplate: A slice of GroupItem that defines the required sequence of tags for every instance in the repeating group.
    3. RepeatingGroup: The main container. It is initialized with a Tag (the NoXXX tag indicating the number of groups) and a GroupTemplate.
    4. Group: An individual instance within the repeating group containing the actual field values.

    Workflow

    • Initialization: Create a template using GroupTemplate and initialize the group with NewRepeatingGroup(tag, template).
    • Adding Data: Use .Add() on the RepeatingGroup to create a new Group instance, then populate it using its underlying FieldMap capabilities.
    • Serialization: Calling .Write() on the RepeatingGroup produces a slice of TagValue containing the count tag followed by all group instances in the correct order.
    • Deserialization: Calling .Read(tagValues) parses the incoming slice into the group structure based on the provided template.
    // 1. Define the template (the order of tags in each group instance)
    template := quickfix.GroupTemplate{
    	quickfix.GroupElement(79),	// Symbol
    	quickfix.GroupElement(44),	// Price
    }
    
    // 2. Create the repeating group (e.g., tag 78 is NoAllocs)
    rg := quickfix.NewRepeatingGroup(78, template)
    
    // 3. Add a new group instance and populate it
    g := rg.Add()
    g.SetString(79, "AAPL")
    g.SetString(44, "150.00")
    
    // 4. Add another instance
    g2 := rg.Add()
    g2.SetString(79, "MSFT")
    g2.SetString(44, "300.00")
    
    // 5. Write to TagValues for transmission
    tvs := rg.Write()
  10. Use FieldMap to manage FIX message fields

    main

    FieldMap is a collection of FIX fields that make up a FIX message. It provides thread-safe methods to get, set, remove, and clear fields. It supports various data types including integers, booleans, strings, UTC timestamps, and repeating groups.

    Key behaviors:

    • Thread Safety: Uses an internal RWMutex to allow concurrent reads and exclusive writes.
    • Type-Specific Helpers: Provides convenience methods like GetInt, GetString, GetBool, and GetTime to avoid manual parsing.
    • Zero-Copy Access: Use GetBytes to access the underlying byte slice of a field without allocation.
    • Group Support: Use GetGroup and SetGroup for handling repeating groups via FieldGroupReader and FieldGroupWriter interfaces.
    // Example of using FieldMap to set and get values
    fm := &quickfix.FieldMap{}
    fm.init()
    
    // Setting values
    fm.SetInt(11, 12345)
    fm.SetString(55, "AAPL")
    fm.SetBool(18, true)
    
    // Getting values
    val, err := fm.GetInt(11)
    str, err := fm.GetString(55)
    b, err := fm.GetBool(18)
    
    if err != nil {
        // Handle MessageRejectError
    }
  11. Identify session-level FIX message types

    main

    In QuickFIX/Go, FIX messages are categorized into session-level (administrative) messages and application-level messages. Session-level messages are used to manage the state of the FIX session (e.g., Logon, Heartbeat, Logout).

    While the internal isAdminMessageType function is not exported, you can identify these messages by checking their MsgType (Tag 35) against the standard FIX administrative codes.

    // Example of identifying a session-level message type via its MsgType value
    // 'A' is the MsgType for Logon
    msgType := []byte("A")
    
    // If msgType matches one of the following, it is an administrative/session message:
    // "0" (Heartbeat)
    // "A" (Logon)
    // "1" (Test Request)
    // "2" (Resend Request)
    // "3" (Reject)
    // "4" (Sequence Reset)
    // "5" (Logout)
  12. Create and initialize a new FIX Message

    main

    Use NewMessage() to create a newly initialized Message instance. A Message is composed of three main sections: Header, Body, and Trailer. Each section is initialized with specific field ordering rules (e.g., the Header ensures tags 8, 9, and 35 appear first, and the Trailer ensures the CheckSum is last).

    import "github.com/quickfixgo/quickfix/quickfix"
    
    msg := quickfix.NewMessage()
    // msg is now ready to have fields added to its Header, Body, or Trailer
    msg := quickfix.NewMessage()