All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.barchart.feed.ddf.message.enums.DDF_TradeDay Maven / Gradle / Ivy

/**
 * Copyright (C) 2011-2012 Barchart, Inc. 
 *
 * All rights reserved. Licensed under the OSI BSD License.
 *
 * http://www.opensource.org/licenses/bsd-license.php
 */
package com.barchart.feed.ddf.message.enums;

import static com.barchart.util.common.ascii.ASCII.QUEST;
import static com.barchart.util.common.ascii.ASCII._0_;
import static com.barchart.util.common.ascii.ASCII._1_;
import static com.barchart.util.common.ascii.ASCII._2_;
import static com.barchart.util.common.ascii.ASCII._3_;
import static com.barchart.util.common.ascii.ASCII._4_;
import static com.barchart.util.common.ascii.ASCII._5_;
import static com.barchart.util.common.ascii.ASCII._6_;
import static com.barchart.util.common.ascii.ASCII._7_;
import static com.barchart.util.common.ascii.ASCII._8_;
import static com.barchart.util.common.ascii.ASCII._9_;
import static com.barchart.util.common.ascii.ASCII._A_;
import static com.barchart.util.common.ascii.ASCII._B_;
import static com.barchart.util.common.ascii.ASCII._C_;
import static com.barchart.util.common.ascii.ASCII._D_;
import static com.barchart.util.common.ascii.ASCII._E_;
import static com.barchart.util.common.ascii.ASCII._F_;
import static com.barchart.util.common.ascii.ASCII._G_;
import static com.barchart.util.common.ascii.ASCII._H_;
import static com.barchart.util.common.ascii.ASCII._I_;
import static com.barchart.util.common.ascii.ASCII._J_;
import static com.barchart.util.common.ascii.ASCII._K_;
import static com.barchart.util.common.ascii.ASCII._L_;
import static com.barchart.util.common.ascii.ASCII._M_;
import static com.barchart.util.common.ascii.ASCII._N_;
import static com.barchart.util.common.ascii.ASCII._O_;
import static com.barchart.util.common.ascii.ASCII._P_;
import static com.barchart.util.common.ascii.ASCII._Q_;
import static com.barchart.util.common.ascii.ASCII._R_;
import static com.barchart.util.common.ascii.ASCII._S_;
import static com.barchart.util.common.ascii.ASCII._T_;
import static com.barchart.util.common.ascii.ASCII._U_;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.barchart.feed.base.enums.EnumByteOrdinal;
import com.barchart.feed.base.enums.EnumCodeByte;
import com.barchart.feed.base.values.api.TimeValue;
import com.barchart.feed.base.values.provider.ValueBuilder;
import com.barchart.feed.ddf.util.ClockDDF;
import com.barchart.util.common.math.MathExtra;

// TODO: Auto-generated Javadoc
/**
 * ddf trade day codes.
 */
public enum DDF_TradeDay implements EnumCodeByte, EnumByteOrdinal {

	/*
	 * NOTE: keep the monotonously increasing sequence or you will break ordinal
	 */

	D01(_1_), //
	D02(_2_), //
	D03(_3_), //
	D04(_4_), //
	D05(_5_), //
	D06(_6_), //
	D07(_7_), //
	D08(_8_), //
	D09(_9_), //
	D10(_0_), //
	D11(_A_), //
	D12(_B_), //
	D13(_C_), //
	D14(_D_), //
	D15(_E_), //
	D16(_F_), //
	D17(_G_), //
	D18(_H_), //
	D19(_I_), //
	D20(_J_), //
	D21(_K_), //
	D22(_L_), //
	D23(_M_), //
	D24(_N_), //
	D25(_O_), //
	D26(_P_), //
	D27(_Q_), //
	D28(_R_), //
	D29(_S_), //
	D30(_T_), //
	D31(_U_), //

	// keep this item last

	UNKNOWN(QUEST), //

	;

	private static final Logger logger = LoggerFactory
			.getLogger(DDF_TradeDay.class);

	/* (non-Javadoc)
	 * @see com.barchart.util.enums.EnumByteOrdinal#ord()
	 */
	@Override
	public final byte ord() {
		return ord;
	}

	/* (non-Javadoc)
	 * @see com.barchart.util.enums.EnumCodeByte#code()
	 */
	@Override
	public final byte code() {
		return code;
	}

	/** byte sized ordinal. */
	public final byte ord;

	/** ddf feed encoding. */
	public final byte code;

	/** day of month number. */
	public int day;

	private DDF_TradeDay(final byte code) {
		this.ord = (byte) ordinal();
		this.code = code;
		this.day = ordinal() + 1;
	}

	private final static DDF_TradeDay[] ENUM_VALUES = values();

	/**
	 * Values unsafe.
	 *
	 * @return the dD f_ trade day[]
	 */
	@Deprecated
	public final static DDF_TradeDay[] valuesUnsafe() {
		return ENUM_VALUES;
	}

	static {
		// validate use of byte ord
		MathExtra.castIntToByte(ENUM_VALUES.length);
	}

