com.opengamma.financial.view.HistoricalViewEvaluationTarget.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.financial.view.HistoricalViewEvaluationTarget.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.financial.view;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.fudgemsg.FudgeField;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeSerializer;
import org.threeten.bp.LocalDate;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.marketdata.historical.HistoricalShockMarketDataSnapshot.ShockType;
import com.opengamma.engine.marketdata.spec.FixedHistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.HistoricalShockMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.execution.ArbitraryViewCycleExecutionSequence;
import com.opengamma.engine.view.execution.ViewCycleExecutionOptions;
import com.opengamma.engine.view.execution.ViewCycleExecutionSequence;
import com.opengamma.financial.OpenGammaExecutionContext;
import com.opengamma.financial.analytics.timeseries.DateConstraint;
import com.opengamma.financial.convention.HolidaySourceCalendarAdapter;
import com.opengamma.id.UniqueId;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;

/**
 * Target for {@link HistoricalViewEvaluationFunction} which ensures that an execution sequence is constructed which matches the function's expectations.
 */
public class HistoricalViewEvaluationTarget extends ViewEvaluationTarget {

    /**
     * Fudge field containing the start date
     */
    protected static final String START_DATE_FIELD = "startDate";
    /**
     * Fudge field containing whether the start date is inclusive.
     */
    protected static final String INCLUDE_START_FIELD = "includeStart";
    /**
     * Fudge field containing the end date.
     */
    protected static final String END_DATE_FIELD = "endDate";
    /**
     * Fudge field containing whether the end date is inclusive.
     */
    protected static final String INCLUDE_END_FIELD = "includeEnd";
    /**
     * Repeated Fudge field, each containing a currency ISO code for the compound holiday calendar to use.
     */
    protected static final String CURRENCY_CALENDAR_FIELD = "currencyCalendar";
    /**
     * Fudge field containing the market data mode.
     */
    protected static final String MARKET_DATA_MODE_FIELD = "marketDataMode";

    /**
     * Creates a new target.
     * 
     * @param user  the user the view is created for, not null.
     * @param startDate  the start date as a {@link DateConstraint} encoded string, not null
     * @param includeStart  whether to include the start date in the evaluation.
     * @param endDate  the end date as a {@link DateConstraint} encoded string, not null
     * @param includeEnd  whether to include the end date in the evaluation.
     * @param currencyCalendars  the currencies for which to obtain a compound holiday calendar in order to obtain a valid sequence of dates, may be null
     * @param marketDataMode  the mode in which market data should be obtained, not null
     */
    public HistoricalViewEvaluationTarget(UserPrincipal user, String startDate, boolean includeStart,
            String endDate, boolean includeEnd, Set<Currency> currencyCalendars,
            HistoricalViewEvaluationMarketDataMode marketDataMode) {
        super(user, new HistoricalSequence(startDate, includeStart, endDate, includeEnd, currencyCalendars,
                marketDataMode));
    }

    protected HistoricalViewEvaluationTarget(ViewDefinition viewDefinition, final HistoricalSequence sequence) {
        super(viewDefinition, sequence);
    }

    private HistoricalViewEvaluationTarget(FudgeDeserializer deserializer, FudgeMsg message) {
        this(deserializer, message, message.getString(START_DATE_FIELD), message.getBoolean(INCLUDE_START_FIELD),
                message.getString(END_DATE_FIELD), message.getBoolean(INCLUDE_END_FIELD),
                getCurrencyCalendars(deserializer, message), deserializer.fieldValueToObject(
                        HistoricalViewEvaluationMarketDataMode.class, message.getByName(MARKET_DATA_MODE_FIELD)));
    }

    private HistoricalViewEvaluationTarget(FudgeDeserializer deserializer, FudgeMsg message, String startDate,
            boolean includeStart, String endDate, boolean includeEnd, Set<Currency> currencyCalendars,
            HistoricalViewEvaluationMarketDataMode marketDataMode) {
        super(deserializer, message, new HistoricalSequence(startDate, includeStart, endDate, includeEnd,
                currencyCalendars, marketDataMode));
    }

    protected HistoricalViewEvaluationTarget(final HistoricalViewEvaluationTarget copyFrom, final UniqueId uid) {
        super(copyFrom, uid);
    }

    @Override
    protected ViewEvaluationTarget createUnion(final ViewDefinition newViewDefinition) {
        return new HistoricalViewEvaluationTarget(newViewDefinition, (HistoricalSequence) getExecutionSequence());
    }

    private static Set<Currency> getCurrencyCalendars(FudgeDeserializer deserializer, FudgeMsg message) {
        Set<Currency> currencies = new HashSet<Currency>();
        for (FudgeField ccyField : message.getAllByName(CURRENCY_CALENDAR_FIELD)) {
            Currency ccy = deserializer.fieldValueToObject(Currency.class, ccyField);
            currencies.add(ccy);
        }
        return !currencies.isEmpty() ? currencies : null;
    }

    private static final class HistoricalSequence implements ViewCycleExecutionSequenceDescriptor {

        /**
         * The description of the start date.
         */
        private final String _startDateDescriptor;
        /**
         * Indicates whether to include the start date.
         */
        private final boolean _includeStart;
        /**
         * The description of the end date.
         */
        private final String _endDateDescriptor;
        /**
         * Indicates whether to include the end date.
         */
        private final boolean _includeEnd;
        /**
         * The currencies for which to obtain a compound calendar in order to generate the correct sequence of dates, null to ignore holidays.
         */
        private final Set<Currency> _currencyCalendars;
        /**
         * The historical market data type
         */
        private final HistoricalViewEvaluationMarketDataMode _marketDataMode;

        public HistoricalSequence(String startDateDescriptor, boolean includeStart, String endDateDescriptor,
                boolean includeEnd, Set<Currency> currencyCalendars,
                HistoricalViewEvaluationMarketDataMode marketDataMode) {
            ArgumentChecker.notNull(startDateDescriptor, "startDate");
            ArgumentChecker.notNull(endDateDescriptor, "endDate");
            ArgumentChecker.notNull(marketDataMode, "marketDataMode");
            _startDateDescriptor = startDateDescriptor;
            _includeStart = includeStart;
            _endDateDescriptor = endDateDescriptor;
            _includeEnd = includeEnd;
            _currencyCalendars = currencyCalendars;
            _marketDataMode = marketDataMode;
        }

        // ViewCycleExecutionSequenceDescriptor

        @Override
        public ViewCycleExecutionSequence createSequence(FunctionExecutionContext executionContext) {
            LocalDate startDate = DateConstraint.evaluate(executionContext, _startDateDescriptor);
            LocalDate endDate = DateConstraint.evaluate(executionContext, _endDateDescriptor);
            if (!_includeStart) {
                startDate = startDate.plusDays(1);
            }
            if (!_includeEnd) {
                endDate = endDate.minusDays(1);
            }
            HolidaySourceCalendarAdapter calendar;
            if (_currencyCalendars != null) {
                Currency[] currencies = _currencyCalendars.toArray(new Currency[_currencyCalendars.size()]);
                HolidaySource holidaySource = OpenGammaExecutionContext.getHolidaySource(executionContext);
                calendar = new HolidaySourceCalendarAdapter(holidaySource, currencies);
            } else {
                calendar = null;
            }
            List<ViewCycleExecutionOptions> executionSequence = new LinkedList<ViewCycleExecutionOptions>();
            LocalDate previousWorkingDate = null;
            LocalDate currentDate = startDate;
            while (!currentDate.isAfter(endDate)) {
                if (calendar == null || calendar.isWorkingDay(currentDate)) {
                    MarketDataSpecification marketDataSpec = createMarketDataSpec(previousWorkingDate, currentDate,
                            LocalDate.now(executionContext.getValuationClock()));
                    if (marketDataSpec != null) {
                        ViewCycleExecutionOptions executionOptions = ViewCycleExecutionOptions.builder()
                                .setMarketDataSpecification(marketDataSpec).create();
                        executionSequence.add(executionOptions);
                    }
                    previousWorkingDate = currentDate;
                }
                currentDate = currentDate.plusDays(1);
            }
            return new ArbitraryViewCycleExecutionSequence(executionSequence);
        }

