package com.activequant.utils.recorder; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Timer; import java.util.TimerTask; import org.apache.log4j.Logger; import com.activequant.component.ComponentBase; import com.activequant.domainmodel.ETransportType; import com.activequant.domainmodel.OHLCV; import com.activequant.domainmodel.TimeFrame; import com.activequant.domainmodel.exceptions.TransportException; import com.activequant.domainmodel.streaming.MarketDataSnapshot; import com.activequant.interfaces.transport.ITransportFactory; import com.activequant.interfaces.utils.IEventListener; import com.activequant.messages.AQMessages; import com.activequant.messages.AQMessages.BaseMessage; import com.activequant.messages.AQMessages.BaseMessage.CommandType; import com.activequant.messages.Marshaller; import com.activequant.messages.MessageFactory2; /** * A chandler makes candles. * * @author GhostRider * */ public class Chandler extends ComponentBase { private ITransportFactory transFac; private Logger log = Logger.getLogger(Chandler.class); final Timer t = new Timer(true); final int timeFrameInMs; final TimeFrame tf; private final Marshaller marshaller = new Marshaller(); private final MessageFactory2 mf = new MessageFactory2(); class InternalTimerTask extends TimerTask { @Override public void run() { List<OHLCV> candleList = new ArrayList<OHLCV>(); synchronized (candles) { Iterator<Entry<String, OHLCV>> it = candles.entrySet() .iterator(); while (it.hasNext()) { OHLCV o = it.next().getValue(); candleList.add(o.clone()); o.clear(); } } process(candleList); log.info("Drew " + candleList.size() + ". "); t.schedule( new InternalTimerTask(), (timeFrameInMs - System.currentTimeMillis() % timeFrameInMs)); } public void process(List<OHLCV> candleList) { for (OHLCV o : candleList) { if (o.getOpen() != null && !o.getOpen().equals(Double.NaN)) { System.out.println(o.getMdiId() + " - " + o.getOpen() + " - " + o.getClose()); try { BaseMessage bm = mf.ohlc(o.getTimeStamp(), o.getMdiId(), o.getOpen(), o.getHigh(), o.getLow(), o.getClose()); // let's convert that candle to a byte array. transFac.getPublisher(o.getId()).send(bm.toByteArray()); } catch (TransportException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } } } public Chandler(ITransportFactory transFac, String mdiFile, TimeFrame tf) throws Exception { super("Chandler " + tf, transFac); this.timeFrameInMs = tf.getMinutes() * 60 * 1000; System.out.println("Starting up and fetching idf"); this.transFac = transFac; this.tf = tf; subscribe(mdiFile); t.schedule(new InternalTimerTask(), (timeFrameInMs - System.currentTimeMillis() % timeFrameInMs)); } private void subscribe(String mdiFile) throws IOException, TransportException { List<String> instruments = new ArrayList<String>(); BufferedReader br = new BufferedReader(new InputStreamReader( new FileInputStream(mdiFile))); String l = br.readLine(); while (l != null) { if (!l.startsWith("#") && !l.isEmpty()) { String symbol = l; int depth = 1; if (l.indexOf(";") != -1) { String[] s = l.split(";"); symbol = s[0]; depth = Integer.parseInt(s[1]); } instruments.add(symbol); } l = br.readLine(); } for (String s : instruments) { log.info("Subscribing to " + s); transFac.getReceiver(ETransportType.MARKET_DATA, s).getRawEvent() .addEventListener(new IEventListener<byte[]>() { @Override public void eventFired(byte[] event) { BaseMessage bm; try { bm = marshaller.demarshall(event); if (log.isDebugEnabled()) log.debug("Event type: " + bm.getType()); if (bm.getType().equals(CommandType.MDS)) { MarketDataSnapshot mds = marshaller .demarshall(((AQMessages.MarketDataSnapshot) bm .getExtension(AQMessages.MarketDataSnapshot.cmd))); // we'll ignore resends. if(!mds.isResend()) process(mds); } } catch (Exception e) { e.printStackTrace(); log.warn("Exception: ", e); } } }); } } private Map<String, OHLCV> candles = new HashMap<String, OHLCV>(); private OHLCV getCandle(String mdiId) { OHLCV ret = candles.get(mdiId); if (ret == null) { ret = new OHLCV(); ret.setResolutionInSeconds(timeFrameInMs / 1000); ret.setMdiId(mdiId); synchronized (candles) { candles.put(mdiId, ret); } } return ret; } protected void process(MarketDataSnapshot mds) { if (mds == null) return; String seriesId = mds.getMdiId(); Double bid = null; Double ask = null; // if (mds.getBidSizes() != null && mds.getBidSizes().length > 0) { double bestBidPx = mds.getBidPrices()[0]; double bestBidQ = mds.getBidSizes()[0]; bid = bestBidPx; System.out.print("B"); } if (mds.getAskSizes() != null && mds.getAskSizes().length > 0) { double bestAskPx = mds.getAskPrices()[0]; double bestAskQ = mds.getAskSizes()[0]; ask = bestAskPx; System.out.print("A"); } // // if (bid != null && ask != null) { double mid = (bid + ask) / 2.0; OHLCV o = getCandle(seriesId); o.update(mds.getTimeStamp(), mid); // let's also pump in bid and ask, too. o.update(mds.getTimeStamp(), bid); o.update(mds.getTimeStamp(), ask); o.update(mds.getTimeStamp(), mid); // System.out.print("O"); } } @Override public String getDescription() { return "Chandler " + tf; } }