	/**
	 * From ord.
	 *
	 * @param ord the ord
	 * @return the dD f_ trade day
	 */
	public final static DDF_TradeDay fromOrd(final byte ord) {
		return ENUM_VALUES[ord];
	}

	// TODO optimize
	/**
	 * From code.
	 *
	 * @param code the code
	 * @return the dD f_ trade day
	 */
	public final static DDF_TradeDay fromCode(final byte code) {
		for (final DDF_TradeDay known : ENUM_VALUES) {
			if (known.code == code) {
				return known;
			}
		}
		return UNKNOWN;
	}

	/**
	 * From millis utc.
	 *
	 * @param millisUTC the millis utc
	 * @return the dD f_ trade day
	 */
	public static final DDF_TradeDay fromMillisUTC(final long millisUTC) {
		final DateTime dateTime = new DateTime(millisUTC, DateTimeZone.UTC);
		return fromDay(dateTime.getDayOfMonth());
	}

	/**
	 * From day.
	 *
	 * @param day the day
	 * @return the dD f_ trade day
	 */
	public static final DDF_TradeDay fromDay(final int day) {
		/* NOTE: Date range is 1...31 ordinal range is 0...30 */
		if (1 <= day & day <= 31) {
			final int ordinal = day - 1;
			return ENUM_VALUES[ordinal];
		}
		return UNKNOWN;
	}

	/**
	 * Checks if is known.
	 *
	 * @return true, if is known
	 */
	public final boolean isKnown() {
		return this != UNKNOWN;
	}

	// not used
	static boolean isCurrent(final DDF_TradeDay one, final DDF_TradeDay two) {

		if (!one.isKnown() || !two.isKnown()) {
			return false;
		}

		return one == two;

	}

	// not used
	static boolean isPrevious(final DDF_TradeDay one, final DDF_TradeDay two) {

		if (!one.isKnown() || !two.isKnown()) {
			return false;
		}

		final int diff = one.ord - two.ord;

		if (diff == -1) {
			return true;
		}

		if (diff > 0) {
			return true;
		}

		return false;

	}

	//

	/**
	 * note: this is an approximation
	 * 
	 * depends on current invocation time
	 * 
	 * assumes DDF CST time zone of DDF_TradeDay.
	 *
	 * @return the time value
	 */
	public TimeValue tradeDate() {

		// current date in chicago
		final DateTime todayCST = new DateTime(ClockDDF.clock.millis(), ZONE_CST);

		final TimeValue tradeDate = tradeDateFrom(this, todayCST);

		return tradeDate;
	}

	private static final DateTimeZone ZONE_CST = DateTimeZone
			.forID("America/Chicago");

	private static final DateTimeZone ZONE_UTC = DateTimeZone.UTC;

	/** longest market holiday duration */
	private static final int HOLIDAY_THESHOLD = 5;

	/**
	 * recover full trade date from DDF day code and todays date
	 * 
	 * expressed in UTC zone
	 * 
	 * year, month, day : should be treated as local market trade date.
	 *
	 * @param tradeDay the trade day
	 * @param todayDate the today date
	 * @return the time value
	 */
	public static TimeValue tradeDateFrom(final DDF_TradeDay tradeDay,
			final DateTime todayDate) {

		// trading day of month reported by the feed
		final int tradingDayNum = tradeDay.day;

		// current day of month
		final int currentDayNum = todayDate.getDayOfMonth();

		// positive for same month if trading date is in the future
		// unless day enum is not a day in the month ???
		final int difference = tradingDayNum - currentDayNum;

		final boolean isSmall = Math.abs(difference) <= HOLIDAY_THESHOLD;
		final boolean isLarge = !isSmall;

		//

		final boolean isSameMonthSameDay = (difference == 0);

		final boolean isSameMonthPastDay = difference < 0 & isSmall;
		final boolean isSameMonthNextDay = difference > 0 & isSmall;

		final boolean isPastMonthPastDay = difference > 0 & isLarge;
		final boolean isNextMonthNextDay = difference < 0 & isLarge;

		//

		DateTime generated;

		try {
			if (isSameMonthSameDay) {
				generated = todayDate;
			} else if (isSameMonthPastDay) {
				generated = todayDate.withDayOfMonth(tradingDayNum);
			} else if (isSameMonthNextDay) {
				generated = todayDate.withDayOfMonth(tradingDayNum);
			} else if (isPastMonthPastDay) {
				generated = todayDate.minusMonths(1).withDayOfMonth(tradingDayNum);
			} else if (isNextMonthNextDay) {
				generated = todayDate.plusMonths(1).withDayOfMonth(tradingDayNum);
			} else {
				logger.error("should not happen");
				generated = todayDate;
			}
		} catch (final Exception e) {
			generated = todayDate;
		}

		final DateTime result = new DateTime(//
				generated.getYear(), //
				generated.getMonthOfYear(), //
				generated.getDayOfMonth(), //
				0, 0, 0, 0, ZONE_UTC);

		final long millisUTC = result.getMillis();

		return ValueBuilder.newTime(millisUTC);

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy