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

com.barchart.feed.ddf.message.provider.DX_XC_Cuvol 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.provider;

import static com.barchart.feed.ddf.message.provider.CodecHelper.*;
import static com.barchart.feed.ddf.message.provider.XmlTagCuvol.*;
import static com.barchart.feed.ddf.util.HelperXML.*;
import static com.barchart.util.common.ascii.ASCII.*;

import java.nio.ByteBuffer;

import org.w3c.dom.Element;

import com.barchart.feed.api.model.meta.Exchange;
import com.barchart.feed.api.model.meta.Instrument;
import com.barchart.feed.api.model.meta.id.InstrumentID;
import com.barchart.feed.base.cuvol.api.MarketDoCuvolEntry;
import com.barchart.feed.base.provider.DefCuvolEntry;
import com.barchart.feed.base.provider.Symbology;
import com.barchart.feed.base.provider.ValueConverter;
import com.barchart.feed.base.values.api.PriceValue;
import com.barchart.feed.base.values.api.SizeValue;
import com.barchart.feed.base.values.provider.ValueBuilder;
import com.barchart.feed.ddf.instrument.provider.DDF_FeedInstProvider;
import com.barchart.feed.ddf.message.api.DDF_MarketCuvol;
import com.barchart.feed.ddf.message.api.DDF_MessageVisitor;
import com.barchart.feed.ddf.message.enums.DDF_MessageType;
import com.barchart.feed.ddf.symbol.enums.DDF_Exchange;
import com.barchart.feed.ddf.util.HelperDDF;
import com.barchart.feed.ddf.util.HelperXML;
import com.barchart.feed.ddf.util.enums.DDF_Fraction;
import com.barchart.feed.meta.instrument.DefaultInstrument;
import com.barchart.util.common.ascii.ASCII;
import com.barchart.util.common.math.MathExtra;
import com.barchart.util.value.api.Fraction;
import com.barchart.util.value.api.Price;

// TODO: Auto-generated Javadoc
/**
 *
 * 15:08:28.909 [# ddf-messages] DEBUG c.d.f.f.example.LoggingHandler - message
 * : 
 *
 * */

