com.opengamma.bbg.loader.SecurityLoader.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.bbg.loader.SecurityLoader.java

Source

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

import static com.opengamma.bbg.BloombergConstants.FIELD_FUT_FIRST_TRADE_DT;
import static com.opengamma.bbg.BloombergConstants.FIELD_FUT_LAST_TRADE_DT;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.fudgemsg.FudgeMsg;
import org.slf4j.Logger;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeParseException;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.bbg.referencedata.ReferenceDataProvider;
import com.opengamma.bbg.security.BloombergSecurityProvider;
import com.opengamma.bbg.util.BloombergDataUtils;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.financial.security.option.AmericanExerciseType;
import com.opengamma.financial.security.option.EuropeanExerciseType;
import com.opengamma.financial.security.option.ExerciseType;
import com.opengamma.financial.security.option.OptionType;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.master.security.ManageableSecurity;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.time.Expiry;
import com.opengamma.util.time.ExpiryAccuracy;

/**
 * Abstract base class for loading data from Bloomberg for a specific security type.
 */
public abstract class SecurityLoader {

    /**
     * The logger.
     */
    private final Logger _logger;
    /**
     * The reference data provider.
     */
    private final ReferenceDataProvider _referenceDataProvider;
    /**
     * The security type.
     */
    private final SecurityType _securityType;

    /**
     * Creates an instance.
     * @param logger  the logger, not null
     * @param referenceDataProvider  the referenceDataProvider, not null
     * @param securityType  the security type, not null
     */
    protected SecurityLoader(final Logger logger, final ReferenceDataProvider referenceDataProvider,
            final SecurityType securityType) {
        ArgumentChecker.notNull(logger, "logger");
        ArgumentChecker.notNull(securityType, "securityType");
        ArgumentChecker.notNull(referenceDataProvider, "referenceDataProvider");
        _logger = logger;
        _securityType = securityType;
        _referenceDataProvider = referenceDataProvider;
    }

    /**
     * Gets the referenceDataProvider.
     * @return the referenceDataProvider
     */
    public ReferenceDataProvider getReferenceDataProvider() {
        return _referenceDataProvider;
    }

    /**
     * Gets the securityType.
     * @return the securityType
     */
    public SecurityType getSecurityType() {
        return _securityType;
    }

    //-------------------------------------------------------------------------
    /**
     * Parses a security from the response.
     * @param fieldData  the response, not null
     * @return the security, null if unable to create
     */
    protected abstract ManageableSecurity createSecurity(FudgeMsg fieldData);

    /**
     * Gets the fields to request from Bloomberg.
     * @return the set of fields, not null
     */
    protected abstract Set<String> getBloombergFields();

    //-------------------------------------------------------------------------
    /**
     * Loads a set of securities from Bloomberg specific keys.
     * @param bloombergKeys  the Bloomberg specific keys, not altered, not null
     * @return the set of securities, not null
     */
    public Map<String, ManageableSecurity> loadSecurities(Set<String> bloombergKeys) {
        ArgumentChecker.notNull(bloombergKeys, "bloombergKeys");
        validateReferenceDataProvider();
        _logger.info("loading securities for {}", bloombergKeys);
        bloombergKeys = Collections.unmodifiableSet(bloombergKeys); // defensive unmodifiable
        Set<String> bbgFields = getBloombergFields(); // subclasses supply unmodifiable collection

        Map<String, ManageableSecurity> result = new HashMap<String, ManageableSecurity>();
        if (bloombergKeys.isEmpty()) {
            return result;
        }

        Map<String, FudgeMsg> refData = _referenceDataProvider.getReferenceData(bloombergKeys, bbgFields);
        for (String securityDes : bloombergKeys) {
            FudgeMsg fieldData = refData.get(securityDes);
            if (fieldData == null) {
                _logger.warn("No reference data for {} cannot be null", securityDes);
                continue;
            }
            // get field data
            ManageableSecurity security = createSecurity(fieldData);
            if (security != null) {
                result.put(securityDes, security);
            }
        }
        return result;
    }

    private void validateReferenceDataProvider() {
        if (getReferenceDataProvider() == null) {
            throw new IllegalStateException("ReferenceDataProvider is null");
        }
    }

    /**
     * Parses a date string.
     * @param deliveryDateStr  the date string
     * @return the parsed ZonedDateTime, null if cannot parse
     */
    protected ZonedDateTime decodeDeliveryDate(String deliveryDateStr) {
        LocalDate deliveryDate = null;
        try {
            deliveryDate = LocalDate.parse(deliveryDateStr);
        } catch (DateTimeParseException ex) {
            _logger.warn("delivery date not in mm/dd/yyyy format - {}", deliveryDateStr);
            return null;
        }
        return deliveryDate.atStartOfDay(ZoneOffset.UTC);
    }

