/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.core.id;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.DateTimeException;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZoneId;
import org.threeten.bp.format.DateTimeFormatter;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalScheme;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.PublicAPI;
import com.opengamma.util.i18n.Country;
import com.opengamma.util.money.Currency;
/**
* Utilities and constants for {@code Security}.
* <p>
* This is a thread-safe static utility class.
*/
@PublicAPI
public class ExternalSchemes {
/** Logger. */
private static final Logger s_logger = LoggerFactory.getLogger(ExternalSchemes.class);
// --------------------------- SCHEMES FOR USER IDENTITY ------------------------------------
/**
* Identification scheme for Windows user id.
*/
public static final ExternalScheme WINDOWS_USER_ID = ExternalScheme.of("WINDOWS_USER_ID");
/**
* Identification scheme for UUID identifier
*/
public static final ExternalScheme BLOOMBERG_UUID = ExternalScheme.of("BLOOMBERG_UUID");
/**
* Identification scheme for EMRSID identifier
*/
public static final ExternalScheme BLOOMBERG_EMRSID = ExternalScheme.of("BLOOMBERG_EMRSID");
// --------------------------- SCHEMES FOR SECURITIES AND RATES -----------------------------
/**
* Identification scheme for the ISIN code.
*/
public static final ExternalScheme ISIN = ExternalScheme.of("ISIN");
/**
* Identification scheme for the CUSIP code.
*/
public static final ExternalScheme CUSIP = ExternalScheme.of("CUSIP");
/**
* Identification scheme for the CUSIP entity stub code.
*/
public static final ExternalScheme CUSIP_ENTITY_STUB = ExternalScheme.of("CUSIP_ENTITY_STUB");
/**
* Identification scheme for SEDOL1.
*/
public static final ExternalScheme SEDOL1 = ExternalScheme.of("SEDOL1");
/**
* Identification scheme for Bloomberg BUIDs.
*/
public static final ExternalScheme BLOOMBERG_BUID = ExternalScheme.of("BLOOMBERG_BUID");
/**
* Identification scheme for weak Bloomberg BUIDs.
* A weak ID permits the underlying market data to return old data.
*/
public static final ExternalScheme BLOOMBERG_BUID_WEAK = ExternalScheme.of("BLOOMBERG_BUID_WEAK");
/**
* Identification scheme for Bloomberg tickers.
*/
public static final ExternalScheme BLOOMBERG_TICKER = ExternalScheme.of("BLOOMBERG_TICKER");
/**
* Identification scheme for weak Bloomberg tickers.
* A weak ID permits the underlying market data to return old data.
*/
public static final ExternalScheme BLOOMBERG_TICKER_WEAK = ExternalScheme.of("BLOOMBERG_TICKER_WEAK");
/**
* Identification scheme for Bloomberg tickers.
* @deprecated use BLOOMBERG_TICKER instead
*/
@Deprecated
public static final ExternalScheme BLOOMBERG_TCM = ExternalScheme.of("BLOOMBERG_TCM");
/**
* Identification scheme for conventions, using the stub of SECURITY_DES (minus date information)
*/
public static final ExternalScheme BLOOMBERG_CONVENTION_NAME = ExternalScheme.of("BLOOMBERG_CONVENTION_NAME");
/**
* Identification scheme for index families, using the stub of SECURITY_DES (minus date information)
*/
public static final ExternalScheme BLOOMBERG_INDEX_FAMILY = ExternalScheme.of("BLOOMBERG_INDEX_FAMILY");
/**
* Identification scheme for Reuters RICs.
*/
public static final ExternalScheme RIC = ExternalScheme.of("RIC");
/**
* Identification scheme for ActivFeed tickers.
*/
public static final ExternalScheme ACTIVFEED_TICKER = ExternalScheme.of("ACTIVFEED_TICKER");
/**
* Identification scheme for OpenGamma synthetic instruments.
*/
public static final ExternalScheme OG_SYNTHETIC_TICKER = ExternalScheme.of("OG_SYNTHETIC_TICKER");
/**
* Identification scheme for Tullett Prebon SURF tickers.
*/
public static final ExternalScheme SURF = ExternalScheme.of("SURF");
/**
* Identification scheme for ICAP market data feed tickers.
*/
public static final ExternalScheme ICAP = ExternalScheme.of("ICAP");
/**
* Identification scheme for GMI contracts.
*/
public static final ExternalScheme GMI = ExternalScheme.of("GMI");
/**
* Identification scheme conventions specified for ISDA.
*/
public static final ExternalScheme ISDA = ExternalScheme.of("ISDA");
// --------------------- SCHEMES FOR EXCHANGES ---------------------------
/**
* Identification scheme for CDS Index and Obligors.
*/
public static final ExternalScheme MARKIT_RED_CODE = ExternalScheme.of("MARKIT_RED_CODE");
//-------------------- SCHEMES FOR REGIONS ---------------------
/**
* Identification scheme for the ISO alpha 2 country code ISO standard.
*/
public static final ExternalScheme ISO_COUNTRY_ALPHA2 = ExternalScheme.of("ISO_COUNTRY_ALPHA2");
/**
* Identification scheme for the ISO alpha 3 currency code ISO standard.
*/
public static final ExternalScheme ISO_CURRENCY_ALPHA3 = ExternalScheme.of("ISO_CURRENCY_ALPHA3");
/**
* Identification scheme for the Copp Clark version of UN/LOCODE , formatted without spaces.
*/
public static final ExternalScheme COPP_CLARK_LOCODE = ExternalScheme.of("COPP_CLARK_LOCODE");
/**
* Identification scheme for the UN/LOCODE 2010-2 code standard, formatted without spaces.
*/
public static final ExternalScheme UN_LOCODE_2010_2 = ExternalScheme.of("UN_LOCODE_2010_2");
/**
* Identification scheme for the tz database time-zone standard.
*/
public static final ExternalScheme TZDB_TIME_ZONE = ExternalScheme.of("TZDB_TIME_ZONE");
/**
* Identification scheme for financial activity.
* This currently tends to be the country code, but can be more complex.
*/
public static final ExternalScheme FINANCIAL = ExternalScheme.of("FINANCIAL_REGION");
/**
* Identification scheme for the MIC exchange code ISO standard.
*/
public static final ExternalScheme ISO_MIC = ExternalScheme.of("ISO_MIC");
/**
* Identification scheme for holiday conventions specified for ISDA.
* Common examples include USNY, CATO, and EUTA.
*/
public static final ExternalScheme ISDA_HOLIDAY = ExternalScheme.of("ISDA_HOLIDAY");
/**
* Restricted constructor.
*/
protected ExternalSchemes() {
}
//------------------ METHODS FOR USER IDENTITY -----------------------------
/**
* Creates a Windows user id.
*
* @param windowsUserId the Windows user id, not null
* @return the identifier, not null
*/
public static ExternalId windowsUserId(String windowsUserId) {
ArgumentChecker.notNull(windowsUserId, "windowsUserId");
return ExternalId.of(ExternalSchemes.WINDOWS_USER_ID, windowsUserId);
}
/**
* Creates a UUID identifier.
* <p>
* This is an identifier for BPS bloomberg user.
*
* @param uuid the bps bloomberg user identifier, not null
* @return the user uuid identifier, not null
*/
public static ExternalId bloombergUuidUserId(final String uuid) {
return ExternalId.of(BLOOMBERG_UUID, ArgumentChecker.notNull(StringUtils.trimToNull(uuid), "uuid"));
}
/**
* Creates an EMRSID identifier.
* <p>
* This is an identifier for NON-BPS bloomberg user
*
* @param emrsid the non-bps bloomberg user identifier, not null
* @return the user emrsid identifier, not null
*/
public static ExternalId bloombergEmrsUserId(final String emrsid) {
return ExternalId.of(BLOOMBERG_EMRSID, ArgumentChecker.notNull(StringUtils.trimToNull(emrsid), "emrsid"));
}
//------------------ METHODS FOR SECURITIES AND RATES ----------------------
/**
* Creates an ISIN code.
* <p>
* This is the international standard securities identifying number.
* The first two characters are the ISO country code, followed by a 9 character
* alphanumeric national code and a single numeric check-digit.
* Example might be {@code US0231351067}.
*
* @param code the ISIN code, not null
* @return the security identifier, not null
*/
public static ExternalId isinSecurityId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.length() == 0) {
throw new IllegalArgumentException("ISIN code is invalid: " + code);
}
// if (code.matches("[A-Z]{2}[A-Z0-9]{9}[0-9]") == false) {
// throw new IllegalArgumentException("ISIN code is invalid: " + code);
// }
return ExternalId.of(ISIN, code);
}
/**
* Creates a CUSIP code.
* <p>
* This is the national securities identifying number for USA and Canada.
* The code should be 8 alphanumeric characters followed by a single numeric check-digit.
* Example might be {@code 023135106}.
*
* @param code the CUSIP code, not null
* @return the security identifier, not null
*/
public static ExternalId cusipSecurityId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.length() == 0) {
throw new IllegalArgumentException("CUSIP code is invalid: " + code);
}
// if (code.matches("[A-Z0-9]{8}[0-9]?") == false) {
// throw new IllegalArgumentException("CUSIP code is invalid: " + code);
// }
return ExternalId.of(CUSIP, code);
}
/**
* Creates a SEDOL code.
* <p>
* This is the national securities identifying number for UK and Ireland.
* The code should be 6 alphanumeric characters followed by a single numeric check-digit.
* Example might be {@code 0263494}.
*
* @param code the SEDOL code, not null
* @return the security identifier, not null
*/
public static ExternalId sedol1SecurityId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.length() == 0) {
throw new IllegalArgumentException("SEDOL1 code is invalid: " + code);
}
// if (code.matches("[A-Z0-9]{6}[0-9]?") == false) {
// throw new IllegalArgumentException("SEDOL1 code is invalid: " + code);
// }
return ExternalId.of(SEDOL1, code);
}
/**
* Creates a Bloomberg BIUD code.
* <p>
* This is the BUID code supplied by Bloomberg.
* Examples might be {@code EQ0010599500001000} or {@code IX6572023-0}.
*
* @param code the Bloomberg BIUD code, not null
* @return the security identifier, not null
*/
public static ExternalId bloombergBuidSecurityId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.length() == 0) {
throw new IllegalArgumentException("BUID code is invalid: " + code);
}
return ExternalId.of(BLOOMBERG_BUID, code);
}
/**
* Creates a Bloomberg ticker.
* <p>
* This is the ticker supplied by Bloomberg.
* Examples might be {@code MCO US Equity} or {@code CSCO US 01/21/12 C30 Equity}.
*
* @param ticker the Bloomberg ticker, not null
* @return the security identifier, not null
*/
public static ExternalId bloombergTickerSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "code");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(BLOOMBERG_TICKER, ticker);
}
/**
* Creates a Synthetic ticker.
* <p>
* This is the ticker used mainly by Examples-Simulated.
*
* @param ticker the OG-Synthetic ticker, not null
* @return the security identifier, not null
*/
public static ExternalId syntheticSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "ticker");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(OG_SYNTHETIC_TICKER, ticker);
}
/**
* Creates a Bloomberg ticker coupon maturity identifier.
* <p>
* This is the ticker combined with a coupon and a maturity supplied by Bloomberg.
* Example might be {@code T 4.75 15/08/43 Govt}.
*
* @param tickerWithoutSector the Bloomberg ticker without the sector, not null
* @param coupon the coupon, not null
* @param maturity the maturity date, not null
* @param marketSector the sector, not null
* @return the security identifier, not null
*/
public static ExternalId bloombergTCMSecurityId(final String tickerWithoutSector, final String coupon, final String maturity, final String marketSector) {
ArgumentChecker.notNull(tickerWithoutSector, "tickerWithoutSector");
ArgumentChecker.notNull(coupon, "coupon");
ArgumentChecker.notNull(maturity, "maturity");
ArgumentChecker.notNull(marketSector, "marketSector");
if (StringUtils.isEmpty(tickerWithoutSector)) {
throw new IllegalArgumentException("Ticker (without sector) must not be empty");
}
if (StringUtils.isEmpty(coupon)) {
throw new IllegalArgumentException("Coupon must not be empty, ticker = " + tickerWithoutSector);
}
if (StringUtils.isEmpty(maturity)) {
throw new IllegalArgumentException("Maturity must not be empty, ticker = " + tickerWithoutSector + ", coupon = " + coupon);
}
if (StringUtils.isEmpty(marketSector)) {
throw new IllegalArgumentException("Market sector must not be empty, ticker = " + tickerWithoutSector + ", coupon = " + coupon + ", maturity = " + maturity);
}
Double couponDbl;
try {
couponDbl = Double.parseDouble(coupon);
} catch (final NumberFormatException ex) {
throw new IllegalArgumentException("Coupon must be a valid double, ticker=" + tickerWithoutSector + ", coupon=" + coupon, ex);
}
if (s_logger.isDebugEnabled()) {
try {
LocalDate.parse(maturity, DateTimeFormatter.ofPattern("MM/dd/yy"));
} catch (final UnsupportedOperationException uoe) {
s_logger.warn("Problem parsing maturity " + maturity + " ticker=" + tickerWithoutSector + ", coupon=" + coupon);
} catch (final DateTimeException ex) {
s_logger.warn("Problem parsing maturity " + maturity + " ticker=" + tickerWithoutSector + ", coupon=" + coupon);
}
}
return ExternalId.of(BLOOMBERG_TCM, tickerWithoutSector + " " + couponDbl + " " + maturity + " " + marketSector);
}
/**
* Creates a Reuters RIC code.
* <p>
* This is the RIC code supplied by Reuters.
* Example might be {@code MSFT.OQ}.
*
* @param code the BIUD code, not null
* @return the security identifier, not null
*/
public static ExternalId ricSecurityId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.length() == 0) {
throw new IllegalArgumentException("RIC code is invalid: " + code);
}
return ExternalId.of(RIC, code);
}
/**
* Creates an ActivFeed ticker.
* <p>
* This is the ticker used by ActivFeed.
* Examples might be {@code IBM.N} or {@code C/04H.CB}.
*
* @param ticker the ActivFeed ticker, not null
* @return the security identifier, not null
*/
public static ExternalId activFeedTickerSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "code");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(ACTIVFEED_TICKER, ticker);
}
/**
* Creates a Tullett-Prebon ticker.
* <p>
* This is the ticker used by Tullett-Prebon.
* An example is {@code ASIRSUSD20Y30S03L}.
*
* @param ticker The Tullett-Prebon ticker, not null
* @return The security identifier, not null
*/
public static ExternalId tullettPrebonSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "ticker");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(SURF, ticker);
}
/**
* Creates an ICAP ticker.
* <p>
* This is the ticker used by ICAP.
*
* @param ticker The ICAP ticker, not null
* @return The security identifier, not null
*/
public static ExternalId icapSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "ticker");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(ICAP, ticker);
}
/**
* Creates a GMI ticker.
* <p>
* This is the ticker used by GMI.
*
* @param ticker The GMI ticker, not null
* @return The security identifier, not null
*/
public static ExternalId gmiSecurityId(final String ticker) {
ArgumentChecker.notNull(ticker, "ticker");
if (ticker.length() == 0) {
throw new IllegalArgumentException("Ticker is invalid: " + ticker);
}
return ExternalId.of(GMI, ticker);
}
/**
* Creates a MarkIt RED_CODE identifier
* <p>
* @param redcode the redcode identifier, not null or empty
* @return the security redcode identifier, not null
*/
public static ExternalId markItRedCode(final String redcode) {
ArgumentChecker.notNull(redcode, "redcode");
ArgumentChecker.isFalse(redcode.isEmpty(), "Empty redcode is invalid");
return ExternalId.of(MARKIT_RED_CODE, redcode);
}
/**
* Creates an ISDA identifier
* <p>
* @param isdaName the isda name, not null or empty
* @return the isda identifier, not null
*/
public static ExternalId isda(final String isdaName) {
ArgumentChecker.notEmpty(isdaName, "isdaname");
return ExternalId.of(ISDA, isdaName);
}
// -------------------------- METHODS FOR REGIONS ---------------------------
/**
* Creates an identifier for a financial location.
*
* @param code the code, not null
* @return the region identifier, not null
*/
public static ExternalId financialRegionId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.matches("[A-Z+]+") == false) {
throw new IllegalArgumentException("Code is invalid: " + code);
}
return ExternalId.of(ExternalSchemes.FINANCIAL, code);
}
/**
* Creates a tz database time-zone code.
* <p>
* Examples might be {@code Europe/London} or {@code Asia/Hong_Kong}.
*
* @param zone the time-zone, not null
* @return the region identifier, not null
*/
public static ExternalId timeZoneRegionId(final ZoneId zone) {
ArgumentChecker.notNull(zone, "zone");
return ExternalId.of(ExternalSchemes.TZDB_TIME_ZONE, zone.getId());
}
/**
* Creates a Copp Clark location code, formatted without spaces.
* This is based on UN/LOCODE.
* <p>
* Examples might be {@code GBHOH} or {@code AEDXB}.
*
* @param locode the Copp Clark LOCODE, not null
* @return the region identifier, not null
*/
public static ExternalId coppClarkRegionId(final String locode) {
ArgumentChecker.notNull(locode, "locode");
if (locode.matches("[A-Z]{2}[A-Z0-9]{3}") == false) {
throw new IllegalArgumentException("Copp Clark LOCODE is invalid: " + locode);
}
return ExternalId.of(ExternalSchemes.COPP_CLARK_LOCODE, locode);
}
/**
* Creates a UN/LOCODE 2010-2 code, formatted without spaces.
* <p>
* Examples might be {@code GBHOH} or {@code AEDXB}.
*
* @param locode the UN/LOCODE, not null
* @return the region identifier, not null
*/
public static ExternalId unLocode20102RegionId(final String locode) {
ArgumentChecker.notNull(locode, "locode");
if (locode.matches("[A-Z]{2}[A-Z0-9]{3}") == false) {
throw new IllegalArgumentException("UN/LOCODE is invalid: " + locode);
}
return ExternalId.of(ExternalSchemes.UN_LOCODE_2010_2, locode);
}
/**
* Creates an ISO alpha 3 currency code.
* <p>
* Examples might be {@code GBP} or {@code USD}.
*
* @param currency the currency, not null
* @return the region identifier, not null
*/
public static ExternalId currencyRegionId(final Currency currency) {
ArgumentChecker.notNull(currency, "currency");
return ExternalId.of(ExternalSchemes.ISO_CURRENCY_ALPHA3, currency.getCode());
}
/**
* Creates an ISO alpha 2 country code.
* <p>
* Examples might be {@code GB} or {@code US}.
*
* @param country the country, not null
* @return the region identifier, not null
*/
public static ExternalId countryRegionId(final Country country) {
ArgumentChecker.notNull(country, "country");
return ExternalId.of(ExternalSchemes.ISO_COUNTRY_ALPHA2, country.getCode());
}
//---------------------- METHODS FOR EXCHANGES ---------------------
/**
* Creates an ISO MIC code.
* <p>
* Examples might be {@code XLON} or {@code XNYS}.
*
* @param code the code, not null
* @return the region identifier, not null
*/
public static ExternalId isoMicExchangeId(final String code) {
ArgumentChecker.notNull(code, "code");
if (code.matches("[A-Z0-9]{4}([-][A-Z0-9]{3})?") == false) {
throw new IllegalArgumentException("ISO MIC code is invalid: " + code);
}
return ExternalId.of(ExternalSchemes.ISO_MIC, code);
}
//---------------------- HOLIDAYS ---------------------
/**
* Creates an ISDA holiday code.
* <p>
* Examples might be {@code USNY} or {@code EUTA}.
*
* @param code the code, not null
* @return the holiday identifier, not null
*/
public static ExternalId isdaHoliday(final String code) {
ArgumentChecker.notNull(code, "code");
return ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, code);
}
}