/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.volatility.surface; import java.io.Serializable; import java.util.Map; import org.apache.commons.lang.Validate; import org.threeten.bp.LocalDate; import com.google.common.collect.Maps; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.financial.convention.expirycalc.BrentCrudeFutureExpiryCalculator; import com.opengamma.financial.convention.expirycalc.ExchangeTradedInstrumentExpiryCalculator; import com.opengamma.financial.convention.expirycalc.GoldFutureExpiryCalculator; import com.opengamma.financial.convention.expirycalc.LiveCattleFutureExpiryCalculator; import com.opengamma.financial.convention.expirycalc.SoybeanFutureExpiryCalculator; import com.opengamma.id.ExternalId; import com.opengamma.util.ArgumentChecker; /** * Provider of commodity Future Instrument ID's. */ public class BloombergCommodityFuturePriceCurveInstrumentProvider implements FuturePriceCurveInstrumentProvider<Number>, Serializable { /** * Gets the expiryRules. * @return the expiryRules */ public static Map<String, ExchangeTradedInstrumentExpiryCalculator> getExpiryRules() { return EXPIRY_RULES; } private static final Map<String, ExchangeTradedInstrumentExpiryCalculator> EXPIRY_RULES; static { EXPIRY_RULES = Maps.newHashMap(); EXPIRY_RULES.put("BO", SoybeanFutureExpiryCalculator.getInstance()); // Soy oil EXPIRY_RULES.put("BZ", BrentCrudeFutureExpiryCalculator.getInstance()); // Brent Crude -- temp for 2 character code in surface name EXPIRY_RULES.put("BZA", BrentCrudeFutureExpiryCalculator.getInstance()); // Brent Crude EXPIRY_RULES.put("GC", GoldFutureExpiryCalculator.getInstance()); // Gold EXPIRY_RULES.put("LC", LiveCattleFutureExpiryCalculator.getInstance()); // Live Cattle EXPIRY_RULES.put("S ", SoybeanFutureExpiryCalculator.getInstance()); // Soy } private final String _futurePrefix; private final String _postfix; private final String _dataFieldName; private final String _tickerScheme; /** * @param futurePrefix Two character string representing future type. e.g. S , AA etc. * @param postfix Generally, "Comdty" * @param dataFieldName Expecting MarketDataRequirementNames.MARKET_VALUE * @param tickerScheme Expecting BLOOMBERG_TICKER_WEAK or BLOOMBERG_TICKER */ public BloombergCommodityFuturePriceCurveInstrumentProvider(final String futurePrefix, final String postfix, final String dataFieldName, String tickerScheme) { Validate.notNull(futurePrefix, "future option prefix"); Validate.notNull(postfix, "postfix"); Validate.notNull(dataFieldName, "data field name"); Validate.notNull(tickerScheme, "tickerScheme was null. Try BLOOMBERG_TICKER_WEAK or BLOOMBERG_TICKER"); _futurePrefix = futurePrefix; _postfix = postfix; _dataFieldName = dataFieldName; _tickerScheme = tickerScheme; } /** If a 4th argument is not provided, constructor uses BLOOMBERG_TICKER_WEAK as its ExternalScheme * @param futurePrefix Two character string representing future type. e.g. S , AA etc. * @param postfix Generally, "Comdty" * @param dataFieldName Expecting MarketDataRequirementNames.MARKET_PRICE */ public BloombergCommodityFuturePriceCurveInstrumentProvider(final String futurePrefix, final String postfix, final String dataFieldName) { Validate.notNull(futurePrefix, "future option prefix"); Validate.notNull(postfix, "postfix"); Validate.notNull(dataFieldName, "data field name"); _futurePrefix = futurePrefix; _postfix = postfix; _dataFieldName = dataFieldName; _tickerScheme = "BLOOMBERG_TICKER_WEAK"; } @Override public ExternalId getInstrument(final Number futureNumber) { throw new OpenGammaRuntimeException("Provider needs a curve date to create interest rate future identifier from futureNumber"); } @Override /** * Provides an ExternalID for Bloomberg ticker, * given a reference date and an integer offset, the n'th subsequent option <p> * The format is prefix + postfix <p> * e.g. S U3 Comdty * <p> * @param futureOptionNumber n'th future following curve date, not null * @param curveDate date of future validity; valuation date, not null * @return the id of the Bloomberg ticker */ public ExternalId getInstrument(final Number futureNumber, final LocalDate curveDate) { ArgumentChecker.notNull(futureNumber, "futureOptionNumber"); ArgumentChecker.notNull(curveDate, "curve date"); final StringBuffer ticker = new StringBuffer(); ticker.append(getFuturePrefix()); final ExchangeTradedInstrumentExpiryCalculator expiryRule = getExpiryRuleCalculator(); final LocalDate expiryDate = expiryRule.getExpiryMonth(futureNumber.intValue(), curveDate); final String expiryCode = BloombergFutureUtils.getShortExpiryCode(expiryDate); ticker.append(expiryCode); ticker.append(" "); ticker.append(getPostfix()); return ExternalId.of(getTickerScheme(), ticker.toString()); } public String getFuturePrefix() { return _futurePrefix; } public String getPostfix() { return _postfix; } @Override public String getTickerScheme() { return _tickerScheme; } @Override public String getDataFieldName() { return _dataFieldName; } @Override public int hashCode() { return getFuturePrefix().hashCode() + getPostfix().hashCode() + getDataFieldName().hashCode(); } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } if (!(obj instanceof BloombergCommodityFuturePriceCurveInstrumentProvider)) { return false; } final BloombergCommodityFuturePriceCurveInstrumentProvider other = (BloombergCommodityFuturePriceCurveInstrumentProvider) obj; return getFuturePrefix().equals(other.getFuturePrefix()) && getPostfix().equals(other.getPostfix()) && getDataFieldName().equals(other.getDataFieldName()); } @Override public ExchangeTradedInstrumentExpiryCalculator getExpiryRuleCalculator() { final ExchangeTradedInstrumentExpiryCalculator expiryRule = EXPIRY_RULES.get(getFuturePrefix()); if (expiryRule == null) { throw new OpenGammaRuntimeException("No expiry rule has been setup for " + getFuturePrefix() + ". Determine week and day pattern and add to EXPIRY_RULES."); } return expiryRule; } }