package com.algotrado.extract.data;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import com.algotrado.mt4.impl.JapaneseCandleBar;
import com.algotrado.mt4.tal.strategy.check.pattern.SingleCandleBarData;

public class LargerTimeFrameDataExtractor extends IDataExtractorSubject implements IDataExtractorObserver {
	
	private TimeFrameType timeFrameType;
	private CandleBarsCollection dataList;
	private IDataExtractorSubject dataExtractorSubject;

	public LargerTimeFrameDataExtractor(AssetType assetType,
			DataEventType dataEventType, List<Float> parameters) {
		super(assetType, dataEventType, parameters);
		this.timeFrameType = setTimeFarmeType(parameters);
	}

	public TimeFrameType setTimeFarmeType(List<Float> parameters) {
		for (TimeFrameType currTimeFrameType : TimeFrameType.values()) {
			if (currTimeFrameType.getValueInMinutes() == parameters.get(0)) {
				return currTimeFrameType;
			}
		}
		return null;
	}

	/**
	 * Use this method to pass the subject to the observer, so the observer can get the new data updates.
	 * Another way to change the way this method works is to send the updates through the notifyObserver method.
	 * @param dataExtractorSubject
	 */
	public void setSubject(IDataExtractorSubject dataExtractorSubject) {
		this.dataExtractorSubject = dataExtractorSubject;
	}
	
	public void removeSubject(IDataExtractorSubject dataExtractorSubject) {
		this.dataExtractorSubject = null;
	}

	@Override
	public void run() {
		notifyObservers(assetType, dataEventType, parameters);
	}

	@Override
	public NewUpdateData getNewData() {
		return dataList;
	}

	public TimeFrameType getTimeFrameType() {
		return timeFrameType;
	}

	@Override
	public void notifyObserver(DataEventType dataEventType, List<Float> parameters) {
		dataList = new CandleBarsCollection();
		TimeFrameType subjectTimeFrame = setTimeFarmeType(parameters);
		CandleBarsCollection subjctDataList = (CandleBarsCollection)this.dataExtractorSubject.getNewData();
		Collection<SingleCandleBarData> subjectCandleBars = subjctDataList.getCandleBars();
		
		if (subjectTimeFrame.isLargerTimeFrame(timeFrameType)) {
			throw new RuntimeException("Cannot use larger time frame " + subjectTimeFrame.getValueInMinutes() + 
					" to get lower time frame " + timeFrameType.getValueInMinutes());
		}
		
		//Take all the candle bars from subject and create new candle bars in larger time frame. 
		
		double open=-1, close=-1, high=-1, low=-1, volume=-1;
		Date openTime = null;
		for (JapaneseCandleBar candleBarData : subjectCandleBars) {
			if (open < 0) {
				open = candleBarData.getOpen();
//				close = candleBarData.getClose();
				high = candleBarData.getHigh();
				low = candleBarData.getLow();
				openTime = candleBarData.getTime();
			}
			
			if (timeFrameType.isTimeFrameStartTime(candleBarData.getTime())) {
				open = candleBarData.getOpen();
				openTime = candleBarData.getTime();
				high = candleBarData.getHigh();
				low = candleBarData.getLow();
			} else if (timeFrameType.isTimeFrameEndTime(candleBarData.getTime())) {
				close = candleBarData.getClose();
				if (candleBarData.getHigh() > high) {
					high = candleBarData.getHigh();
				} else if (candleBarData.getLow() < low) {
					low = candleBarData.getLow();
				}
				dataList.addCandleBar(new SingleCandleBarData(open, close, high, low, openTime, candleBarData.getCommodityName(), 0, 
																0, 0, 0, 0, 0, 0));
			} else {
				if (candleBarData.getHigh() > high) {
					high = candleBarData.getHigh();
				} else if (candleBarData.getLow() < low) {
					low = candleBarData.getLow();
				}
			}
			
		}
		
		run();
	}
}

@@ -30,16 +30,43 @@
 .data;%0A%0A
+import java.util.Calendar;%0A
 import j
@@ -109,16 +109,52 @@
 l.Date;%0A
+import java.util.GregorianCalendar;%0A
 import j
@@ -2469,16 +2469,41 @@
 ame. %0A%09%09
+Date previousDate = null;
 %0A%09%09doubl
@@ -2843,24 +2843,765 @@
 ime();%0A%09%09%09%7D%0A
+%09%09%09boolean isNewWeek = false;%0A%09%09%09if (previousDate != null && openTime != null) %7B//Support new candle when a new week starts. %0A%09%09%09%09Calendar prevCalendar = GregorianCalendar.getInstance(); // creates a new calendar instance%0A%09%09%09%09prevCalendar.setTime(previousDate);%0A%09%09%09%09Calendar currCalendar = GregorianCalendar.getInstance(); // creates a new calendar instance%0A%09%09%09%09currCalendar.setTime(openTime);%0A%09%09%09%09if (prevCalendar.get(Calendar.WEEK_OF_YEAR) != currCalendar.get(Calendar.WEEK_OF_YEAR)) %7B%0A%09%09%09%09%09isNewWeek = true;%0A%09%09%09%09%09if (!timeFrameType.isTimeFrameEndTime(previousDate)) %7B%0A%09%09%09%09%09%09dataList.addCandleBar(new SingleCandleBarData(open, close, high, low, openTime, candleBarData.getCommodityName(), 0, %0A%09%09%09%09%09%09%09%090, 0, 0, 0, 0, 0));%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09%7D%0A
 %09%09%09%0A%09%09%09if (t
@@ -3650,32 +3650,45 @@
 rData.getTime())
+ %7C%7C isNewWeek
 ) %7B%0A%09%09%09%09open = c
@@ -4259,16 +4259,45 @@
 0, 0));%0A
+%09%09%09%09previousDate = openTime;%0A
 %09%09%09%7D els

Support new candle when new week starts.