package com.activequant.backtesting.reporting; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JFrame; import org.apache.log4j.Logger; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.data.time.Millisecond; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import com.activequant.domainmodel.ETransportType; import com.activequant.domainmodel.PersistentEntity; import com.activequant.domainmodel.TimeFrame; import com.activequant.domainmodel.TimeStamp; import com.activequant.domainmodel.exceptions.TransportException; import com.activequant.domainmodel.streaming.PNLChangeEvent; import com.activequant.interfaces.transport.IReceiver; import com.activequant.interfaces.transport.ITransportFactory; import com.activequant.interfaces.utils.IEventListener; import com.activequant.timeseries.ChartUtils; import com.activequant.timeseries.DoubleColumn; import com.activequant.timeseries.TSContainer2; import com.activequant.timeseries.TypedColumn; public class PNLMonitor { private TSContainer2 tsContainer; private TSContainer2 cumulatedTSContainer; private Map<String, Double> currentValues = new HashMap<String, Double>(); private boolean liveEnabled = false; private TimeSeriesCollection dataset; private List<TimeSeries> timeSeries = new ArrayList<TimeSeries>(); private AtomicBoolean dataChanged = new AtomicBoolean(false); private Logger log = Logger.getLogger(PNLMonitor.class); public PNLMonitor(ITransportFactory transportFactory) throws TransportException { this(transportFactory, TimeFrame.RAW); } public PNLMonitor(ITransportFactory transportFactory, TimeFrame resolution) throws TransportException { log.info("Instantiating PNL monitor with " + resolution.toString() + " resolution."); // add the pnl data listener. if (transportFactory != null) { IReceiver pnlChannel = transportFactory.getReceiver(ETransportType.RISK_DATA.toString()); pnlChannel.getMsgRecEvent().addEventListener(new IEventListener<PersistentEntity>() { @Override public void eventFired(PersistentEntity event) { if (event instanceof PNLChangeEvent) { process((PNLChangeEvent) event); } } }); } // tsContainer = new TSContainer2("PNL", Arrays.asList(new String[] { "TOTAL" }), Arrays.asList(new TypedColumn[] { new DoubleColumn() })); cumulatedTSContainer = new TSContainer2("PNL", Arrays.asList(new String[] { "TOTAL" }), Arrays.asList(new TypedColumn[] { new DoubleColumn() })); // if (!resolution.equals(TimeFrame.RAW)) { tsContainer.setResolutionInNanoseconds(resolution.getNanoseconds()); cumulatedTSContainer.setResolutionInNanoseconds(resolution.getNanoseconds()); } } public void process(PNLChangeEvent delta) { dataChanged = new AtomicBoolean(true); tsContainer.setValue(delta.getTradInstId(), delta.getTimeStamp(), delta.getChange()); double currentVal = 0.0; if (!currentValues.containsKey(delta.getTradInstId())) { // also add a new line chart. currentVal = delta.getChange(); currentValues.put(delta.getTradInstId(), currentVal); cumulatedTSContainer.setValue(delta.getTradInstId(), delta.getTimeStamp(), currentVal); } else { currentVal = currentValues.get(delta.getTradInstId()); currentVal += delta.getChange(); currentValues.put(delta.getTradInstId(), currentVal); cumulatedTSContainer.setValue(delta.getTradInstId(), delta.getTimeStamp(), currentVal); } Iterator<Entry<String, Double>> it = currentValues.entrySet().iterator(); double total = 0.0; while (it.hasNext()) { total += it.next().getValue(); } cumulatedTSContainer.setValue("TOTAL", delta.getTimeStamp(), total); } public TSContainer2 getTsContainer() { return tsContainer; } public void setTsContainer(TSContainer2 tsContainer) { this.tsContainer = tsContainer; } public void showLiveChart() { liveEnabled = true; // dataset = new TimeSeriesCollection(); // JFreeChart chart = ChartFactory.createTimeSeriesChart("PNL", "Time", "Value", dataset, true, true, false); chart.setAntiAlias(true); chart.setBackgroundPaint(Color.WHITE); final XYPlot plot = chart.getXYPlot(); ValueAxis axis = plot.getDomainAxis(); axis.setAutoRange(true); // axis.setFixedAutoRange(600000.0); JFrame frame = new JFrame("GraphTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ChartPanel label = new ChartPanel(chart); frame.getContentPane().add(label); // Suppose I add combo boxes and buttons here later frame.pack(); frame.setVisible(true); Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(500); if (dataChanged.get() == true) { dataChanged = new AtomicBoolean(false); TimeSeriesCollection tempDataSet = new TimeSeriesCollection(); for (int i = 0; i < cumulatedTSContainer.getNumColumns(); i++) { DoubleColumn dc = (DoubleColumn) cumulatedTSContainer.getColumns().get(i); List<TimeStamp> ts = cumulatedTSContainer.getTimeStamps(); TimeSeries tsNew = new TimeSeries(cumulatedTSContainer.getColumnHeaders().get(i)); for (int j = 0; j < dc.size(); j++) tsNew.addOrUpdate(new Millisecond(ts.get(j).getDate()), dc.get(j)); // add a new series. tempDataSet.addSeries(tsNew); } plot.setDataset(tempDataSet); } } catch (Exception ex) { ex.printStackTrace(); } } } }); t.setDaemon(true); t.start(); } public JFreeChart getStaticChart() { return ChartUtils.getStepChart("PNL", cumulatedTSContainer); } public TSContainer2 getCumulatedTSContainer() { return cumulatedTSContainer; } public void setCumulatedTSContainer(TSContainer2 cumulatedTSContainer) { this.cumulatedTSContainer = cumulatedTSContainer; } }