class DX_XC_Cuvol extends BaseMarket implements DDF_MarketCuvol {

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * com.barchart.feed.ddf.message.provider.Base#accept(com.barchart.feed.
	 * ddf.message.api.DDF_MessageVisitor, java.lang.Object)
	 */
	@Override
	public  Result accept(
			final DDF_MessageVisitor visitor, final Param param) {
		return visitor.visit(this, param);
	}

	DX_XC_Cuvol() {
		super(DDF_MessageType.CUVOL_SNAP_XML);
	}

	DX_XC_Cuvol(final DDF_MessageType messageType) {
		super(messageType);
	}

	// //////////////////////////////////////

	// cuvol descriptor
	protected long priceFirst = HelperDDF.DDF_EMPTY;
	protected long priceStep = HelperDDF.DDF_EMPTY;
	protected long[] sizeArray = DDF_NO_SIZES;

	// last trade
	protected long priceTrade = HelperDDF.DDF_EMPTY;
	protected long sizeTrade = HelperDDF.DDF_EMPTY;
	protected long sizeTradeCuvol = HelperDDF.DDF_EMPTY;

	// //////////////////////////////////////

	/**
	 * Gets the price first.
	 *
	 * @return the price first
	 */
	public final PriceValue getPriceFirst() {
		return HelperDDF.newPriceDDF(priceFirst, getFraction());
	}

	protected final int entryCount() {
		final long[] array = sizeArray;
		final int length = array.length;
		int entryCount = 0;
		for (int index = 0; index < length; index++) {
			final long sizeValue = array[index];
			if (sizeValue > 0) {
				entryCount++;
			}
		}
		return entryCount;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.api.DDF_MarketCuvol#entries()
	 */
	@Override
	public final MarketDoCuvolEntry[] entries() {

		final long[] array = sizeArray;
		final int length = array.length;

		final int entryCount = entryCount();

		final int exponent = getFraction().decimalExponent;

		final MarketDoCuvolEntry[] entries = new MarketDoCuvolEntry[entryCount];
		int entryIndex = 0;

		for (int index = 0; index < length; index++) {
			final long sizeValue = array[index];
			if (sizeValue > 0) {
				final int place = entryIndex + 1;
				final long mantissa = priceFirst + index * priceStep;
				final PriceValue price = ValueBuilder.newPrice(mantissa,
						exponent);
				final SizeValue size = ValueBuilder.newSize(sizeValue);
				final MarketDoCuvolEntry entry = new DefCuvolEntry(
						place, price, size);
				entries[entryIndex++] = entry;
			}
		}

		assert entryIndex == entryCount;

		return entries;

	}

	/**
	 * Entries.
	 *
	 * @param array
	 *            the array
	 */
	public final void entries(final long[] array) {
		sizeArray = array;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.api.DDF_MarketCuvol#getSizeLastCuvol()
	 */
	@Override
	public SizeValue getSizeLastCuvol() {
		return HelperDDF.newSizeDDF(sizeTradeCuvol);
	}

	/**
	 * Sets the last size cuvol.
	 *
	 * @param size
	 *            the new last size cuvol
	 */
	public void setLastSizeCuvol(final long size) {
		sizeTradeCuvol = size;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.api.DDF_MarketCuvol#getPriceLast()
	 */
	@Override
	public PriceValue getPriceLast() {
		return HelperDDF.newPriceDDF(priceTrade, getFraction());
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.api.DDF_MarketCuvol#getSizeLast()
	 */
	@Override
	public SizeValue getSizeLast() {
		return HelperDDF.newSizeDDF(sizeTrade);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.api.DDF_MarketCuvol#getPriceStep()
	 */
	@Override
	public PriceValue getPriceStep() {
		return HelperDDF.newPriceDDF(priceStep, getFraction());
	}

	//

	@Override
	protected final String xmlTagName() {
		return TAG;
	}

	// @Override
	// public DDF_Exchange getExchange() {
	// return
	// DDF_Exchange.fromCode(getInstrument().exchangeCode().getBytes()[0]);
	// }

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * com.barchart.feed.ddf.message.provider.Base#decodeXML(org.w3c.dom.Element
	 * )
	 */
	@Override
	public final void decodeXML(final Element tag) {

		xmlCheckTagName(tag, TAG);

		symbolArray = xmlDecSymbol(tag, SYMBOL, XML_STOP);

		updateSpread();

		final byte baseCode = xmlByteDecode(tag, FRACTION_DDF, XML_STOP);
		final DDF_Fraction frac = DDF_Fraction.fromBaseCode(baseCode);
		setFraction(frac);

		priceStep = xmlDecimalDecode(frac, tag, PRICE_TICK_INCREMENT, XML_STOP);

		priceTrade = xmlDecimalDecode(frac, tag, PRICE_LAST, XML_STOP);
		sizeTrade = xmlLongDecode(tag, SIZE_LAST, XML_STOP);
		sizeTradeCuvol = xmlLongDecode(tag, SIZE_LAST_CUVOL, XML_STOP);

		//

		final int entryCount = xmlIntegerDecode(tag, ENTRY_COUNT, XML_STOP);

		if (entryCount > 0) {

			final String stringEntries = xmlStringDecode(tag, ENTRY_ARRAY,
					XML_STOP);

			final String[] stringArray = stringEntries.split(STRING_COLON);

			long priceMin = Long.MAX_VALUE;
			long priceMax = Long.MIN_VALUE;

			final long[] prices = new long[entryCount];
			final int[] sizes = new int[entryCount];

			int index = 0;

			for (final String stringEntry : stringArray) {
				assert ValueBuilder.isPureAscii(stringEntry);
				final ByteBuffer buffer = ByteBuffer.wrap(stringEntry
						.getBytes(ASCII_CHARSET));
				final long price = HelperDDF.decimalDecode(frac, buffer, COMMA);
				final long size = HelperDDF.longDecode(buffer, NUL);
				priceMin = Math.min(priceMin, price);
				priceMax = Math.max(priceMax, price);
				prices[index] = price;
				sizes[index] = MathExtra.castLongToInt(size);
				index++;
			}

			assert index == entryCount;

			priceFirst = priceMin;

			final long range = priceMax - priceMin + priceStep;
			final int length = MathExtra.castLongToInt(range / priceStep);
			sizeArray = new long[length];

			for (index = 0; index < entryCount; index++) {
				final long price = prices[index];
				final int size = sizes[index];
				final int offset = (int) ((price - priceFirst) / priceStep);
				sizeArray[offset] = size;
			}

			assert index == entryCount;

		}

		final Instrument instrument = getInstrument();

		// FIXME This doesnt work, instrument uses the exchange() method to get it's exchange
		// so you can't call exchangeCode() on instrument before it's been set in the message;
		setExchange(DDF_Exchange.fromCode(instrument.exchangeCode().getBytes()[0]));

		final long millisUTC = xmlTimeDecode(getExchange().kind.time.zone, tag,
				TIME_LAST, XML_PASS);
		setDecodeDefaults(millisUTC);

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * com.barchart.feed.ddf.message.provider.Base#encodeXML(org.w3c.dom.Element
	 * )
	 */
	@Override
	public final void encodeXML(final Element tag) {

		xmlCheckTagName(tag, TAG);

		xmlAsciiEncode(getSymbolFull(), tag, SYMBOL);

		final DDF_Fraction frac = getFraction();
		xmlByteEncode(frac.baseCode, tag, FRACTION_DDF);

		xmlDecimalEncode(priceStep, frac, tag, PRICE_TICK_INCREMENT);

		xmlDecimalEncode(priceTrade, frac, tag, PRICE_LAST);
		xmlLongEncode(sizeTrade, tag, SIZE_LAST);
		xmlLongEncode(sizeTradeCuvol, tag, SIZE_LAST_CUVOL);

		//

		final int entryCount = entryCount();
		xmlIntegerEncode(entryCount, tag, ENTRY_COUNT);

		final StringBuilder text = new StringBuilder(512);

		final ByteBuffer buffer = ByteBuffer.allocate(32);

		if (entryCount > 0) {

			final long[] array = sizeArray;
			final int length = array.length;

			int entryIndex = 0;

			for (int index = 0; index < length; index++) {
				final long size = array[index];
				if (size > 0) {
					if (entryIndex > 0) {
						text.append(STRING_COLON);
					}
					final long price = priceFirst + index * priceStep;
					buffer.clear();
					HelperDDF.decimalEncode(price, frac, buffer, COMMA);
					HelperDDF.longEncode(size, buffer, NUL);
					final String stringEntry = new String(buffer.array(), 0,
							buffer.position(), ASCII_CHARSET);
					text.append(stringEntry);
					entryIndex++;
				}
			}

			assert entryCount == entryIndex;

		}

		xmlTextEncode(text, tag, ENTRY_ARRAY);

		// see decodeXML() above

		xmlTimeEncode(millisUTC, getExchange().kind.time.zone, tag, TIME_LAST);

	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.barchart.feed.ddf.message.provider.Base#toString()
	 */
	@Override
	public String toString() {
		final Element tag = HelperXML.xmlNewDocument(xmlTagName());
		encodeXML(tag);
		final byte[] array = HelperXML.xmlDocumentEncode(tag, true);
		return new String(array, ASCII.ASCII_CHARSET);
	}

	@Override
	protected void appedFields(final StringBuilder text) {

		super.appedFields(text);

		// TODO
		text.append("TODO : ");

	}

	@Override
	public Instrument getInstrument() {
		return DDF_FeedInstProvider.fromMessage(stub);
	}

	/*
	 * Lazy eval instrument stub
	 */
	private final Instrument stub = new DefaultInstrument(InstrumentID.NULL) {

		@Override
		public String marketGUID() {
			return Symbology.formatSymbol(getId().toString());
		}

		@Override
		public SecurityType securityType() {
			return getExchange().kind.asSecType();
		}

		@Override
		public String symbol() {
			return Symbology.formatSymbol(getId().toString());
		}

		@Override
		public Exchange exchange() {
			return Exchange.NULL;
		}

		@Override
		public String exchangeCode() {
			return "NULL";
		}

		@Override
		public Price tickSize() {
			return ValueConverter.price(getPriceStep());
		}

		@Override
		public Fraction displayFraction() {
			return ValueConverter.fraction(getFraction().fraction);
		}

	};

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy