/* * Copyright (c) 2004-2011 Marco Maccaferri and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marco Maccaferri - initial API and implementation */ package org.eclipsetrader.core.internal.ats; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import org.eclipse.core.runtime.ListenerList; import org.eclipsetrader.core.ats.BarFactoryEvent; import org.eclipsetrader.core.ats.IBarFactoryListener; import org.eclipsetrader.core.feed.ITrade; import org.eclipsetrader.core.feed.PricingDelta; import org.eclipsetrader.core.feed.PricingEvent; import org.eclipsetrader.core.feed.TimeSpan; import org.eclipsetrader.core.instruments.ISecurity; public class BarFactory { final Map<ISecurity, Set<Data>> map = new HashMap<ISecurity, Set<Data>>(); private final Timer timer; private final ListenerList listeners = new ListenerList(); class Data { final ISecurity security; final TimeSpan timeSpan; Date dateOpen; Double open; Double high; Double low; Double close; Long volume; Date dateClose; public Data(ISecurity security, TimeSpan timeSpan) { this.security = security; this.timeSpan = timeSpan; } } private class BarCloseTimerTask extends TimerTask { private final Data data; private final Date date; public BarCloseTimerTask(Data data) { this.data = data; this.date = data.dateOpen; } @Override public void run() { if (data.dateOpen == date) { fireBarCloseEvent(data); } } } public BarFactory() { this.timer = new Timer(true); } public void add(ISecurity security, TimeSpan timeSpan) { Set<Data> set = map.get(security); if (set == null) { set = new HashSet<Data>(); map.put(security, set); } set.add(new Data(security, timeSpan)); } public void addBarFactoryListener(IBarFactoryListener listener) { listeners.add(listener); } public void removeBarFactoryListener(IBarFactoryListener listener) { listeners.remove(listener); } public void dispose() { timer.cancel(); listeners.clear(); } public void pricingUpdate(PricingEvent event) { Set<Data> set = map.get(event.getSecurity()); if (set == null) { return; } for (PricingDelta delta : event.getDelta()) { if (delta.getNewValue() instanceof ITrade) { for (Data data : set) { processTrade(data, (ITrade) delta.getNewValue()); } } } } private void processTrade(Data data, ITrade trade) { if (trade.getTime() == null) { return; } Calendar c = Calendar.getInstance(); c.setTime(trade.getTime()); c.set(Calendar.MILLISECOND, 0); if (data.dateOpen != null && data.dateClose != null) { Date time = c.getTime(); if (!time.before(data.dateOpen) && time.before(data.dateClose)) { if (data.high == null || trade.getPrice() > data.high) { data.high = trade.getPrice(); } if (data.low == null || trade.getPrice() < data.low) { data.low = trade.getPrice(); } data.close = trade.getPrice(); if (trade.getSize() != null) { data.volume = data.volume != null ? data.volume + trade.getSize() : trade.getSize(); } } if (!time.before(data.dateClose)) { fireBarCloseEvent(data); } } if (data.dateOpen == null) { data.dateOpen = c.getTime(); data.open = trade.getPrice(); data.high = trade.getPrice(); data.low = trade.getPrice(); data.close = trade.getPrice(); data.volume = trade.getSize(); c.add(Calendar.MINUTE, data.timeSpan.getLength()); data.dateClose = c.getTime(); fireBarOpenEvent(data); timer.schedule(new BarCloseTimerTask(data), data.dateClose); } } private void fireBarOpenEvent(Data data) { BarFactoryEvent event = new BarFactoryEvent(data.security, data.timeSpan, data.dateOpen, data.open); Object[] l = listeners.getListeners(); for (int i = 0; i < l.length; i++) { ((IBarFactoryListener) l[i]).barOpen(event); } } private void fireBarCloseEvent(Data data) { BarFactoryEvent event = new BarFactoryEvent(data.security, data.timeSpan, data.dateOpen, data.open, data.high, data.low, data.close, data.volume); data.dateOpen = null; Object[] l = listeners.getListeners(); for (int i = 0; i < l.length; i++) { ((IBarFactoryListener) l[i]).barClose(event); } } }