        private MarketDataSpecification createMarketDataSpec(LocalDate previousHistoricalDate,
                LocalDate historicalDate, LocalDate valuationDate) {
            FixedHistoricalMarketDataSpecification historicalDateSpec = new FixedHistoricalMarketDataSpecification(
                    historicalDate);
            switch (_marketDataMode) {
            case HISTORICAL:
                return historicalDateSpec;
            case RELATIVE_SHOCK:
                if (previousHistoricalDate == null) {
                    return null;
                }
                FixedHistoricalMarketDataSpecification valuationDateSpec = new FixedHistoricalMarketDataSpecification(
                        valuationDate);
                FixedHistoricalMarketDataSpecification previousHistoricalDateSpec = new FixedHistoricalMarketDataSpecification(
                        previousHistoricalDate);
                return new HistoricalShockMarketDataSpecification(ShockType.PROPORTIONAL,
                        previousHistoricalDateSpec, historicalDateSpec, valuationDateSpec);
            default:
                throw new OpenGammaRuntimeException("Unsupported market data mode: " + _marketDataMode);
            }
        }

        // Object

        @Override
        public int hashCode() {
            int hc = 1;
            hc += (hc << 4) + ObjectUtils.hashCode(_startDateDescriptor);
            hc += (hc << 4) + (_includeStart ? 1 : 0);
            hc += (hc << 4) + ObjectUtils.hashCode(_endDateDescriptor);
            hc += (hc << 4) + (_includeEnd ? 1 : 0);
            hc += (hc << 4) + (_currencyCalendars != null ? _currencyCalendars.hashCode() : 0);
            hc += (hc << 4) + _marketDataMode.hashCode();
            return hc;
        }

        @Override
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            }
            if (!(o instanceof HistoricalSequence)) {
                return false;
            }
            final HistoricalSequence other = (HistoricalSequence) o;
            return ObjectUtils.equals(_startDateDescriptor, other._startDateDescriptor)
                    && (_includeStart == other._includeStart)
                    && ObjectUtils.equals(_endDateDescriptor, other._endDateDescriptor)
                    && (_includeEnd == other._includeEnd)
                    && ObjectUtils.equals(_currencyCalendars, other._currencyCalendars)
                    && (_marketDataMode == other._marketDataMode);
        }

    }

    public String getStartDate() {
        return ((HistoricalSequence) getExecutionSequence())._startDateDescriptor;
    }

    public boolean isIncludeStart() {
        return ((HistoricalSequence) getExecutionSequence())._includeStart;
    }

    public String getEndDate() {
        return ((HistoricalSequence) getExecutionSequence())._endDateDescriptor;
    }

    public boolean isIncludeEnd() {
        return ((HistoricalSequence) getExecutionSequence())._includeEnd;
    }

    public Set<Currency> getCurrencyCalendars() {
        return ((HistoricalSequence) getExecutionSequence())._currencyCalendars;
    }

    public HistoricalViewEvaluationMarketDataMode getMarketDataMode() {
        return ((HistoricalSequence) getExecutionSequence())._marketDataMode;
    }

    @Override
    public HistoricalViewEvaluationTarget withUniqueId(final UniqueId uid) {
        return new HistoricalViewEvaluationTarget(this, uid);
    }

    @Override
    protected void toFudgeMsgImpl(FudgeSerializer serializer, MutableFudgeMsg message) {
        super.toFudgeMsgImpl(serializer, message);
    }

    @Override
    protected void serializeExecutionSequence(FudgeSerializer serializer, MutableFudgeMsg message) {
        // More efficient to recreate the execution sequence rather than serializing it
        message.add(START_DATE_FIELD, getStartDate());
        message.add(INCLUDE_START_FIELD, isIncludeStart());
        message.add(END_DATE_FIELD, getEndDate());
        message.add(INCLUDE_END_FIELD, isIncludeEnd());
        if (getCurrencyCalendars() != null) {
            for (Currency ccy : getCurrencyCalendars()) {
                serializer.addToMessage(message, CURRENCY_CALENDAR_FIELD, null, ccy);
            }
        }
        serializer.addToMessage(message, MARKET_DATA_MODE_FIELD, null, getMarketDataMode());
    }

    public static HistoricalViewEvaluationTarget fromFudgeMsg(FudgeDeserializer deserializer, FudgeMsg message) {
        return new HistoricalViewEvaluationTarget(deserializer, message);
    }

}