/**
* 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 java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.DayOfWeek;
import org.threeten.bp.LocalDate;
import org.threeten.bp.format.DateTimeFormatter;
import com.opengamma.analytics.financial.schedule.NoHolidayCalendar;
import com.opengamma.financial.analytics.ircurve.NextExpiryAdjuster;
import com.opengamma.financial.analytics.model.FutureOptionExpiries;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.expirycalc.DaysFromEndOfMonthExpiryAdjuster;
import com.opengamma.financial.convention.expirycalc.ExchangeTradedInstrumentExpiryCalculator;
import com.opengamma.id.ExternalId;
import com.opengamma.util.ArgumentChecker;
/**
* Provides ExternalIds for equity future options used to build a volatility surface
*/
public class BloombergEquityFutureOptionVolatilitySurfaceInstrumentProvider extends BloombergFutureOptionVolatilitySurfaceInstrumentProvider {
/** The logger */
private static final Logger s_logger = LoggerFactory.getLogger(BloombergEquityFutureOptionVolatilitySurfaceInstrumentProvider.class);
/** The date-time formatter */
private static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("MM/dd/yy");
/** The expiry rules */
private static final HashMap<String, ExchangeTradedInstrumentExpiryCalculator> EXPIRY_RULES;
/** An empty holiday calendar */
private static final Calendar NO_HOLIDAYS = new NoHolidayCalendar();
static {
EXPIRY_RULES = new HashMap<>();
EXPIRY_RULES.put("NKY", FutureOptionExpiries.of(new NextExpiryAdjuster(2, DayOfWeek.FRIDAY)));
EXPIRY_RULES.put("NDX", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1))); //TODO
EXPIRY_RULES.put("RUT", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1))); //TODO
EXPIRY_RULES.put("DJX", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1)));
EXPIRY_RULES.put("SPX", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1)));
EXPIRY_RULES.put("VIX", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, -30)));
EXPIRY_RULES.put("AAPL US", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1)));
EXPIRY_RULES.put("UKX", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY)));
EXPIRY_RULES.put("FB US", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1)));
EXPIRY_RULES.put("TWSE", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.WEDNESDAY)));
EXPIRY_RULES.put("HSCEI", new DaysFromEndOfMonthExpiryAdjuster(1));
EXPIRY_RULES.put("RDXUSD", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.THURSDAY, 1)));
EXPIRY_RULES.put("DEFAULT", FutureOptionExpiries.of(new NextExpiryAdjuster(3, DayOfWeek.FRIDAY, 1)));
//TODO DAX, EUROSTOXX 50 (SX5E)
}
/**
* Uses the default ticker scheme (BLOOMBERG_TICKER_WEAK)
* @param futureOptionPrefix the prefix to the resulting code (e.g. DJX), not null
* @param postfix the postfix to the resulting code (e.g. Index), not null
* @param dataFieldName the name of the data field, not null. Expecting MarketDataRequirementNames.IMPLIED_VOLATILITY or OPT_IMPLIED_VOLATILITY_MID
* @param useCallAboveStrike the strike above which to use calls rather than puts, not null
* @param exchangeIdName the exchange id, not null
*/
public BloombergEquityFutureOptionVolatilitySurfaceInstrumentProvider(final String futureOptionPrefix, final String postfix, final String dataFieldName, final Double useCallAboveStrike,
final String exchangeIdName) {
super(futureOptionPrefix, postfix, dataFieldName, useCallAboveStrike, exchangeIdName);
}
/**
* @param futureOptionPrefix the prefix to the resulting code (e.g. DJX), not null
* @param postfix the postfix to the resulting code (e.g. Index), not null
* @param dataFieldName the name of the data field, not null. Expecting MarketDataRequirementNames.IMPLIED_VOLATILITY or OPT_IMPLIED_VOLATILITY_MID
* @param useCallAboveStrike the strike above which to use calls rather than puts, not null
* @param exchangeIdName the exchange id, not null
* @param schemeName the ticker scheme name, not null
*/
public BloombergEquityFutureOptionVolatilitySurfaceInstrumentProvider(final String futureOptionPrefix, final String postfix, final String dataFieldName, final Double useCallAboveStrike,
final String exchangeIdName, final String schemeName) {
super(futureOptionPrefix, postfix, dataFieldName, useCallAboveStrike, exchangeIdName, schemeName);
}
/**
* Provides an ExternalID for Bloomberg ticker,
* given a reference date and an integer offset, the n'th subsequent option <p>
* The format is prefix + date + callPutFlag + strike + postfix <p>
* e.g. DJX 12/21/13 C145.0 Index
* <p>
* @param futureOptionNumber n'th future following curve date, not null
* @param strike option's strike, expressed as price in %, e.g. 98.750, not null
* @param surfaceDate date of curve validity; valuation date, not null
* @return the id of the Bloomberg ticker
*/
@Override
public ExternalId getInstrument(final Number futureOptionNumber, final Double strike, final LocalDate surfaceDate) {
ArgumentChecker.notNull(futureOptionNumber, "futureOptionNumber");
ArgumentChecker.notNull(strike, "strike");
ArgumentChecker.notNull(surfaceDate, "surface date");
final String prefix = getFutureOptionPrefix();
final StringBuffer ticker = new StringBuffer();
ticker.append(prefix);
ticker.append(" ");
final ExchangeTradedInstrumentExpiryCalculator expiryRule = getExpiryRuleCalculator();
final LocalDate expiry = expiryRule.getExpiryDate(futureOptionNumber.intValue(), surfaceDate, NO_HOLIDAYS);
ticker.append(FORMAT.format(expiry));
ticker.append(" ");
ticker.append(strike > useCallAboveStrike() ? "C" : "P");
ticker.append(strike);
ticker.append(" ");
ticker.append(getPostfix());
return ExternalId.of(getScheme(), ticker.toString());
}
/**
* Gets the expiryRules.
* @return the expiryRules
*/
public static HashMap<String, ExchangeTradedInstrumentExpiryCalculator> getExpiryRules() {
return EXPIRY_RULES;
}
@Override
public ExchangeTradedInstrumentExpiryCalculator getExpiryRuleCalculator() {
final String prefix = getFutureOptionPrefix();
ExchangeTradedInstrumentExpiryCalculator expiryRule = EXPIRY_RULES.get(prefix);
if (expiryRule == null) {
s_logger.info("No expiry rule has been setup for " + prefix + ". Using Default of 3rd Friday.");
expiryRule = EXPIRY_RULES.get("DEFAULT");
}
return expiryRule;
}
}