Skip to content

Instantly share code, notes, and snippets.

@khayrov
Created July 21, 2012 20:40
Show Gist options
  • Save khayrov/3157086 to your computer and use it in GitHub Desktop.
Save khayrov/3157086 to your computer and use it in GitHub Desktop.
stock quote parsing with Ragel
CFLAGS=-O2
CXXFLAGS=-O2
all: parser
parser.cpp: parser.rl
ragel -G2 $^ -o $@
parser.o: parser.cpp RawQuote.h
RawQuote.o: RawQuote.cpp RawQuote.h
parser: parser.o RawQuote.o
g++ $^ -o $@
.PHONY: clean
clean:
rm -f parser parser.cpp *.o
#include <string>
#include <iostream>
#include "RawQuote.h"
/**
Fields:
1003 - Symbol
2002 - Last
2003 - Bid
2004 - Ask
2005 - Bid Size
2006 - Ask Size
2007 - Last Size
2008 - Yesterday?s close
2009 - The High for today
2010 - The Low for today
2011 - The Open for today
2012 - The total volume traded for today
2013 - Uptick/Downtick
Uptick - 20020
Downtick - 20021
2014 - TimeStamp (HH:MM:SS)
2015 - Date (MM/DD/YYYY)
**/
%%{
machine quote;
write data;
}%%
bool ParseQuote(const std::string &message, RawQuote &quote)
{
int cs;
const char *p = message.data(), *pe = message.data() + message.size();
const char *symstart;
int intval;
double realval;
double intpart, fracpart, tenpow;
#define ASSIGN_INT(fieldname) quote.fieldname = intval; quote.has##fieldname = true;
#define ASSIGN_REAL(fieldname) quote.fieldname = realval; quote.has##fieldname = true;
%%{
integer = ( digit @ { intval = intval * 10 + (fc - '0'); } )+
> { intval = 0; } ;
intpart = ( digit @ { intpart = intpart * 10 + (fc - '0'); } )+
> { intpart = 0.0; } ;
fracpart = ( digit @ { fracpart += (fc - '0') * tenpow; tenpow *= 0.1; } )+
> { fracpart = 0.0; tenpow = 0.1; } ;
real = intpart @ { realval = intpart; }
| (intpart '.' fracpart ) @ { realval = intpart + fracpart; };
symbol = '1003=' (
[^;]+
> { symstart = p; }
@ { quote.Symbol.assign(symstart, p + 1); quote.hasSymbol = true; }
) ;
last = '2002=' real @ { ASSIGN_REAL(Last); } ;
bid = '2003=' real @ { ASSIGN_REAL(Bid); } ;
ask = '2004=' real @ { ASSIGN_REAL(Ask); } ;
bidsize = '2005=' integer @ { ASSIGN_INT(BidSize); } ;
asksize = '2006=' integer @ { ASSIGN_INT(AskSize); } ;
lastsize = '2007=' integer @ { ASSIGN_INT(LastSize); } ;
close = '2008=' real @ { ASSIGN_REAL(Close); } ;
high = '2009=' real @ { ASSIGN_REAL(High); } ;
low = '2010=' real @ { ASSIGN_REAL(Low); } ;
open = '2011=' real @ { ASSIGN_REAL(Open); } ;
total = '2012=' real @ { ASSIGN_REAL(Volume); } ;
uptick = '2013=' (
'20020' @ { quote.Uptick = true; } |
'20021' @ { quote.Uptick = false; }
) @ { quote.hasUptick = true; } ;
timestamp = '2014='
integer @ { ASSIGN_INT(Hour); } ':'
integer @ { ASSIGN_INT(Minute); } ':'
integer @ { ASSIGN_INT(Second); } ;
date = '2015='
integer @ { ASSIGN_INT(Month); } '/'
integer @ { ASSIGN_INT(Day); } '/'
integer @ { ASSIGN_INT(Year); } ;
genericfield = digit+ '=' [^;]+ ;
field = symbol | last | bid | ask | bidsize | asksize | lastsize |
close | high | low | open | total | uptick |
timestamp | date |
genericfield ;
main := '1|' (field ';')* field ;
write init;
write exec;
}%%
#undef ASSIGN_INT
#undef ASSIGN_REAL
return cs >= %%{ write first_final; }%%;
}
int main()
{
std::string message = "1|2025=US;2026=USD;1003=EUR/USD;2087=10070;2089=0;2042=FX;2090=0;2002=1.21899;2003=1.21899;2004=1.21907;2005=500000;2006=1000000;2007=150;2008=1.22376;2009=1.22479;2010=1.21842;2011=1.22377;2012=28603324;2013=20021;2014=06:43:15;2015=07/12/2012";
RawQuote quote;
bool result;
for (int i = 0; i < 1000000; ++i)
{
result = ParseQuote(message, quote);
}
std::cout << (result ? "Success" : "Failure") << std::endl
<< quote;
}
#include <ostream>
#include "RawQuote.h"
std::ostream &operator <<(std::ostream &os, const RawQuote &quote)
{
#define PRINT_FIELD(fieldname) if (quote.has##fieldname) { \
os << #fieldname << " = " << quote.fieldname << '\n'; \
}
PRINT_FIELD(Symbol);
PRINT_FIELD(Last);
PRINT_FIELD(Bid);
PRINT_FIELD(Ask);
PRINT_FIELD(BidSize);
PRINT_FIELD(AskSize);
PRINT_FIELD(LastSize);
PRINT_FIELD(Close);
PRINT_FIELD(High);
PRINT_FIELD(Low);
PRINT_FIELD(Open);
PRINT_FIELD(Volume);
PRINT_FIELD(Uptick);
PRINT_FIELD(Hour);
PRINT_FIELD(Minute);
PRINT_FIELD(Second);
PRINT_FIELD(Month);
PRINT_FIELD(Day);
PRINT_FIELD(Year);
#undef PRINT_FIELD
}
#ifndef RAWQUOTE_H
#define RAWQUOTE_H
#include <string>
#include <ostream>
struct RawQuote
{
std::string Symbol;
double Last;
double Bid;
double Ask;
int BidSize;
int AskSize;
int LastSize;
double Close;
double High;
double Low;
double Open;
double Volume;
bool Uptick;
int Hour;
int Minute;
int Second;
int Month;
int Day;
int Year;
bool hasSymbol;
bool hasLast;
bool hasBid;
bool hasAsk;
bool hasBidSize;
bool hasAskSize;
bool hasLastSize;
bool hasClose;
bool hasHigh;
bool hasLow;
bool hasOpen;
bool hasVolume;
bool hasUptick;
bool hasHour;
bool hasMinute;
bool hasSecond;
bool hasMonth;
bool hasDay;
bool hasYear;
};
std::ostream &operator <<(std::ostream &os, const RawQuote &quote);
#endif // RAWQUOTE_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment