package jtrade.io; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.NavigableMap; import java.util.zip.GZIPOutputStream; import jtrade.marketfeed.MarketDepth; import jtrade.marketfeed.Tick; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; public class CsvTickFileWriter extends BufferedWriter implements TickWriter { private static final String dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"; protected String source; protected boolean headerWritten; protected DateTimeFormatter dateFormatter; public CsvTickFileWriter(File file, boolean append, String source) throws IOException { this(file, append, false, source); } public CsvTickFileWriter(File file, boolean append, boolean compress, String source) throws IOException { super(compress ? new OutputStreamWriter(new GZIPOutputStream(new FileOutputStream(file.getPath().concat(".gz"), append))) : new FileWriter(file, append)); if (append && compress) { close(); throw new IllegalArgumentException("Cannot both append and compress"); } if (file.exists() && file.length() > 0 && append) { headerWritten = true; } dateFormatter = DateTimeFormat.forPattern(dateFormat); } private void writeHeader(Tick tick) throws IOException { DateTime now = new DateTime(); write("# This dataset is from "); write(source != null ? source : "<unknown>"); write(", created on "); write(now.toString("yyyy-MM-dd HH:mm:ss")); write(".\n"); write("# version=2\n"); write("# symbol="); write(tick.getSymbol().getFullCode()); write('\n'); write("# dateFormat="); write(dateFormat); write('\n'); write("# timeZone="); write(now.getZone().getID()); write('\n'); write("date,ask,asksize,bid,bidsize,last,lastsize,volume,ask1,asksize1,ask2,asksize2,ask3,asksize3,ask4,asksize4,ask5,asksize5,ask6,asksize6,ask7,asksize7,ask8,asksize8,ask9,asksize9,bid1,bidsize1,bid2,bidsize2,bid3,bidsize3,bid4,bidsize4,bid5,bidsize5,bid6,bidsize6,bid7,bidsize7,bid8,bidsize8,bid9,bidsize9"); write('\n'); } @Override public void write(Tick tick) throws IOException { if (!headerWritten) { writeHeader(tick); headerWritten = true; } write(dateFormatter.print(tick.getDateTime())); write(','); write(Double.toString(tick.getAsk())); write(','); write(Integer.toString(tick.getAskSize())); write(','); write(Double.toString(tick.getBid())); write(','); write(Integer.toString(tick.getBidSize())); write(','); write(Double.toString(tick.getPrice())); write(','); write(Integer.toString(tick.getLastSize())); write(','); write(Integer.toString(tick.getVolume())); MarketDepth marketDepth = tick.getMarketDepth(); if (marketDepth != null) { int levels = marketDepth.getLevels(); double[] prices = marketDepth.getAskPrices(); int[] sizes = marketDepth.getAskSizes(); for (int i = 1; i < levels; i++) { write(','); if (prices[i] > 0.0) { write(Double.toString(prices[i])); } write(','); if (sizes[i] > 0) { write(Integer.toString(sizes[i])); } } for (int i = levels; i < 10; i++) { write(",,"); } prices = marketDepth.getBidPrices(); sizes = marketDepth.getBidSizes(); for (int i = 1; i < levels; i++) { write(','); if (prices[i] > 0.0) { write(Double.toString(prices[i])); } write(','); if (sizes[i] > 0) { write(Integer.toString(sizes[i])); } } for (int i = levels; i < 10; i++) { write(",,"); } } write('\n'); } @Override public void writeAll(NavigableMap<DateTime, Tick> ticks) throws IOException { try { for (Tick t : ticks.values()) { write(t); } } finally { try { close(); } catch (IOException e) { } } } }