    //-------------------------------------------------------------------------  
    /**
     * Parses the expiry field.
     * @param expiryDate  the expiry string
     * @param futureTradingHours the future trading hours
     * @return the parsed expiry object, null if cannot parse
     */
    protected Expiry decodeExpiry(final String expiryDate, final String futureTradingHours) {
        _logger.debug("decodeExpiry expiryDate={} futureTradingHours={}", expiryDate, futureTradingHours);
        if (expiryDate == null || futureTradingHours == null) {
            _logger.warn("expirydate/futureTradingHours is null, cannot construct expiry");
            return null;
        }
        LocalDate expiryInLocalDate = null;
        try {
            expiryInLocalDate = LocalDate.parse(expiryDate);
        } catch (DateTimeParseException ex) {
            _logger.warn("expiry not in mm/dd/yyyy format - {}", expiryDate);
            return null;
        }
        //expects future trading hours in 07:00-21:00 OR 00:00-19:15 & 15:30-19:15 format
        String splitTradingHours = null;
        if (futureTradingHours.contains("&")) {
            String[] tokens = StringUtils.splitByWholeSeparator(futureTradingHours, "&");
            if (tokens.length != 2) {
                _logger.warn("futureTradingHours not in (hh:mm-hh:mm OR hh:mm-hh:mm & hh:mm-hh:mm) format - {}",
                        futureTradingHours);
                return null;
            }
            splitTradingHours = tokens[1];
        } else {
            splitTradingHours = futureTradingHours;
        }
        int closeHr = 23;
        int closeMins = 59;
        String[] tradingHrsToken = StringUtils.splitByWholeSeparator(splitTradingHours, "-");
        if (tradingHrsToken.length != 2) {
            _logger.warn("futureTradingHours not in (hh:mm-hh:mm OR hh:mm-hh:mm & hh:mm-hh:mm) format - {}",
                    futureTradingHours);
            return null;
        } else {
            String closeTime = tradingHrsToken[1];
            String[] closeTimeTokens = closeTime.split(":");
            if (closeTimeTokens.length != 2) {
                closeTimeTokens = closeTime.split("\\.");
                if (closeTimeTokens.length != 2) {
                    _logger.warn("exchange close time not in hh:mm format - {}", futureTradingHours);
                    return null;
                }
            }

            try {
                closeHr = Integer.parseInt(closeTimeTokens[0]);
                closeMins = Integer.parseInt(closeTimeTokens[1]);
            } catch (NumberFormatException ex) {
                _logger.warn("Cannot parse futureTrading hours - {}", futureTradingHours);
            }
        }
        ZonedDateTime utcDate = DateUtils.getUTCDate(expiryInLocalDate.getYear(), expiryInLocalDate.getMonthValue(),
                expiryInLocalDate.getDayOfMonth(), closeHr, closeMins);
        return new Expiry(utcDate, ExpiryAccuracy.MIN_HOUR_DAY_MONTH_YEAR);
    }

    protected ExerciseType getExerciseType(String bbgExerciseType) {
        final ExerciseType result;
        if (bbgExerciseType.equalsIgnoreCase("American")) {
            result = new AmericanExerciseType();
        } else if (bbgExerciseType.equalsIgnoreCase("European")) {
            result = new EuropeanExerciseType();
        } else {
            // an option exercise type we don't support
            _logger.warn("option exercise type {} not currently supported", bbgExerciseType);
            throw new OpenGammaRuntimeException(
                    "option exercise type " + bbgExerciseType + " not currently supported");
        }
        return result;
    }

    /**
     * Parse the identifiers from the response.
     * @param fieldData  the response, not null
     * @param security  the security to populate, not null
     */
    protected void parseIdentifiers(final FudgeMsg fieldData, final ManageableSecurity security) {
        parseIdentifiers(fieldData, security, FIELD_FUT_FIRST_TRADE_DT, FIELD_FUT_LAST_TRADE_DT);
    }

    protected void parseIdentifiers(final FudgeMsg fieldData, final ManageableSecurity security,
            final String firstTradeDateField, final String lastTradeDateField) {
        ExternalIdBundle identifierBundle = BloombergDataUtils
                .parseIdentifiers(fieldData, firstTradeDateField, lastTradeDateField).toBundle();
        security.setUniqueId(BloombergSecurityProvider
                .createUniqueId(identifierBundle.getValue(ExternalSchemes.BLOOMBERG_BUID)));
        security.setExternalIdBundle(identifierBundle);
    }

    protected OptionType getOptionType(String putOrCall) {
        if (putOrCall.equalsIgnoreCase("Call") || putOrCall.equalsIgnoreCase("C")) {
            return OptionType.CALL;
        }
        return OptionType.PUT;
    }

    protected ExternalId buildUnderlyingTicker(String underlingTicker) {
        return ExternalSchemes.bloombergTickerSecurityId(underlingTicker.replaceFirst(" (?i)COMB ", " "));
    }

}