com.barchart.feed.base.instrument.enums.MarketDisplay.java Source code

Java tutorial

Introduction

Here is the source code for com.barchart.feed.base.instrument.enums.MarketDisplay.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.base.instrument.enums;

import static com.barchart.feed.base.instrument.enums.MarketDisplay.Base.BINARY;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Base.DECIMAL;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N01;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N02;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N03;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N04;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N05;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N06;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N07;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N08;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.N09;
import static com.barchart.feed.base.instrument.enums.MarketDisplay.Exponent.Z00;
import static java.lang.Math.abs;
import static java.lang.Math.log10;
import static java.lang.Math.pow;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.barchart.feed.base.instrument.values.MarketInstrument;
import com.barchart.util.ascii.ASCII;
import com.barchart.util.values.api.PriceValue;
import com.barchart.util.values.api.SizeValue;
import com.barchart.util.values.api.TextValue;
import com.barchart.util.values.api.TimeValue;
import com.barchart.util.values.api.Value;
import com.barchart.util.values.provider.ValueConst;

/** global value formatter */
public enum MarketDisplay {

    /* TODO add custom overrides */
    DEFAULT, //

    ;

    // ############################################

    private static TimeValue filter(final TimeValue time) {
        if (time == null) {
            return ValueConst.NULL_TIME;
        }
        return time;
    }

    private final static DateTimeFormatter YEAR_FULL = DateTimeFormat.forPattern("yyyy");

    private final static DateTimeFormatter YEAR_SHORT = DateTimeFormat.forPattern("yy");

    private final static DateTimeFormatter MONTH_FULL = DateTimeFormat.forPattern("MMMMMMMMMMMM");

    private final static DateTimeFormatter MONTH_SHORT = DateTimeFormat.forPattern("MMM");

    /** such as 2011 */
    public static String timeYearFull(/* local */TimeValue time) {
        time = filter(time);
        return YEAR_FULL.print(time.asMillisUTC());
    }

    /** such as 2011 = 11 */
    public static String timeYearShort(/* local */TimeValue time) {
        time = filter(time);
        return YEAR_SHORT.print(time.asMillisUTC());
    }

    /** such as December */
    public static String timeMonthFull(/* local */TimeValue time) {
        time = filter(time);
        return MONTH_FULL.print(time.asMillisUTC());
    }

    /** such as December = DEC */
    public static String timeMonthShort(/* local */TimeValue time) {
        time = filter(time);
        return MONTH_SHORT.print(time.asMillisUTC()).toUpperCase();
    }

    /** such as future January = "F" */
    public static String timeMonthCode(/* local */TimeValue time) {

        time = filter(time);

        final DateTime date = new DateTime(time.asMillisUTC());

        final int month = date.getMonthOfYear();

        switch (month) {
        case 1:
            return "F";
        case 2:
            return "G";
        case 3:
            return "H";
        case 4:
            return "J";
        case 5:
            return "K";
        case 6:
            return "M";
        case 7:
            return "N";
        case 8:
            return "Q";
        case 9:
            return "U";
        case 10:
            return "V";
        case 11:
            return "X";
        case 12:
            return "Z";
        default:
            return "?";
        }

    }

    public static long priceFraction(/* local */PriceValue price, /* local */Fraction frac) {

        if (price == null) {
            price = ValueConst.NULL_PRICE;
        }

        if (frac == null) {
            frac = Fraction.DEC_Z00;
        }

        return priceFraction(price.mantissa(), price.exponent(), frac);

    }

    // note: can overflow
    public static final long priceWhole(/* local */long mantissa, /* local */
            int exponent, final Fraction frac) {

        final int scale = frac.decimalExponent;

        while (exponent > scale) {
            mantissa *= 10;
            exponent--;
        }

        while (exponent < scale) {
            mantissa /= 10;
            exponent++;
        }

        return mantissa / frac.decimalDenominator;

    }

    // note: can overflow
    public static final long priceFraction(/* local */long mantissa, /* local */
            int exponent, /* local */Fraction frac) {

        if (frac == null) {
            frac = Fraction.DEC_Z00;
        }

        final int scale = frac.decimalExponent;

        while (exponent > scale) {
            mantissa *= 10;
            exponent--;
        }

        while (exponent < scale) {
            mantissa /= 10;
            exponent++;
        }

        mantissa = abs(mantissa);

        switch (frac.base) {
        default:
        case DECIMAL:
            mantissa %= frac.denominator;
            break;
        case BINARY:
            mantissa %= frac.decimalDenominator;
            mantissa *= frac.denominator;
            mantissa /= frac.decimalDenominator;
            break;
        }

        return mantissa;

    }

    public static final String priceWholeText(/* local */PriceValue price) {
        if (price == null) {
            price = ValueConst.NULL_PRICE;
        }
        return ""; // priceWholeText(price.mantissa(), price.exponent());
    }

