FIX 4.4 Connection Guide

Comprehensive guide to FIX protocol connections, message debugging, and real-world best practices

0. Note

We recommend using the Python client package — it handles all FIX protocol details for you, so you can start papertrading in minutes without reading this guide.

Only come back here if you need to debug at the protocol level or want a deeper understanding of how FIX works under the hood.

1. Connection Prerequisites

Before connecting to FIX, ensure you have all the following information ready:

Account Information

Field Description Example
username Paper Broker login username your_username
password Account password your_password
default_sub_account Default sub-account for trading D1, D2, D3...

FIX Session Information

Field Description Example
sender_comp_id Client identifier (your ID) TRADER-001-FIX
target_comp_id Server identifier PAPERBROKER
socket_connect_host FIX server address localhost / 192.168.1.100
socket_connect_port FIX server port 5001

REST API (Optional)

Field Description Example
rest_base_url REST API base URL http://localhost:9090
Important Note

sender_comp_id must be unique for each client. If two clients use the same sender_comp_id, the session will conflict and connection will fail.

2. Configuration File Setup

QuickFIX uses a configuration file (.cfg) to define session parameters. Below is a detailed breakdown of each setting:

Sample Configuration File

[DEFAULT] ConnectionType=initiator SocketConnectHost=your.server.address SocketConnectPort=5001 StartTime=00:00:00 EndTime=23:59:59 HeartBtInt=30 FileStorePath=logs/fix/client_fix_messages/ FileLogPath=logs/fix/ [SESSION] BeginString=FIX.4.4 SenderCompID=YOUR-CLIENT-ID TargetCompID=SERVER DataDictionary=/path/to/FIX44.xml ResetOnLogon=Y ResetOnLogout=Y ResetOnDisconnect=Y

Configuration Parameters Explained

[DEFAULT] Section

Parameter Description Recommended Value
ConnectionType Client role: initiator (client connects to server) or acceptor (server waits for connections) initiator
SocketConnectHost IP address or hostname of FIX server Your server IP
SocketConnectPort TCP port for FIX connection 5001 (or server-specified)
StartTime Time when session becomes active (UTC) 00:00:00
EndTime Time when session ends (UTC) 23:59:59
HeartBtInt Heartbeat interval in seconds. If no message exchanged within this time, heartbeat is sent 30
FileStorePath Directory to store sequence numbers and message history logs/fix/store/
FileLogPath Directory for FIX message logs logs/fix/

[SESSION] Section

Parameter Description Recommended Value
BeginString FIX protocol version FIX.4.4
SenderCompID Your unique client identifier Assigned by server admin
TargetCompID Server identifier Provided by server
DataDictionary Path to FIX data dictionary XML file /path/to/FIX44.xml
ResetOnLogon Reset sequence numbers on each logon Y
ResetOnLogout Reset sequence numbers on logout Y
ResetOnDisconnect Reset sequence numbers on disconnect Y

DataDictionary - Why It's Critical

The DataDictionary is ESSENTIAL for proper FIX communication!

The DataDictionary (FIX44.xml) defines:

  • Message Structure: Which tags are required, optional, or forbidden for each message type
  • Field Validation: Valid values for each tag (e.g., Side: 1=Buy, 2=Sell)
  • Custom Fields: Any server-specific tags beyond standard FIX 4.4
  • Group Definitions: Repeating groups structure
Common DataDictionary Issues
  • Missing dictionary: Messages rejected with "Invalid tag" errors
  • Wrong version: Using FIX42.xml for FIX 4.4 session causes validation failures
  • Custom fields not defined: Server-specific tags will be rejected

Solution: Always request the exact DataDictionary file from your server administrator.

Optional Validation Settings

Parameter Description When to Use
ValidateFieldsOutOfOrder=N Don't reject messages with tags in wrong order When server sends non-standard tag order
ValidateUserDefinedFields=N Don't validate custom tags (5000+) When server uses custom fields not in dictionary
IgnoreSeqNumTooLow=Y Accept messages with lower-than-expected sequence During development/testing

2. Connection Sequence

FIX connection follows a strict sequence. Understanding this sequence helps you debug connection issues.

Connection Flow

Step 1 - TCP Connect
Client opens TCP connection → Server
Step 2 - Logon Request
Client sends: 35=A (Logon) with Username/Password
Step 3 - Logon Response
Server returns: 35=A (Logon accepted) or 35=3 (Reject)
Step 4 - Heartbeat Loop
35=0 (Heartbeat) exchanged periodically to keep connection alive
Ready!
Session ready to send orders, query data...

Actual Timeline

00:00.000 TCP Connection established 00:00.050 → Sent Logon (35=A) 00:00.120 ← Received Logon (35=A) - Session accepted 00:30.000 → Sent Heartbeat (35=0) 00:30.050 ← Received Heartbeat (35=0) ... Ready to trade ...

4. Message Flow

Each action you perform triggers a chain of messages. Below are the most common flows:

Server Design Note

The intermediate states (PendingNew, PendingCancel) are server design decisions. Some servers send these states, others skip directly to New/Canceled. Always check your server's documentation or test to understand which execution reports you'll receive.

Place Order Flow (Full)

1. Client sends
35=D (NewOrderSingle) 11=CLO001 (ClOrdID - your unique ID)
2. Server acknowledges receipt (Optional)
35=8 (ExecutionReport) 150=A (PendingNew), 39=A (PendingNew) 37=SRV001 (OrderID - server assigned)
3. Order accepted
35=8 (ExecutionReport) 150=0 (New), 39=0 (New) 37=SRV001 (OrderID)
4. When order fills
35=8 (ExecutionReport) 150=F (Fill) or 150=1 (Partial Fill) 39=2 (Filled) or 39=1 (PartiallyFilled)

Cancel Order Flow (Full)

