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.

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=valuefields - 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.

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 Meaning8
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
MsgSeqNumwith tag34 - 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.

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:
Lesson 1: Introduction to API in C++
APIs are contracts. Your C++ code must respect request/response shapes, errors, and data formats.Lesson 2: Reading Gmail API in C++
You learned how external messages can enter your program through an authenticated API.Lesson 3: Parsing Buy and Sell Signals in C++
You transformed raw text into structured trading intent.Lesson 4: Working with REST APIs in C++
You connected to HTTP-style services and handled status codes, retries, and client structure.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.
