AlgoDaily

Lesson 5: Working with FIX API in C++

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

Final API Bridge

From signals to orders

In Lesson 2, you read Gmail messages. In Lesson 3, you turned message text into structured BUY / SELL signals. In Lesson 4, you learned the REST request-response style.

Now we finish the course with FIX API, the protocol many brokers, exchanges, and institutional trading systems use for order routing and execution reports.

The big shift:

REST: ask a server, receive a response
FIX: keep a session open, exchange ordered trading messages

By the end of this lesson, you will understand the shape of FIX messages, how C++ can build and parse them, and how FIX fits into your trading pipeline.

Final API Bridge

FIX Versus REST

Same goal, different rhythm

REST and FIX can both move trading information, but they feel very different in code.

REST style
  • Usually stateless
  • One request gets one response
  • URLs and JSON are common
  • Great for account info, historical data, simple order APIs
FIX style
  • Usually persistent TCP session
  • Messages are sequenced
  • Uses compact tag=value fields
  • Built for fast order routing, fills, cancels, and session recovery

A useful mental model:

REST: "Here is my request. What is the answer?"
FIX:  "We have a live trading conversation. Every message is numbered."

For algorithmic trading in C++, FIX matters because your program often needs to stay connected, maintain sequence numbers, handle heartbeats, and react to execution reports continuously.

FIX Versus REST

Message Anatomy

FIX is tag-value text

A FIX message is a sequence of fields:

tag=value<delimiter>tag=value<delimiter>...

The real delimiter is the ASCII SOH character, often displayed as | in logs.

Common tags:

Tag Meaning 8 BeginString, such as FIX.4.4 9 BodyLength 35 MsgType 34 MsgSeqNum 49 SenderCompID 56 TargetCompID 52 SendingTime 10 CheckSum

Example message type values:

35 Meaning A Logon 0 Heartbeat D NewOrderSingle 8 ExecutionReport

The following standalone C++ example builds a simple NewOrderSingle and computes BodyLength and CheckSum.

```cpp
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <utility>

const std::string SOH = "\x01";

std::string joinFields(const std::vector<std::pair<std::string, std::string>>& fields) {
    std::string out;
    for (const auto& [tag, value] : fields) {
        out += tag + "=" + value + SOH;
    }
    return out;
}

std::string checksum(const std::string& data) {
    unsigned int sum = 0;
    for (unsigned char c : data) sum += c;

    std::ostringstream oss;
    oss << std::setw(3) << std::setfill('0') << (sum % 256);
    return oss.str();
}

std::string visibleFix(std::string msg) {
    for (char& c : msg) {
        if (c == '\x01') c = '|';
    }
    return msg;
}

int main() {
    std::vector<std::pair<std::string, std::string>> bodyFields = {
        {"35", "D"},                 // NewOrderSingle
        {"34", "1"},                 // sequence number
        {"49", "MY_TRADER"},
        {"56", "BROKER"},
        {"52", "20250115-14:30:00.000"},
        {"11", "ORDER-1001"},         // client order id
        {"55", "AAPL"},               // symbol
        {"54", "1"},                  // 1 = buy, 2 = sell
        {"38", "100"},                // order quantity
        {"40", "2"},                  // 2 = limit order
        {"44", "185.25"},             // price
        {"59", "0"}                   // day order
    };

    std::string body = joinFields(bodyFields);
    std::string header = "8=FIX.4.4" + SOH + "9=" + std::to_string(body.size()) + SOH;
    std::string withoutChecksum = header + body;
    std::string fixMessage = withoutChecksum + "10=" + checksum(withoutChecksum) + SOH;

    std::cout << "Human-readable FIX:\n" << visibleFix(fixMessage) << "\n";
    std::cout << "BodyLength: " << body.size() << "\n";
    std::cout << "CheckSum: " << checksum(withoutChecksum) << "\n";
}
```

Protocol Check

In a trading system, which description best matches FIX compared with the REST style from Lesson 4?

Session Lifecycle

FIX is not just one message

A FIX connection has a session lifecycle. Your C++ program is not only sending orders; it is also keeping the conversation healthy.

Typical flow:

Connect TCP/TLS
   ↓
Send Logon              35=A
   ↓
Exchange Heartbeats     35=0
   ↓
Send NewOrderSingle     35=D
   ↓
Receive ExecutionReport 35=8
   ↓
Logout / reconnect if needed

Important session responsibilities:

  • Track outgoing MsgSeqNum with tag 34
  • Detect missing incoming sequence numbers
  • Send or respond to heartbeats
  • Recover with resend logic when messages are missed
  • Log raw inbound and outbound messages for audit/debugging

For a production trading system, teams often use a mature engine such as QuickFIX or a broker-provided SDK. Still, understanding the message mechanics makes you a much stronger C++ API developer.

Session Lifecycle

Checksum Claim

True or false: FIX CheckSum tag 10 is calculated by including the bytes of the 10=... checksum field itself.

Parse Incoming FIX

Execution reports complete the loop

In earlier lessons, your pipeline produced a structured trading signal. With FIX, after you send an order, the broker responds with messages such as ExecutionReport.

An execution report might tell you:

  • Order accepted
  • Partially filled
  • Fully filled
  • Rejected
  • Canceled

Below is a simple parser that accepts either real SOH-delimited FIX or log-style |-delimited FIX. It extracts key fields from an ExecutionReport.