1. Client sends
35=F (OrderCancelRequest) 11=CLO002 (NEW ClOrdID for cancel request) 41=CLO001 (OrigClOrdID - original order's ClOrdID) 37=SRV001 (OrderID - if known)
2. Server acknowledges receipt (Optional)
35=8 (ExecutionReport) 150=6 (PendingCancel), 39=6 (PendingCancel) 37=SRV001 (OrderID)
3. If successful
35=8 (ExecutionReport) 150=4 (Canceled), 39=4 (Canceled) 11=CLO002, 41=CLO001, 37=SRV001
3. If failed
35=9 (OrderCancelReject) 11=CLO002, 41=CLO001, 37=SRV001 58=Order already filled (rejection reason)

Market Data Flow

Client sends
35=V (MarketDataRequest)
Server returns
35=W (MarketDataSnapshot) or 35=Y (MarketDataRequestReject)

ExecType (150) State Reference

Value ExecType Description Server Optional?
A Pending New Order received, not yet accepted Yes - many servers skip this
0 New Order accepted and active No - always sent
1 Partial Fill Order partially executed No
2 or F Fill Order fully executed No
6 Pending Cancel Cancel request received, not yet processed Yes - many servers skip this
4 Canceled Order successfully canceled No
8 Rejected Order rejected No

5. OrderID vs ClOrdID - Critical Difference

Understanding the difference between OrderID and ClOrdID is crucial to avoid ID mismatch errors, especially in cancel/modify flows.

Most Common Bug: ID Mismatch in Cancel Requests

Confusing ClOrdID with OrderID, or using the wrong OrigClOrdID, is the #1 cause of "Order not found" or "Unknown order" rejections.

ID Definitions

Tag Name Who Creates It Purpose
11 ClOrdID Client Your unique identifier for each request. Must be unique per session.
37 OrderID Server Server's internal order identifier. Returned in ExecutionReports.
41 OrigClOrdID Client Used in Cancel/Modify requests to reference the original order's ClOrdID.

ID Flow Example

// Step 1: Place Order CLIENT → 35=D | 11=MY-ORD-001 | 55=VNM | 54=1 | 38=100 | 44=85000 // Step 2: Server confirms (PendingNew - optional) SERVER ← 35=8 | 11=MY-ORD-001 | 37=SRV-123456 | 150=A | 39=A // Step 3: Server confirms (New) SERVER ← 35=8 | 11=MY-ORD-001 | 37=SRV-123456 | 150=0 | 39=0 // Step 4: Cancel Request - NOTE THE IDs! CLIENT → 35=F | 11=MY-CANCEL-001 | 41=MY-ORD-001 | 37=SRV-123456 ↑ NEW ClOrdID ↑ ORIGINAL ClOrdID ↑ Server's OrderID // Step 5: Cancel confirmed SERVER ← 35=8 | 11=MY-CANCEL-001 | 41=MY-ORD-001 | 37=SRV-123456 | 150=4 | 39=4

Common ID Mistakes

Mistake 1: Reusing ClOrdID for Cancel
❌ WRONG: 35=F | 11=MY-ORD-001 | 41=MY-ORD-001 Same ID for both fields! ✓ CORRECT: 35=F | 11=MY-CANCEL-001 | 41=MY-ORD-001 New unique ID Original order ID

Each request (order, cancel, modify) must have a unique ClOrdID.

Mistake 2: Using OrderID as OrigClOrdID
❌ WRONG: 35=F | 11=MY-CANCEL-001 | 41=SRV-123456 Using server's OrderID! ✓ CORRECT: 35=F | 11=MY-CANCEL-001 | 41=MY-ORD-001 Using YOUR original ClOrdID

OrigClOrdID (41) must be the ClOrdID you sent, not the server's OrderID.

Mistake 3: Not Storing OrderID

Some servers require OrderID (37) in cancel requests. If you don't store it from the ExecutionReport, your cancel will fail.

// Best practice: Store mapping when you receive ExecutionReport order_map = { "MY-ORD-001": { # Your ClOrdID "order_id": "SRV-123456", # Server's OrderID "status": "New" } }

Best Practice: ID Management

Recommended ID Strategy
  • ClOrdID format: {prefix}-{timestamp}-{counter} (e.g., ORD-20260212093000-001)
  • Always unique: Never reuse ClOrdID within a session
  • Store mapping: Keep a map of ClOrdID → OrderID from ExecutionReports
  • Cancel/Modify: Generate new ClOrdID, use stored original as OrigClOrdID

6. Reading FIX Messages

FIX messages have a special format: Tag=Value separated by SOH (ASCII 01). In log files, SOH is typically displayed as | or ^A.

FIX Message Structure

8=FIX.4.4|9=148|35=D|49=CLIENT-FIX|56=SERVER|34=2|52=20260212-09:30:00| 11=ORD001|21=1|55=VNM|54=1|60=20260212-09:30:00|38=100|40=2|44=85000|10=123|

Field Breakdown:

Tag Name Value Meaning
8 BeginString FIX.4.4 FIX protocol version
9 BodyLength 148 Message body length
35 MsgType D NewOrderSingle (new order)
49 SenderCompID CLIENT-FIX Sender identifier
56 TargetCompID SERVER Receiver identifier
34 MsgSeqNum 2 Message sequence number
11 ClOrdID ORD001 Client Order ID (you generate this)
55 Symbol VNM Stock symbol
54 Side 1 1=Buy, 2=Sell
38 OrderQty 100 Quantity
40 OrdType 2 2=Limit order
44 Price 85000 Order price
10 CheckSum 123 Checksum for message verification
Tip: Quick message reading

Always read 35= (MsgType) first to identify the message type. Then check the relevant tags based on that type.

7. Important Debug Fields

When debugging FIX messages, focus on these key tags:

Tag 35 - MsgType (Message Type)

Value Name Description
A Logon Session login
0 Heartbeat Keep-alive message
5 Logout Session logout
D NewOrderSingle New order placement
F OrderCancelRequest Order cancellation request
G OrderCancelReplaceRequest Order modification
8 ExecutionReport Order execution result
9 OrderCancelReject Cancel request rejected
3 Reject Message rejected (format error)
V MarketDataRequest Market data request
W MarketDataSnapshot Market data response

Tag 39 - OrdStatus (Order Status)

Value Status Description
0 New New order accepted
1 Partially Filled Partially filled
2 Filled Fully filled
4 Canceled Order canceled
8 Rejected Order rejected

Tag 150 - ExecType (Execution Type)

Value Type Description
0 New New order created
1 Partial Fill Partially filled
2 or F Fill Fully filled
4 Canceled Successfully canceled
8 Rejected Order rejected

Tag 58 - Text (Error Message)

This is the MOST IMPORTANT tag when debugging!

When you receive a Reject (35=3) or ExecutionReport with Rejected status, always read tag 58 for the detailed reason.

35=8|39=8|150=8|58=Insufficient funds for order|...

8. Common Issues & Solutions

Session Timeout / Disconnect

Symptoms: Sudden disconnection, no heartbeat response received

Causes:

  • Not sending heartbeat at correct interval (default 30s)
  • Network issue / Firewall block
  • Server overload

Solutions:

  • Check HeartBtInt setting (tag 108 in Logon)
  • Implement reconnect logic with exponential backoff
  • Check firewall rules for FIX port
Sequence Number Gap / Reset Required

Symptoms: Receiving ResendRequest (35=2) or SequenceReset (35=4)

Causes:

  • Client restart without sequence reset
  • Messages lost during transmission
  • Sequence file corrupted

Solutions:

  • Send Logon with ResetSeqNumFlag=Y (tag 141=Y)
  • Delete sequence files and reconnect
  • Check message store configuration
Order Rejected

Symptoms: ExecutionReport with 39=8 (Rejected)

Common causes:

  • 58=Insufficient funds - Not enough cash
  • 58=Invalid symbol - Invalid stock symbol
  • 58=Price out of range - Price outside allowed range
  • 58=Quantity invalid - Invalid quantity (must be divisible by lot size)
  • 58=Market closed - Market is closed

Solution: Read tag 58 carefully for the specific reason

Session Reject (35=3)

Symptoms: MsgType=3 with SessionRejectReason

Causes:

  • Tag 373=1: Invalid tag number
  • Tag 373=5: Value incorrect for tag
  • Tag 373=9: CompID problem
  • Tag 373=11: Invalid MsgType

Solutions:

  • Check RefSeqNum (tag 45) to identify which message was rejected
  • Check RefTagID (tag 371) to identify which tag has problem
  • Verify message format against FIX 4.4 spec

9. Experience & Best Practices

Logging Strategy
  • Log ALL messages: Both outgoing and incoming
  • Timestamp: Include microseconds to debug timing issues
  • Pretty print: Convert SOH → | for readability in logs
  • Separate log files: Keep FIX messages separate from application logs
# Example log format 2026-02-12 09:30:00.123456 OUT: 35=D|11=ORD001|55=VNM|... 2026-02-12 09:30:00.234567 IN: 35=8|11=ORD001|39=0|150=0|...
Connection Management
  • Wait for Logon: Always wait for Logon response before sending orders
  • Retry with backoff: 1s → 2s → 4s → 8s → max 30s
  • Health check: Monitor heartbeat response time
  • Graceful shutdown: Send Logout (35=5) before disconnecting
ClOrdID Best Practices
  • Unique: Use UUID or timestamp-based ID
  • Traceable: Include prefix for easy log searching
  • No reuse: Each order must have a different ClOrdID
# Recommended format ClOrdID = f"ORD-{timestamp}-{random_suffix}" # Example: ORD-20260212093000-A1B2C3
Error Handling
  • Always check OrdStatus: Don't assume order success
  • Handle partial fills: Track CumQty and LeavesQty
  • Timeout handling: Set timeout for each order, cancel if expired
  • Idempotency: Implement to handle duplicate responses
Pro Tip

When debugging, build a simple tool to parse FIX messages into readable format. This will save significant time when handling production issues.

Back to Docs API Reference Examples