com.barchart.feed.ddf.message.enums.DDF_TradeDay.java Source code

Java tutorial

Introduction

Here is the source code for com.barchart.feed.ddf.message.enums.DDF_TradeDay.java

Source

/**
 * Copyright (C) 2011-2012 Barchart, Inc. <http://www.barchart.com/>
 *
 * 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);

    }

}