package jtrade.io;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.zip.GZIPInputStream;
import jtrade.Symbol;
import jtrade.SymbolFactory;
import jtrade.marketfeed.MarketDepth;
import jtrade.marketfeed.MarketFeed;
import jtrade.marketfeed.Tick;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
public class BinaryTickFileReader extends DataInputStream implements TickReader {
MarketFeed marketFeed;
Symbol symbol;
DateTimeZone tz;
boolean skipMarketDepth;
boolean hasMarketDepth;
int marketDepthLevels;
public BinaryTickFileReader(File file) throws IOException {
this(file, null, false);
}
public BinaryTickFileReader(File file, boolean skipMarketDepth) throws IOException {
this(file, null, skipMarketDepth);
}
public BinaryTickFileReader(File file, MarketFeed marketFeed) throws IOException {
this(file, marketFeed, false);
}
public BinaryTickFileReader(File file, MarketFeed marketFeed, boolean skipMarketDepth) throws IOException {
super(new BufferedInputStream(file.getPath().endsWith(".gz") ? new GZIPInputStream(new FileInputStream(file), 8192) : new FileInputStream(file)));
this.marketFeed = marketFeed;
this.skipMarketDepth = skipMarketDepth;
this.marketDepthLevels = 5;
readHeader();
}
private void readHeader() throws IOException {
StringBuilder sb = new StringBuilder();
char c;
while ((c = readChar()) != '|') {
sb.append(c);
}
symbol = SymbolFactory.getSymbol(sb.toString().toUpperCase().trim());
sb.setLength(0);
while ((c = readChar()) != '|') {
sb.append(c);
}
tz = DateTimeZone.forID(sb.toString().trim());
sb.setLength(0);
while ((c = readChar()) != '|') {
sb.append(c);
}
if (sb.toString().equals("L1")) {
hasMarketDepth = false;
} else if (sb.toString().equals("L2")) {
hasMarketDepth = true;
} else {
throw new IOException("Invalid header");
}
}
@Override
public Tick readTick() throws IOException {
try {
if (!hasMarketDepth) {
return new Tick(symbol, new DateTime(readLong(), tz), readFloat(), readInt(), readFloat(), readInt(), readFloat(), readInt(), readInt(),
null);
}
DateTime dateTime = new DateTime(readLong(), tz);
double askPrice = readFloat();
int askSize = readInt();
double bidPrice = readFloat();
int bidSize = readInt();
double lastPrice = readFloat();
int lastSize = readInt();
int volume = readInt();
if (skipMarketDepth) {
skipBytes(144);
return new Tick(symbol, dateTime, askPrice, askSize, bidPrice, bidSize, lastPrice, lastSize, volume, null);
}
MarketDepth md = new MarketDepth(marketDepthLevels);
double[] askPrices = md.getAskPrices();
int[] askSizes = md.getAskSizes();
askPrices[0] = askPrice;
askSizes[0] = askSize;
for (int p = 1; p < askPrices.length; p++) {
askPrices[p] = readFloat();
askSizes[p] = readInt();
}
skipBytes((10 - marketDepthLevels) * 8);
double[] bidPrices = md.getBidPrices();
int[] bidSizes = md.getBidSizes();
bidPrices[0] = bidPrice;
bidSizes[0] = bidSize;
for (int p = 1; p < bidPrices.length; p++) {
bidPrices[p] = readFloat();
bidSizes[p] = readInt();
}
skipBytes((10 - marketDepthLevels) * 8);
return new Tick(symbol, dateTime, askPrice, askSize, bidPrice, bidSize, lastPrice, lastSize, volume, md);
} catch (EOFException e) {
return null;
}
}
@Override
public NavigableMap<DateTime, Tick> readTicks() throws IOException {
try {
NavigableMap<DateTime, Tick> ticks = new TreeMap<DateTime, Tick>();
Tick t = null;
while ((t = readTick()) != null) {
ticks.put(t.getDateTime(), t);
}
return ticks;
} finally {
try {
close();
} catch (IOException e) {
}
}
}
}