/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.analytics.model.equity; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.opengamma.core.id.ExternalSchemes; import com.opengamma.core.security.Security; import com.opengamma.core.security.SecuritySource; import com.opengamma.financial.security.FinancialSecurity; import com.opengamma.financial.security.FinancialSecurityUtils; import com.opengamma.financial.security.FinancialSecurityVisitorSameValueAdapter; import com.opengamma.financial.security.option.EquityIndexOptionSecurity; import com.opengamma.financial.security.option.EquityOptionSecurity; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalScheme; import com.opengamma.id.UniqueId; import com.opengamma.util.ArgumentChecker; /** * Utility class for equity index options, equity barrier options, equity options and equity variance swaps. */ public final class EquitySecurityUtils { /** The logger */ private static final Logger s_logger = LoggerFactory.getLogger(EquitySecurityUtils.class); /** mapping between surface names and data schemes */ private static final Map<String, ExternalScheme> SCHEME_MAPPING = new HashMap<>(); /** mapping between source external schemes and destination schemes i.e. BBG_TICKER_WEAK -> BBG_TICKER */ private static final HashMap<ExternalScheme, ExternalScheme> SCHEME_REMAPPING = new HashMap<>(); static { SCHEME_MAPPING.put("DEFAULT", ExternalSchemes.BLOOMBERG_TICKER_WEAK); SCHEME_MAPPING.put("ACTIV", ExternalSchemes.ACTIVFEED_TICKER); SCHEME_MAPPING.put("BBG", ExternalSchemes.BLOOMBERG_TICKER_WEAK); SCHEME_MAPPING.put("ICAP", ExternalSchemes.ICAP); SCHEME_MAPPING.put("TULLET", ExternalSchemes.SURF); SCHEME_REMAPPING.put(ExternalSchemes.BLOOMBERG_TICKER_WEAK, ExternalSchemes.BLOOMBERG_TICKER); } private EquitySecurityUtils() { } /** * Gets the underlying index or equity name from a security. At the moment, only securities with a Bloomberg ticker or BUID (if the security is an equity index option) are handled. For a Bloomberg * ticker, the suffix is stripped (SPX Index -> SPX). For a BUID, the last three letters are assumed to be the name. * * @param security The security, not null * @return The equity or index name, null if the underlying id is not a BUID or Bloomberg ticker */ public static String getIndexOrEquityNameFromUnderlying(final Security security) { return getIndexOrEquityNameFromUnderlying(security, false); } /** * Gets the underlying index or equity name from a security. At the moment, only securities with a Bloomberg ticker or BUID (if the security is an equity index option) are handled. For a Bloomberg * ticker, the suffix is stripped (SPX Index -> SPX). For a BUID, the last three letters are assumed to be the name. * * @param security The security, not null * @param stopAtFirstSpace true if one wishes result to include id up to first space (eg true : "IBM US Equity" => "IBM", false : => "IBM US"). * @return The equity or index name, null if the underlying id is not a BUID or Bloomberg ticker */ public static String getIndexOrEquityNameFromUnderlying(final Security security, final boolean stopAtFirstSpace) { ArgumentChecker.notNull(security, "security"); final ExternalId underlyingId = FinancialSecurityUtils.getUnderlyingId(security); if (underlyingId == null) { s_logger.error("Underlying id for security {} was null", security); return null; } final String value = underlyingId.getValue(); final ExternalScheme scheme = underlyingId.getScheme(); if (scheme.equals(ExternalSchemes.BLOOMBERG_BUID) || scheme.equals(ExternalSchemes.BLOOMBERG_BUID_WEAK)) { if (security instanceof EquityIndexOptionSecurity) { final int length = value.length(); return value.substring(length - 3, length).toUpperCase(); //TODO fix this } s_logger.info("Can only use BUIDs for equity index options; have {}", security); return null; } else if (scheme.equals(ExternalSchemes.BLOOMBERG_TICKER) || scheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK)) { if (stopAtFirstSpace) { final int firstSpace = value.indexOf(" "); return value.substring(0, firstSpace); } final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } s_logger.info("Cannot handle scheme of type {}", scheme); return null; } /** * Gets the underlying index or equity name from an external id. At the moment, only ids with a Bloomberg ticker are handled. For a Bloomberg ticker, the suffix is stripped (SPX Index -> SPX). * * @param underlyingId The security, not null * @return The equity or index name, null if the underlying id is not a Bloomberg ticker */ public static String getIndexOrEquityNameFromUnderlying(final ExternalId underlyingId) { ArgumentChecker.notNull(underlyingId, "underlying id"); final String value = underlyingId.getValue(); final ExternalScheme scheme = underlyingId.getScheme(); if (scheme.equals(ExternalSchemes.BLOOMBERG_TICKER) || scheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK)) { final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } s_logger.info("Cannot handle scheme of type {}", scheme); return null; } /** * Gets the underlying index or equity name from a unique id. At the moment, only securities with a Bloomberg ticker or BUID (if the security is an equity index option) are handled. For a Bloomberg * ticker, the suffix is stripped (SPX Index -> SPX). For a BUID, the last three letters are assumed to be the name. * * @param externalId The unique id, not null * @return The equity or index name, null if the underlying id is not a BUID or Bloomberg ticker */ public static String getIndexOrEquityName(final ExternalId externalId) { //FIXME: Modify to take ExternalId to avoid incorrect cast to UniqueId ArgumentChecker.notNull(externalId, "unique id"); final String value = externalId.getValue(); final ExternalScheme extScheme = externalId.getScheme(); if (extScheme.equals(ExternalSchemes.BLOOMBERG_BUID) || extScheme.equals(ExternalSchemes.BLOOMBERG_BUID_WEAK)) { final int length = value.length(); return value.substring(length - 3, length).toUpperCase(); //TODO fix this } if (extScheme.equals(ExternalSchemes.BLOOMBERG_TICKER) || extScheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK)) { final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } if (extScheme.equals(ExternalSchemes.ACTIVFEED_TICKER)) { final int firstDot = value.indexOf(".", 0); return value.substring(0, firstDot + 1); // e.g. "IBM." } s_logger.info("Cannot handle scheme of type {}", extScheme); return null; } /* * * public static String getIndexOrEquityName(final UniqueId uniqueId) { //FIXME: Modify to take ExternalId to avoid incorrect cast to UniqueId ArgumentChecker.notNull(uniqueId, "unique id"); final String value = uniqueId.getValue(); final String uidScheme = uniqueId.getScheme(); final String extScheme; if (uidScheme.substring(0, 11).equalsIgnoreCase("ExternalId-")) { extScheme = uidScheme.substring(11); } else { extScheme = uidScheme; } if (extScheme.equals(ExternalSchemes.BLOOMBERG_BUID.getName()) || extScheme.equals(ExternalSchemes.BLOOMBERG_BUID_WEAK.getName())) { final int length = value.length(); return value.substring(length - 3, length).toUpperCase(); //TODO fix this } if (extScheme.equals(ExternalSchemes.BLOOMBERG_TICKER.getName()) || extScheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK.getName())) { final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } if (extScheme.equals(ExternalSchemes.ACTIVFEED_TICKER.getName())) { final int firstDot = value.indexOf(".", 0); return value.substring(0, firstDot + 1); // e.g. "IBM." } s_logger.info("Cannot handle scheme of type {}", uidScheme); return null; } */ /** * Removes the postfix if the uid is a Bloomberg ticker. * * @param uid The unique id, not null * @return The ticker without postfix * @deprecated holding a Bloomberg ticker in a unique identifier is normally wrong */ @Deprecated public static String getTrimmedTarget(final UniqueId uid) { ArgumentChecker.notNull(uid, "unique id"); final String value = uid.getValue(); if (uid.getScheme().equals(ExternalSchemes.BLOOMBERG_TICKER.getName()) || uid.getScheme().equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK.getName())) { final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } return value; } /** * Removes the postfix if the identifier is a Bloomberg ticker. * * @param identifier The ticker identifier * @return The ticker without postfix */ public static String getTrimmedTarget(final ExternalId identifier) { ArgumentChecker.notNull(identifier, "identifier"); final String value = identifier.getValue(); if (identifier.getScheme().equals(ExternalSchemes.BLOOMBERG_TICKER) || identifier.getScheme().equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK)) { final int lastSpace = value.lastIndexOf(" "); return value.substring(0, lastSpace); } return value; } /** * Gets the exchange given a unique id representing an equity underlying. If the id scheme is weak, this is transformed before the security is requested from the security source. * * @param securitySource The security source, not null * @param id The id of the equity, not null * @return The exchange or null if there is no security for this id in the source. */ public static String getExchange(final SecuritySource securitySource, final UniqueId id) { ArgumentChecker.notNull(securitySource, "security source"); ArgumentChecker.notNull(id, "unique id"); return "CBOE"; // final String scheme; // final String originalScheme = id.getScheme(); // if (originalScheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK.getName())) { // scheme = ExternalSchemes.BLOOMBERG_TICKER.getName(); // } else if (originalScheme.equals(ExternalSchemes.BLOOMBERG_BUID_WEAK.getName())) { // scheme = ExternalSchemes.BLOOMBERG_BUID.getName(); // } else { // scheme = originalScheme; // } // final String value = id.getValue(); // final ExternalId ticker = ExternalId.of(scheme, value); // final Security security = securitySource.getSingle(ExternalIdBundle.of(ticker)); // if (security == null) { // return null; // } // return FinancialSecurityUtils.getExchange(security).getValue(); } /** * Gets the currency given a unique id representing an equity underlying. If the id scheme is weak, this is transformed before the security is requested from the security source. * * @param securitySource The security source, not null * @param id The id of the equity, not null * @return The currency or null if there is no security for this id in the source. */ public static String getCurrency(final SecuritySource securitySource, final UniqueId id) { ArgumentChecker.notNull(securitySource, "security source"); ArgumentChecker.notNull(id, "unique id"); return "USD"; // final String scheme; // final String originalScheme = id.getScheme(); // if (originalScheme.equals(ExternalSchemes.BLOOMBERG_TICKER_WEAK.getName())) { // scheme = ExternalSchemes.BLOOMBERG_TICKER.getName(); // } else if (originalScheme.equals(ExternalSchemes.BLOOMBERG_BUID_WEAK.getName())) { // scheme = ExternalSchemes.BLOOMBERG_BUID.getName(); // } else { // scheme = originalScheme; // } // final String value = id.getValue(); // final ExternalId ticker = ExternalId.of(scheme, value); // final Security security = securitySource.getSingle(ExternalIdBundle.of(ticker)); // if (security == null) { // return null; // } // return FinancialSecurityUtils.getCurrency(security).getCode(); } /** * Determine the data scheme from the surface name e.g. BBG -> Bloomberg ticker * * @param surfaceName the surface or curve name * @return the scheme */ //TODO: This should be moved somewhere non equity specific public static ExternalScheme getTargetType(final String surfaceName) { final ExternalScheme target = SCHEME_MAPPING.get(surfaceName); if (target == null) { s_logger.warn("Can't determine data scheme from surface/curve name: " + surfaceName); return null; } return target; } /** * Get scheme which maps onto this one * * @param scheme the destination scheme * @return the source scheme */ public static ExternalScheme getRemappedScheme(final ExternalScheme scheme) { final ExternalScheme remappedScheme = SCHEME_REMAPPING.get(scheme); if (remappedScheme == null) { return scheme; //no remapping } return remappedScheme; } public static Double getPointValue(final Security security) { if (security instanceof FinancialSecurity) { final FinancialSecurity financialSecurity = (FinancialSecurity) security; final Double pointValue = financialSecurity.accept(new FinancialSecurityVisitorSameValueAdapter<Double>(null) { @Override public Double visitEquityOptionSecurity(final EquityOptionSecurity equityOption) { return equityOption.getPointValue(); } @Override public Double visitEquityIndexOptionSecurity(final EquityIndexOptionSecurity equityIndexOption) { return equityIndexOption.getPointValue(); } }); return pointValue; } return null; } }