/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.volatility.surface; import org.apache.commons.lang.ObjectUtils; import org.threeten.bp.LocalDate; import org.threeten.bp.Period; import com.opengamma.OpenGammaRuntimeException; import com.opengamma.core.id.ExternalSchemes; import com.opengamma.financial.analytics.volatility.surface.BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalScheme; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.time.Tenor; import com.opengamma.util.tuple.Pair; /** * Autogenerates ICAP FX option volatility surface codes given a tenor, quote type (ATM, butterfly, risk reversal) and distance from * ATM. */ public class ICAPFXOptionVolatilitySurfaceInstrumentProvider implements SurfaceInstrumentProvider<Tenor, Pair<Number, FXVolQuoteType>> { /** Butterfly */ private static final String BF_STRING = "BF"; /** Risk reversal */ private static final String RR_STRING = "RR"; /** String representing years */ private static final String YR_STRING = "YR"; /** String representing months */ private static final String M_STRING = "M"; /** String representing weeks */ private static final String WK_STRING = "WK"; /** The ICAP scheme */ private static final ExternalScheme SCHEME = ExternalSchemes.ICAP; /** The prefix */ private final String _fxPrefix; /** The currency pair */ private final String _ccyPair; /** The data field name */ private final String _dataFieldName; /** * @param fxPrefix The code prefix, not null * @param ccyPair The currency pair, not null * @param dataFieldName The data field name, not null */ public ICAPFXOptionVolatilitySurfaceInstrumentProvider(final String fxPrefix, final String ccyPair, final String dataFieldName) { ArgumentChecker.notNull(fxPrefix, "fx prefix"); ArgumentChecker.notNull(ccyPair, "curreny pair"); ArgumentChecker.notNull(dataFieldName, "data field name"); _fxPrefix = fxPrefix; _ccyPair = ccyPair; _dataFieldName = dataFieldName; } /** * Gets the code prefix. * @return The code prefix */ public String getFXPrefix() { return _fxPrefix; } /** * Gets the currency pair. * @return The currency pair */ public String getCurrencyPair() { return _ccyPair; } @Override public ExternalId getInstrument(final Tenor xAxis, final Pair<Number, FXVolQuoteType> yAxis) { ArgumentChecker.notNull(xAxis, "x axis"); ArgumentChecker.notNull(yAxis, "y axis"); final StringBuffer ticker = new StringBuffer(_fxPrefix); ticker.append(_ccyPair); final int delta = yAxis.getFirst().intValue(); final FXVolQuoteType quoteType = yAxis.getSecond(); if (delta != 0) { switch (quoteType) { case ATM: throw new OpenGammaRuntimeException("Asked for an ATM code with non-zero delta"); case RISK_REVERSAL: ticker.append(RR_STRING); ticker.append(delta); break; case BUTTERFLY: ticker.append(BF_STRING); ticker.append(delta); break; default: throw new OpenGammaRuntimeException("Did not recognise quote type " + quoteType); } } ticker.append("_"); final Period period = xAxis.getPeriod(); if (period.getYears() != 0) { ticker.append(period.getYears()); ticker.append(YR_STRING); } else if (period.getMonths() != 0) { ticker.append(period.getMonths()); ticker.append(M_STRING); } else if (period.getDays() != 0) { if (period.getDays() % 7 != 0) { throw new OpenGammaRuntimeException("Can only handle tenors with periods in weeks; have " + period.getDays()); } ticker.append(period.getDays() / 7); ticker.append(WK_STRING); } return ExternalId.of(SCHEME, ticker.toString()); } @Override public ExternalId getInstrument(final Tenor xAxis, final Pair<Number, FXVolQuoteType> yAxis, final LocalDate surfaceDate) { return getInstrument(xAxis, yAxis); } @Override public String getDataFieldName() { return _dataFieldName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _ccyPair.hashCode(); result = prime * result + _dataFieldName.hashCode(); result = prime * result + _fxPrefix.hashCode(); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ICAPFXOptionVolatilitySurfaceInstrumentProvider other = (ICAPFXOptionVolatilitySurfaceInstrumentProvider) obj; if (!ObjectUtils.equals(_ccyPair, other._ccyPair)) { return false; } if (!ObjectUtils.equals(_fxPrefix, other._fxPrefix)) { return false; } if (!ObjectUtils.equals(_dataFieldName, other._dataFieldName)) { return false; } return true; } }