#ifndef __GTS_H__ #define __GTS_H__ #include #include using namespace std; #pragma pack(1) struct Header { uint16_t m_packetLength; // Length of the entire packet (Including this data member). uint16_t m_numUpdates; // Number of market updates in this packet. void print() { cout << "Header: PacketLen: " << m_packetLength << " numUpdates: " << m_numUpdates << endl; } }; struct Base { uint16_t m_messageLength; // Length of the entire market update (Including this data member). char m_type; // 'T', 'Q' void print() { cout << "Base: MsgLen: " << m_messageLength << " type: " << m_type << endl; } }; struct Quote { char m_symbol[5]; // Alpha Left-justified string with spaces filling the unused bytes. uint16_t m_priceLevel; // Integer Zero-indexed price level to apply this update. uint16_t m_size; // Integer New size of price level (given in round lots 100's). uint64_t m_price; // New price of price level (see below*). //char m_reserved; // Dynamic Alpha Reserved data; can be ignored. void print() { string symbol(m_symbol, 5); cout << "Quote: " << " symbol: " << symbol << " priceLev: " << m_priceLevel << " size: " << m_size << " price: " << m_price << endl; } }; struct Trade { char m_symbol[5]; // Alpha Left-justified string with spaces filling the unused bytes. uint16_t m_size; // Integer New size of price level (given in round lots 100's). uint64_t m_price; // New price of price level (see below*). //char m_reserved; // Dynamic Alpha Reserved data; can be ignored void print() { string symbol(m_symbol, 5); cout << "Trade: " << " symbol: " << symbol << " size: " << m_size << " price: " << m_price << endl; } }; struct Parser { ifstream m_stream; size_t m_packetNum; Parser(const string& file) : m_stream(file, ios::binary), m_packetNum(0) {} void parse() { while (m_stream.peek() != EOF) { m_packetNum++; cout << "---------------------------------\n"; cout << "PacketNum: " << m_packetNum << endl; cout << "---------------------------------\n"; Header headerIn, headerOut; m_stream.read(reinterpret_cast(&headerIn), sizeof(Header)); if (!m_stream.good()) cerr << "error reading header" << endl; headerOut.m_packetLength = bswap_16(headerIn.m_packetLength); headerOut.m_numUpdates = bswap_16(headerIn.m_numUpdates); for (uint16_t i = 0; i < headerOut.m_numUpdates; i++) { Base baseIn, baseOut; m_stream.read(reinterpret_cast(&baseIn), sizeof(Base)); if (!m_stream.good()) cerr << "error reading Base" << endl; baseOut.m_messageLength = bswap_16(baseIn.m_messageLength); baseOut.m_type = baseIn.m_type; switch(baseOut.m_type) { case 'T': parseTrade(baseOut.m_messageLength); break; case 'Q': parseQuote(baseOut.m_messageLength); break; default: cerr << "Unknown MessageType" << endl; } } } } void printReserved() { size_t pos = 0; char c = m_stream.peek(); cout << "peek: "; while (c >= 'A' && c <= 'Z') { cout << c; m_stream.seekg(1, ios_base::cur); c = m_stream.peek(); pos++; } cout << endl; m_stream.seekg(-pos, ios_base::cur); } void parseTrade(uint16_t messageLength) { Trade tradeIn, tradeOut; m_stream.read(reinterpret_cast(&tradeIn), sizeof(Trade)); if (!m_stream.good()) cerr << "error reading trade" << endl; strncpy(tradeOut.m_symbol, tradeIn.m_symbol, 5); tradeOut.m_size = bswap_16(tradeIn.m_size); tradeOut.m_price = bswap_64(tradeIn.m_price) / 10000; tradeOut.print(); // ignore reserved size_t reservedSize = messageLength - (sizeof(Trade) + sizeof(Base)); m_stream.seekg(reservedSize, ios_base::cur); } void parseQuote(uint16_t messageLength) { Quote quoteIn, quoteOut; m_stream.read(reinterpret_cast("eIn), sizeof(Quote)); if (!m_stream.good()) cerr << "error reading quote" << endl; strncpy(quoteOut.m_symbol, quoteIn.m_symbol, 5); quoteOut.m_priceLevel = bswap_16(quoteIn.m_priceLevel); quoteOut.m_size = bswap_16(quoteIn.m_size); quoteOut.m_price = bswap_64(quoteIn.m_price) / 10000; quoteOut.print(); // ignore reserved size_t reservedSize = messageLength - (sizeof(Quote) + sizeof(Base)); m_stream.seekg(reservedSize, ios_base::cur); } }; #endif