```cpp
#include <iostream>
#include <map>
#include <sstream>
#include <string>

std::map<std::string, std::string> parseFix(const std::string& message) {
    std::map<std::string, std::string> fields;
    std::string token;

    for (char c : message) {
        if (c == '\x01' || c == '|') {
            if (!token.empty()) {
                std::size_t eq = token.find('=');
                if (eq != std::string::npos) {
                    fields[token.substr(0, eq)] = token.substr(eq + 1);
                }
                token.clear();
            }
        } else {
            token += c;
        }
    }

    return fields;
}

std::string sideName(const std::string& side) {
    if (side == "1") return "BUY";
    if (side == "2") return "SELL";
    return "UNKNOWN";
}

std::string statusName(const std::string& status) {
    if (status == "0") return "NEW";
    if (status == "1") return "PARTIALLY_FILLED";
    if (status == "2") return "FILLED";
    if (status == "8") return "REJECTED";
    return "UNKNOWN";
}

int main() {
    std::string msg =
        "8=FIX.4.4|9=150|35=8|34=2|49=BROKER|56=MY_TRADER|"
        "52=20250115-14:30:01.000|11=ORDER-1001|17=EXEC-9001|"
        "55=AAPL|54=1|39=1|150=1|14=40|151=60|32=40|31=185.25|10=123|";

    auto fields = parseFix(msg);

    std::cout << "MsgType: " << fields["35"] << "\n";
    std::cout << "Symbol: " << fields["55"] << "\n";
    std::cout << "Side: " << sideName(fields["54"]) << "\n";
    std::cout << "Status: " << statusName(fields["39"]) << "\n";
    std::cout << "CumQty: " << fields["14"] << "\n";
    std::cout << "LeavesQty: " << fields["151"] << "\n";
    std::cout << "LastPx: " << fields["31"] << "\n";
}
```

Delimiter Blank

FIX fields are separated by the ASCII control character usually called ____.

Order State

Convert reports into state

Your algorithm should not treat execution reports as random strings. It should update an internal order state.

Think back to Lesson 3, where text became a validated BUY or SELL intent. In FIX, broker reports become validated order state:

Signal → NewOrderSingle → ExecutionReport → OrderState

This example applies multiple execution reports to one order and logs the changing state.

```cpp
#include <iostream>
#include <map>
#include <string>
#include <vector>

std::map<std::string, std::string> parseFix(const std::string& message) {
    std::map<std::string, std::string> fields;
    std::string token;

    for (char c : message) {
        if (c == '|' || c == '\x01') {
            auto eq = token.find('=');
            if (eq != std::string::npos) fields[token.substr(0, eq)] = token.substr(eq + 1);
            token.clear();
        } else {
            token += c;
        }
    }
    return fields;
}

struct OrderState {
    std::string clOrdId;
    std::string symbol;
    int cumQty = 0;
    int leavesQty = 0;
    std::string status = "UNKNOWN";
};

std::string statusName(const std::string& status) {
    if (status == "0") return "NEW";
    if (status == "1") return "PARTIALLY_FILLED";
    if (status == "2") return "FILLED";
    if (status == "8") return "REJECTED";
    return "UNKNOWN";
}

void applyExecutionReport(OrderState& state, const std::map<std::string, std::string>& f) {
    if (f.at("35") != "8") return; // only ExecutionReport here

    state.clOrdId = f.at("11");
    state.symbol = f.at("55");
    state.status = statusName(f.at("39"));
    state.cumQty = std::stoi(f.at("14"));
    state.leavesQty = std::stoi(f.at("151"));

    std::cout << "Order " << state.clOrdId
              << " " << state.symbol
              << " status=" << state.status
              << " cumQty=" << state.cumQty
              << " leavesQty=" << state.leavesQty
              << "\n";
}

int main() {
    std::vector<std::string> reports = {
        "35=8|11=ORDER-1001|55=AAPL|39=0|14=0|151=100|",
        "35=8|11=ORDER-1001|55=AAPL|39=1|14=40|151=60|",
        "35=8|11=ORDER-1001|55=AAPL|39=2|14=100|151=0|"
    };

    OrderState state;
    for (const auto& raw : reports) {
        applyExecutionReport(state, parseFix(raw));
    }

    std::cout << "Final state: " << state.status << "\n";
}
```

Course Wrap

You now have the API map

Across this section, you built a practical mental model for C++ trading APIs:

  1. Lesson 1: Introduction to API in C++
    APIs are contracts. Your C++ code must respect request/response shapes, errors, and data formats.

  2. Lesson 2: Reading Gmail API in C++
    You learned how external messages can enter your program through an authenticated API.

  3. Lesson 3: Parsing Buy and Sell Signals in C++
    You transformed raw text into structured trading intent.

  4. Lesson 4: Working with REST APIs in C++
    You connected to HTTP-style services and handled status codes, retries, and client structure.

  5. Lesson 5: Working with FIX API in C++
    You saw how orders and fills move through persistent, sequenced FIX sessions.

Your end-to-end architecture can now look like this:

Gmail alert
  → parse signal
  → validate risk rules
  → optionally call REST data/account APIs
  → send FIX order
  → parse execution reports
  → update order state and logs

Final trading-engine checklist:

  • Validate every signal before sending an order
  • Log raw API/FIX messages safely
  • Treat network failures as normal, not surprising
  • Keep sequence numbers and order state consistent
  • Test with a broker simulator before real capital
  • Prefer mature libraries for production FIX connectivity

That is the core journey: from external data to reliable C++ trading actions.

Course Wrap

Open interactive view →