/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.tool.marketdata;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.LocalDate;
import com.opengamma.bbg.BloombergIdentifierProvider;
import com.opengamma.bbg.loader.hts.BloombergHistoricalTimeSeriesLoader;
import com.opengamma.component.tool.AbstractTool;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.financial.analytics.curve.CurveConstructionConfiguration;
import com.opengamma.financial.analytics.curve.CurveGroupConfiguration;
import com.opengamma.financial.analytics.curve.CurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.DiscountingCurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.IborCurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.InflationCurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.InflationIssuerCurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.IssuerCurveTypeConfiguration;
import com.opengamma.financial.analytics.curve.OvernightCurveTypeConfiguration;
import com.opengamma.financial.security.index.IborIndex;
import com.opengamma.financial.security.index.OvernightIndex;
import com.opengamma.id.ExternalId;
import com.opengamma.integration.tool.IntegrationToolContext;
import com.opengamma.master.config.ConfigDocument;
import com.opengamma.master.config.ConfigMaster;
import com.opengamma.master.config.ConfigSearchRequest;
import com.opengamma.master.config.impl.ConfigSearchIterator;
import com.opengamma.master.security.ManageableSecurity;
import com.opengamma.master.security.SecurityMaster;
import com.opengamma.master.security.SecuritySearchRequest;
import com.opengamma.master.security.SecuritySearchResult;
import com.opengamma.scripts.Scriptable;
/**
* Tool to load required time series for curve construction (for post 2.1.0 multi-curve framework)
*/
@Scriptable
public final class CurveTimeSeriesLoaderTool extends AbstractTool<IntegrationToolContext> {
/** Logger. */
private static Logger s_logger = LoggerFactory.getLogger(CurveTimeSeriesLoaderTool.class);
/** Write option flag */
private static final String WRITE_OPT = "w";
/** Verbose option flag */
private static final String VERBOSE_OPT = "v";
/** Time series data provider option flag */
private static final String TIME_SERIES_DATAPROVIDER_OPT = "p";
/** Time series data field option flag */
private static final String TIME_SERIES_DATAFIELD_OPT = "d";
//-------------------------------------------------------------------------
/**
* Main method to run the tool.
*
* @param args the standard tool arguments, not null
*/
public static void main(final String[] args) { // CSIGNORE
new CurveTimeSeriesLoaderTool().invokeAndTerminate(args);
}
//-------------------------------------------------------------------------
@Override
protected void doRun() {
final ConfigMaster configMaster = getToolContext().getConfigMaster();
final SecurityMaster securityMaster = getToolContext().getSecurityMaster();
// Find all matching curves
final List<CurveConstructionConfiguration> curveConstructionConfigs = getCurveConstructionConfigs(configMaster);
Set<ExternalId> ids = new LinkedHashSet<>();
for (CurveConstructionConfiguration curveConstructionConfig : curveConstructionConfigs) {
// search config for ids
ids.addAll(grepCurveConstructionConfigurationForIds(curveConstructionConfig));
}
// add ids for ibor indices currently loaded in sec master
ids.addAll(getIndexIds(securityMaster, IborIndex.INDEX_TYPE));
// add ids for overnight indices currently loaded in sec master
ids.addAll(getIndexIds(securityMaster, OvernightIndex.INDEX_TYPE));
// Load the required time series
loadHistoricalData(getCommandLine().hasOption(WRITE_OPT),
getCommandLine().getOptionValues(TIME_SERIES_DATAFIELD_OPT) == null ? new String[] {"PX_LAST" } : getCommandLine().getOptionValues(TIME_SERIES_DATAFIELD_OPT),
getCommandLine().getOptionValue(TIME_SERIES_DATAPROVIDER_OPT, "DEFAULT"),
ids);
}
/**
* Get all the curve construction configuration config objects
* @param configMaster
* @return list of curve construction configurations
*/
private List<CurveConstructionConfiguration> getCurveConstructionConfigs(final ConfigMaster configMaster) {
final List<CurveConstructionConfiguration> results = new ArrayList<CurveConstructionConfiguration>();
final ConfigSearchRequest<CurveConstructionConfiguration> request = new ConfigSearchRequest<CurveConstructionConfiguration>(CurveConstructionConfiguration.class);
for (final ConfigDocument doc : ConfigSearchIterator.iterable(configMaster, request)) {
results.add((CurveConstructionConfiguration) doc.getConfig().getValue());
}
return results;
}
/**
* go through the curve construction configuration and make a list of all the referenced ids that may need loading.
* @param curveConstructionConfig
* @return
*/
private Set<ExternalId> grepCurveConstructionConfigurationForIds(CurveConstructionConfiguration curveConstructionConfig) {
Set<ExternalId> externalIds = new HashSet<>();
for (CurveGroupConfiguration curveGroupConfig : curveConstructionConfig.getCurveGroups()) {
for (List<? extends CurveTypeConfiguration> curveTypeConfigurations : curveGroupConfig.getTypesForCurves().values()) {
for (CurveTypeConfiguration curveTypeConfiguration : curveTypeConfigurations) {
if (curveTypeConfiguration instanceof DiscountingCurveTypeConfiguration) {
@SuppressWarnings("unused")
DiscountingCurveTypeConfiguration discountingCurveTypeConfiguration = (DiscountingCurveTypeConfiguration) curveTypeConfiguration;
// do nothing for now
} else if (curveTypeConfiguration instanceof IborCurveTypeConfiguration) {
IborCurveTypeConfiguration iborCurveTypeConfiguration = (IborCurveTypeConfiguration) curveTypeConfiguration;
ExternalId convention = iborCurveTypeConfiguration.getConvention();
if (!convention.getScheme().equals("CONVENTION")) {
externalIds.add(convention);
}
} else if (curveTypeConfiguration instanceof InflationCurveTypeConfiguration) {
InflationCurveTypeConfiguration inflationCurveTypeConfiguration = (InflationCurveTypeConfiguration) curveTypeConfiguration;
ExternalId priceIndex = inflationCurveTypeConfiguration.getPriceIndex();
externalIds.add(priceIndex);
} else if (curveTypeConfiguration instanceof InflationIssuerCurveTypeConfiguration) {
InflationIssuerCurveTypeConfiguration inflationIssuerCurveTypeConfiguration = (InflationIssuerCurveTypeConfiguration) curveTypeConfiguration;
ExternalId priceIndex = inflationIssuerCurveTypeConfiguration.getPriceIndex();
externalIds.add(priceIndex);
} else if (curveTypeConfiguration instanceof IssuerCurveTypeConfiguration) {
@SuppressWarnings("unused")
IssuerCurveTypeConfiguration issuerCurveTypeConfiguration = (IssuerCurveTypeConfiguration) curveTypeConfiguration;
// do nothing for now
} else if (curveTypeConfiguration instanceof OvernightCurveTypeConfiguration) {
OvernightCurveTypeConfiguration overnightCurveTypeConfiguration = (OvernightCurveTypeConfiguration) curveTypeConfiguration;
ExternalId convention = overnightCurveTypeConfiguration.getConvention();
if (!convention.getScheme().equals("CONVENTION")) {
externalIds.add(convention);
}
} else {
s_logger.error("Not handling curve type configuration of class {}, skippings", curveTypeConfiguration.getClass());
}
}
}
}
return externalIds;
}
/**
* Search the security master for indices of the specified type and return the bloomberg tickers for each.
* @param secMaster the security master
* @param indexType the type of index (e.g. INDEX_TYPE on each Index subclass).
* @return bloomberg tickers for each index of given type
*/
private Collection<ExternalId> getIndexIds(SecurityMaster secMaster, String indexType) {
Set<ExternalId> externalIds = new LinkedHashSet<>();
SecuritySearchRequest searchRequest = new SecuritySearchRequest();
searchRequest.setSecurityType(indexType);
SecuritySearchResult searchResult = secMaster.search(searchRequest);
for (ManageableSecurity security : searchResult.getSecurities()) {
ExternalId externalId = security.getExternalIdBundle().getExternalId(ExternalSchemes.BLOOMBERG_TICKER);
if (externalId != null) {
externalIds.add(externalId);
} else {
s_logger.warn("No BLOOMBERG_TICKER for {}, skipping", security);
}
}
return externalIds;
}
/**
* Load the historical data
* @param write whether to actually add the data
* @param dataFields a list of fields to load
* @param dataProvider a data provider
* @param externalIdSets a varargs list of sets of external ids
*/
@SafeVarargs
private final void loadHistoricalData(final boolean write, final String[] dataFields, final String dataProvider, final Set<ExternalId>... externalIdSets) { //CSIGNORE
final BloombergHistoricalTimeSeriesLoader loader = new BloombergHistoricalTimeSeriesLoader(getToolContext().getHistoricalTimeSeriesMaster(), getToolContext()
.getHistoricalTimeSeriesProvider(), new BloombergIdentifierProvider(getToolContext().getBloombergReferenceDataProvider()));
for (final Set<ExternalId> externalIds : externalIdSets) {
if (externalIds.size() > 0) {
for (final String dataField : dataFields) {
s_logger.info("Loading time series (field: " + dataField + ", provider: " + dataProvider + ") with external IDs " + externalIds);
if (write) {
loader.loadTimeSeries(externalIds, dataProvider, dataField, LocalDate.now().minusYears(1), null);
}
}
}
}
}
@Override
protected Options createOptions(final boolean contextProvided) {
final Options options = super.createOptions(contextProvided);
final Option writeOption = new Option(WRITE_OPT, "write", false, "Actually persists the time series to the database if specified, otherwise pretty-prints without persisting");
options.addOption(writeOption);
final Option verboseOption = new Option(VERBOSE_OPT, "verbose", false, "Displays progress messages on the terminal");
options.addOption(verboseOption);
final Option timeSeriesDataProviderOption = new Option(TIME_SERIES_DATAPROVIDER_OPT, "provider", true, "The name of the time series data provider");
options.addOption(timeSeriesDataProviderOption);
final Option timeSeriesDataFieldOption = new Option(TIME_SERIES_DATAFIELD_OPT, "field", true, "The name(s) of the time series data field(s)");
options.addOption(timeSeriesDataFieldOption);
return options;
}
}