    public static final String priceFractionText(/* local */PriceValue price, /* local */Fraction frac) {

        if (price == null) {
            price = ValueConst.NULL_PRICE;
        }

        if (frac == null) {
            frac = Fraction.DEC_Z00;
        }

        long value = priceFraction(price, frac);

        final char[] array = new char[frac.places];

        for (int k = frac.places - 1; k >= 0; k--) {
            final char alpha = (char) (value % 10 + '0');
            value /= 10;
            array[k] = alpha;
        }

        return new String(array);

    }

    /**
     * render price according to BARCHART convention & fraction format; decimal
     * vs binary; number of places;
     */
    public static final String priceText(/* local */PriceValue price, /* local */Fraction frac) {

        if (price == null) {
            price = ValueConst.NULL_PRICE;
        }

        if (frac == null) {
            frac = Fraction.DEC_Z00;
        }

        return priceText(price.mantissa(), price.exponent(), frac);

    }

    /**
     * render price according to BARCHART convention & fraction format; decimal
     * vs binary; proper number of places;
     */
    public static final String priceText(/* local */long mantissa, /* local */int exponent,
            /* local */Fraction frac) {

        if (frac == null) {
            frac = Fraction.DEC_Z00;
        }

        /* consume sign */

        final boolean isMinus;

        if (mantissa < 0) {
            mantissa = -mantissa;
            isMinus = true;
        } else {
            isMinus = false;
        }

        /* normalize exponent to fraction */

        final int scale = frac.decimalExponent;

        while (exponent > scale) {
            mantissa *= 10;
            exponent--;
        }

        while (exponent < scale) {
            mantissa /= 10;
            exponent++;
        }

        /* produce whole */

        long whole = mantissa / frac.decimalDenominator;

        /* produce part */

        final char separator;

        switch (frac.base) {
        default:
        case DECIMAL:
            mantissa %= frac.denominator;
            separator = ASCII.DOT;
            break;
        case BINARY:
            mantissa %= frac.decimalDenominator;
            mantissa *= frac.denominator;
            mantissa /= frac.decimalDenominator;
            separator = ASCII.DASH;
            break;
        }

        long part = mantissa;

        /* render price to array */

        final int size = 64;

        final char[] array = new char[size];

        int index = size - 1;

        final int places = frac.places;

        /* part */if (places > 0) {

            for (int k = 0; k < places; k++) {
                final char alpha = (char) (part % 10 + ASCII._0_);
                array[index--] = alpha;
                part /= 10;
            }

            array[index--] = separator;

        }

        /* whole */if (whole == 0) {
            array[index--] = ASCII._0_;
        } else {

            while (whole != 0) {
                final char alpha = (char) (whole % 10 + ASCII._0_);
                array[index--] = alpha;
                whole /= 10;
            }

            if (isMinus) {
                array[index--] = ASCII.MINUS;
            }

        }

        final int offset = index + 1;

        final int length = size - offset;

        return new String(array, offset, length);

    }

    /**
     * BARCHART convention: use ',' separators regardless of user LOCALE
     */
    public static final String sizeText(/* local */SizeValue size) {
        if (size == null) {
            size = ValueConst.NULL_SIZE;
        }
        return sizeText(size.asLong());
    }

    /**
     * BARCHART convention: use ',' separators regardless of user LOCALE
     * 
     * TODO : replace String.format with direct render
     */
    public static final String sizeText(final long size) {
        return String.format("%,d", size);
    }

    /** in default time zone */
    public static final String timeTextISO(final TimeValue value) {
        final long millisUTC = value.asMillisUTC();
        final DateTime time = new DateTime(millisUTC);
        return time.toString();
    }

    private final static DateTimeFormatter TIME_SHORT = DateTimeFormat.forPattern("HH:mm:ss");

    private final static DateTimeFormatter DATE_SHORT = DateTimeFormat.forPattern("MM/dd/yyyy");

    private final static DateTimeFormatter TIME_WITH_DATE = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");

    /** in default time zone */
    public static final String timeTextShort(final TimeValue value) {
        return TIME_SHORT.print(value.asMillisUTC());
    }

    /** in default time zone with date MM/dd/yyyy */
    public static final String dateTimeText(final TimeValue value) {
        return TIME_WITH_DATE.print(value.asMillisUTC());
    }

    /** in default date MM/dd/yyyy */
    public static final String dateTextShort(final TimeValue value) {
        return DATE_SHORT.print(value.asMillisUTC());
    }

    /** in provided time zone */
    public static final String timeTextShort(final TimeValue value, final DateTimeZone zone) {
        return TIME_SHORT.print(value.asDateTime(zone));
    }

    /** in instrument time zone */
    public static final String timeTextShort(final TimeValue value, final MarketInstrument instrument) {
        final TextValue name = instrument.get(InstrumentField.TIME_ZONE);
        final DateTimeZone zone = DateTimeZone.forID(name.toString());
        return TIME_SHORT.print(value.asDateTime(zone));
    }

    // ############################################

    /** fraction display format base */
    public static enum Base {

        NULL_BASE(10), //

        BINARY(2), // i.e. 5/32
        DECIMAL(10), // i.e. 0.127

        ;

        public final int value;

        Base(final int base) {
            this.value = base;
        }

        public static final Base fromValue(final int value) {
            switch (value) {
            case 2:
                return BINARY;
            case 10:
                return DECIMAL;
            default:
                return NULL_BASE;
            }
        }

        public final boolean isBinary() {
            return this == BINARY;
        }

        public final boolean isDecimal() {
            return this == DECIMAL;
        }

    }

    // ############################################

    /** known decimal or binary exponent */
    public static enum Exponent {

        NULL_EXPONENT(0), //

        P12(+12), //
        P11(+11), //
        P10(+10), //
        P09(+9), //
        P08(+8), //
        P07(+7), //
        P06(+6), //
        P05(+5), //
        P04(+4), //
        P03(+3), //
        P02(+2), //
        P01(+1), //
        Z00(0), //
        N01(-1), //
        N02(-2), //
        N03(-3), //
        N04(-4), //
        N05(-5), //
        N06(-6), //
        N07(-7), //
        N08(-8), //
        N09(-9), //
        N10(-10), //
        N11(-11), //
        N12(-12), //

        ;

        public final int value;

        Exponent(final int exponent) {
            this.value = exponent;
        }

        public static final Exponent fromValue(final int value) {
            for (final Exponent known : ENUM_VALUES) {
                if (known.value == value) {
                    return known;
                }
            }
            return NULL_EXPONENT;
        }

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

    }

    // ############################################

    /** known fraction descriptor */
    public static enum Fraction implements Value<Fraction> {

        NULL_FRACTION(Base.NULL_BASE, Exponent.NULL_EXPONENT, "unknown fraction"), //

        DEC_Z00(DECIMAL, Z00, "decimal, zero exponent, 1.0"), //

        DEC_N01(DECIMAL, N01, "decimal, negative one, 0.1"), //
        DEC_N02(DECIMAL, N02, "decimal, negative two, 0.01"), //
        DEC_N03(DECIMAL, N03, "decimal, negative three, 0.001"), //
        DEC_N04(DECIMAL, N04, "decimal, negative four, 0.000,1"), //
        DEC_N05(DECIMAL, N05, "decimal, negative five, 0.000,01"), //
        DEC_N06(DECIMAL, N06, "decimal, negative six, 0.000,001"), //
        DEC_N07(DECIMAL, N07, "decimal, negative seven, 0.000,000,1"), //
        DEC_N08(DECIMAL, N08, "decimal, negative eight, 0.000,000,01"), //
        DEC_N09(DECIMAL, N09, "decimal, negative nine, 0.000,000,001"), //

        BIN_Z00(BINARY, Z00, "binary, zero exponent, 1/1"), //

        BIN_N01(BINARY, N01, "binary, negative one, 1/2"), //
        BIN_N02(BINARY, N02, "binary, negative two, 1/4"), //
        BIN_N03(BINARY, N03, "binary, negative three, 1/8"), //
        BIN_N04(BINARY, N04, "binary, negative four, 1/16"), //
        BIN_N05(BINARY, N05, "binary, negative five, 1/32"), //
        BIN_N06(BINARY, N06, "binary, negative six, 1/64"), //
        BIN_N07(BINARY, N07, "binary, negative seven, 1/128"), //
        BIN_N08(BINARY, N08, "binary, negative eight, 1/256"), //
        BIN_N09(BINARY, N09, "binary, negative nine, 1/512"), //

        ;

        public String description;

        public final Base base;
        public final Exponent exponent;

        /** native form, such as 1/10 or 1/32 */
        public final long numerator;
        public final long denominator;

        /** decimal form, such as 1/10 */
        public final int decimalExponent;
        public final long decimalDenominator;

        /** number of PLACES it takes to DISPLAY a fraction in a native form */
        public final int places;

        Fraction(final Base base, final Exponent exponent, final String description) {

            this.base = base;
            this.exponent = exponent;
            this.description = description;

            numerator = 1;
            denominator = (long) pow(base.value, -exponent.value);

            decimalExponent = exponent.value;
            decimalDenominator = (long) pow(10, -decimalExponent);

            switch (base) {
            case BINARY:
                if (denominator == 1) {
                    places = 0;
                } else {
                    places = (int) (1 + log10(denominator));
                }
                break;
            default:
            case DECIMAL:
                places = -exponent.value;
                break;
            }

        }

        public final boolean isSmallerThan(final Fraction that) {
            if (that == null) {
                return false;
            }
            return this.decimalExponent < that.decimalExponent;
        }

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

        @Override
        public Fraction freeze() {
            return this;
        }

        @Override
        public boolean isFrozen() {
            return true;
        }

        @Override
        public boolean isNull() {
            return this == NULL_FRACTION;
        }

    }

    // ############################################

}