Ticker Plant

MEDIUM • Live C++ Rust Java Python
2M
MESSAGES
20
SYMBOLS
4
EXCHANGES

Problem Description

Normalize 2 million trade messages from 4 exchanges (NYSE, NASDAQ, BATS, IEX) into consolidated 1-second OHLCV bars with VWAP and trade count. Each exchange uses a different message format and timestamp resolution.

Parse exchange-specific pipe-delimited formats, normalize timestamps to seconds, aggregate trades into bars per symbol per second, compute VWAP, and output sorted results.

Tier System & Performance Targets

LANGUAGEGOLDSILVERBRONZE
C++ / Rust< 10000ms< 30000ms< 90000ms
Java< 15000ms< 45000ms< 100000ms
Python< 30000ms< 60000ms< 120000ms

Evaluation Criteria

Correctness: Output must be sorted by timestamp then symbol. Float values (prices, VWAP) are compared with tolerance 0.001. Integer values must match exactly.

Performance: Wall-clock time to process all messages determines tier placement.

Input Format

Read from stdin. The first line is the number of messages N. The next N lines are pipe-delimited trade messages from 4 exchanges, each with a different format:

NYSE|nanoseconds|SYMBOL|price|qty|side
NASDAQ|microseconds|SYMBOL|side|qty|price
BATS|milliseconds|SYMBOL|price|qty|side|trade_id
IEX|seconds.microseconds|SYMBOL|price|qty|side

Key differences:

Output Format

First line: num_symbols num_bars. Then one line per OHLCV bar, sorted by timestamp then symbol:

num_symbols num_bars
timestamp_second symbol open high low close volume vwap trade_count

Where:

Example

Input

4
NYSE|1704067200000000000|AAPL|150.25|500|B
NASDAQ|1704067200000100|AAPL|S|300|150.50
BATS|1704067200100|MSFT|300.00|200|B|T001
IEX|1704067200.500000|AAPL|150.75|400|B

Output

2 2
1704067200 AAPL 150.250000 150.750000 150.250000 150.750000 1200 150.475000 3
1704067200 MSFT 300.000000 300.000000 300.000000 300.000000 200 300.000000 1

All 4 messages fall within the same second. AAPL has 3 trades aggregated into one bar. MSFT has 1 trade. Output is sorted by timestamp then symbol.

Submission Rules

Starter Templates

C++
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

struct Trade {
    long long ts_seconds;
    std::string symbol;
    double price;
    long long qty;
};

struct Bar {
    double open, high, low, close, vwap_num;
    long long volume, count;
};

int main() {
    int N;
    scanf("%d", &N);

    // key = (ts_seconds, symbol)
    std::map<std::pair<long long, std::string>, Bar> bars;
    char line[512];

    for (int i = 0; i < N; i++) {
        scanf(" %[^\n]", line);
        // Parse exchange-specific format:
        // NYSE|ns|SYM|price|qty|side
        // NASDAQ|us|SYM|side|qty|price
        // BATS|ms|SYM|price|qty|side|trade_id
        // IEX|sec.us|SYM|price|qty|side

        // Normalize timestamp to seconds
        // Aggregate into OHLCV bar with VWAP
    }

    // Count unique symbols and bars
    // Output header: num_symbols num_bars
    // Output sorted bars
    return 0;
}
Python
import sys
from collections import defaultdict

N = int(input())

# bars[(ts_sec, symbol)] = {open, high, low, close, volume, vwap_num, count}
bars = {}

for _ in range(N):
    line = input().strip()
    parts = line.split('|')
    exchange = parts[0]

    # Parse based on exchange format
    if exchange == 'NYSE':
        ts_ns = int(parts[1])
        symbol, price, qty, side = parts[2], float(parts[3]), int(parts[4]), parts[5]
        ts_sec = ts_ns // 1_000_000_000
    elif exchange == 'NASDAQ':
        ts_us = int(parts[1])
        symbol, side, qty, price = parts[2], parts[3], int(parts[4]), float(parts[5])
        ts_sec = ts_us // 1_000_000
    elif exchange == 'BATS':
        ts_ms = int(parts[1])
        symbol, price, qty, side = parts[2], float(parts[3]), int(parts[4]), parts[5]
        ts_sec = ts_ms // 1_000
    elif exchange == 'IEX':
        ts_dec = float(parts[1])
        symbol, price, qty, side = parts[2], float(parts[3]), int(parts[4]), parts[5]
        ts_sec = int(ts_dec)

    key = (ts_sec, symbol)
    if key not in bars:
        bars[key] = {'open': price, 'high': price, 'low': price, 'close': price,
                     'volume': qty, 'vwap_num': price * qty, 'count': 1}
    else:
        b = bars[key]
        b['high'] = max(b['high'], price)
        b['low'] = min(b['low'], price)
        b['close'] = price
        b['volume'] += qty
        b['vwap_num'] += price * qty
        b['count'] += 1

symbols = set()
for (ts, sym) in bars:
    symbols.add(sym)

sorted_keys = sorted(bars.keys())
print(f"{len(symbols)} {len(sorted_keys)}")
for (ts, sym) in sorted_keys:
    b = bars[(ts, sym)]
    vwap = b['vwap_num'] / b['volume'] if b['volume'] > 0 else 0
    print(f"{ts} {sym} {b['open']:.6f} {b['high']:.6f} {b['low']:.6f} {b['close']:.6f} {b['volume']} {vwap:.6f} {b['count']}")
Rust
use std::io::{self, BufRead, Write, BufWriter};
use std::collections::BTreeMap;

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut out = BufWriter::new(stdout.lock());
    let mut lines = stdin.lock().lines();

    let n: usize = lines.next().unwrap().unwrap().trim().parse().unwrap();

    // BTreeMap for sorted output: (ts_sec, symbol) -> bar data
    // Parse each exchange format, normalize timestamps, aggregate OHLCV
    // Output: header + sorted bars

    for _ in 0..n {
        let line = lines.next().unwrap().unwrap();
        let parts: Vec<&str> = line.trim().split('|').collect();
        let exchange = parts[0];
        // Parse based on exchange...
    }
}
Java
import java.util.*;
import java.io.*;

public class Solution {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine().trim());

        // TreeMap for sorted output: "ts_sec|symbol" -> bar data
        TreeMap<String, double[]> bars = new TreeMap<>();

        for (int i = 0; i < N; i++) {
            String line = br.readLine().trim();
            String[] parts = line.split("\\|");
            String exchange = parts[0];

            // Parse based on exchange format
            // NYSE: ns, NASDAQ: us, BATS: ms, IEX: decimal seconds
            // Normalize to seconds, aggregate OHLCV + VWAP
        }

        // Output header: num_symbols num_bars
        // Output sorted bars
    }
}

Submit Your Solution

Supported formats: .cpp, .py, .rs, .java, or raw text