FIX Protocol Parser
Problem Description
Parse 1,000,000 FIX 4.2 protocol messages, validate fields, and extract key order data. Handle multiple message types including NewOrderSingle, ExecutionReport, OrderCancelRequest, and others. Validate field presence, data types, and checksums.
Output summary statistics: total messages, valid/invalid counts, message type distribution, and extracted order data aggregates.
Tier System & Performance Targets
| LANGUAGE | GOLD | SILVER | BRONZE |
|---|---|---|---|
| C++ / Rust | < 300ms | < 1000ms | < 5000ms |
| Java | < 600ms | < 2000ms | < 10000ms |
| Python | < 2000ms | < 5000ms | < 30000ms |
Evaluation Criteria
Correctness: 12 output lines are compared against the reference. Integer lines must match exactly. Float values (VWAP) use tolerance. String values must match exactly.
Performance: Wall-clock time to parse all messages determines tier placement.
Input Format
Read from stdin. The first line is the number of messages N. The next N lines are FIX-format messages with pipe (|) delimiters:
8=FIX.4.2|35=D|49=SENDER|56=TARGET|11=ORD001|55=AAPL|54=1|38=100|44=150.00|10=100|
Key FIX tags:
35(MsgType): D=NewOrderSingle, 8=ExecutionReport, F=OrderCancelRequest55(Symbol): Trading symbol54(Side): 1=Buy, 2=Sell38(OrderQty): Order quantity44(Price): Limit price39(OrdStatus): 0=New, 1=PartiallyFilled, 2=Filled, 4=Canceled, 8=Rejected10(CheckSum): Message checksum
Output Format
Output exactly 12 lines to stdout (plain values, one per line):
TOTAL_MESSAGES
UNIQUE_ORDERS
FULLY_FILLED
PARTIALLY_FILLED
CANCELED
REJECTED
TOTAL_BUY
TOTAL_SELL
TOTAL_FILLED_QTY
VWAP
UNIQUE_SYMBOLS
SYMBOL_MAX
Where:
- Lines 1-9, 11: Integer values
- Line 10 (
VWAP): Float with 6 decimal places - Line 12 (
SYMBOL_MAX): Symbol string with highest filled quantity
Example
Input
3
8=FIX.4.2|35=D|49=CLIENT1|56=BROKER|11=ORD001|55=AAPL|54=1|38=100|44=150.00|10=100|
8=FIX.4.2|35=8|49=BROKER|56=CLIENT1|11=ORD001|55=AAPL|54=1|38=100|44=150.00|39=2|32=100|31=150.00|10=101|
8=FIX.4.2|35=D|49=CLIENT2|56=BROKER|11=ORD002|55=MSFT|54=2|38=50|44=300.50|10=102|
Output
3
2
1
0
0
0
1
1
100
150.000000
2
AAPL
12 plain values: total messages, unique orders, fully filled, partially filled, canceled, rejected, buy count, sell count, filled qty, VWAP, unique symbols, top symbol by filled qty.
Submission Rules
- Your program receives input via stdin
- Output 12 lines to stdout (integers, one float, one string)
- Program must complete within 120 seconds
- Memory usage must not exceed 2GB
- Single-file solutions only
- Java class must be named
Solution
Starter Templates
C++
#include <cstdio>
#include <cstring>
#include <unordered_map>
struct FIXMessage {
char begin_string[20];
int body_length;
char msg_type[4];
char sender[20];
char target[20];
char symbol[10];
char side;
int order_qty;
double price;
char checksum[10];
};
int main() {
// Read FIX messages from stdin
// Parse and validate each message
// Track statistics
// Output summary
return 0;
}
Python
import sys
from collections import defaultdict
def parse_fix_message(line):
# Replace SOH with pipe or parse directly
fields = line.split('|')
message = {}
for field in fields:
if '=' in field:
tag, value = field.split('=', 1)
message[tag] = value
return message
stats = {
'total': 0,
'valid': 0,
'invalid': 0,
'msg_types': defaultdict(int),
'total_qty': 0,
'total_value': 0.0
}
for line in sys.stdin:
msg = parse_fix_message(line.strip())
stats['total'] += 1
# Validate message
# Extract order data
# Update statistics
# Output stats
Rust
use std::io::{self, BufRead};
use std::collections::HashMap;
struct FIXMessage {
fields: HashMap<String, String>,
}
fn parse_fix_message(line: &str) -> FIXMessage {
let mut fields = HashMap::new();
for part in line.split('|') {
if let Some(pos) = part.find('=') {
let (tag, value) = part.split_at(pos);
fields.insert(tag.to_string(), value[1..].to_string());
}
}
FIXMessage { fields }
}
fn main() {
let stdin = io::stdin();
let mut total = 0;
let mut valid = 0;
for line in stdin.lock().lines() {
if let Ok(line) = line {
let msg = parse_fix_message(&line);
total += 1;
// Validate and extract data
}
}
}
Java
import java.util.*;
import java.io.*;
public class Solution {
static class FIXMessage {
Map<String, String> fields = new HashMap<>();
}
static FIXMessage parseMessage(String line) {
FIXMessage msg = new FIXMessage();
String[] parts = line.split("\\|");
for (String part : parts) {
String[] kv = part.split("=", 2);
if (kv.length == 2) {
msg.fields.put(kv[0], kv[1]);
}
}
return msg;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int total = 0, valid = 0;
Map<String, Integer> msgTypes = new HashMap<>();
String line;
while ((line = br.readLine()) != null) {
FIXMessage msg = parseMessage(line);
total++;
// Validate and extract data
}
}
}