org.quil.interpreter.strata.QuilMarketDataBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.quil.interpreter.strata.QuilMarketDataBuilder.java

Source

package org.quil.interpreter.strata;

/**
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */

import static com.opengamma.strata.collect.Guavate.toImmutableList;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.ignite.igfs.IgfsPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.io.CharSource;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.FxRate;
import com.opengamma.strata.collect.Messages;
import com.opengamma.strata.collect.io.ResourceLocator;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.data.FxRateId;
import com.opengamma.strata.data.ImmutableMarketData;
import com.opengamma.strata.data.ImmutableMarketDataBuilder;
import com.opengamma.strata.data.ObservableId;
import com.opengamma.strata.loader.csv.FixingSeriesCsvLoader;
import com.opengamma.strata.loader.csv.QuotesCsvLoader;
import com.opengamma.strata.loader.csv.RatesCurvesCsvLoader;
import com.opengamma.strata.market.curve.CurveGroup;
import com.opengamma.strata.market.curve.CurveGroupId;
import com.opengamma.strata.market.curve.CurveId;
import com.opengamma.strata.market.observable.QuoteId;
import com.opengamma.strata.measure.rate.RatesMarketDataLookup;
import com.opengamma.strata.pricer.credit.IsdaYieldCurveInputs;
import com.opengamma.strata.pricer.credit.IsdaYieldCurveInputsId;

public abstract class QuilMarketDataBuilder {

    private static final Logger log = LoggerFactory.getLogger(QuilMarketDataBuilder.class);

    /** The name of the subdirectory containing historical fixings. */
    private static final String HISTORICAL_FIXINGS_DIR = "historical-fixings";

    /** The name of the subdirectory containing calibrated rates curves. */
    private static final String CURVES_DIR = "curves";
    /** The name of the curve groups file. */
    private static final String CURVES_GROUPS_FILE = "groups.csv";
    /** The name of the curve settings file. */
    private static final String CURVES_SETTINGS_FILE = "settings.csv";

    /** The name of the directory containing CDS ISDA yield curve, credit curve and static data. */
    private static final String CREDIT_DIR = "credit";
    private static final String CDS_YIELD_CURVES_FILE = "cds.yieldCurves.csv";
    private static final String SINGLE_NAME_CREDIT_CURVES_FILE = "singleName.creditCurves.csv";
    private static final String SINGLE_NAME_STATIC_DATA_FILE = "singleName.staticData.csv";
    private static final String INDEX_CREDIT_CURVES_FILE = "index.creditCurves.csv";
    private static final String INDEX_STATIC_DATA_FILE = "index.staticData.csv";

    /** The name of the subdirectory containing simple market quotes. */
    private static final String QUOTES_DIR = "quotes";
    /** The name of the quotes file. */
    private static final String QUOTES_FILE = "quotes.csv";

    //-------------------------------------------------------------------------
    /**
     * Creates an instance from a given classpath resource root location using the class loader
     * which created this class.
     * <p>
     * This is designed to handle resource roots which may physically correspond to a directory on
     * disk, or be located within a jar file.
     *
     * @param resourceRoot  the resource root path
     * @return the market data builder
     */
    public static QuilMarketDataBuilder ofResource(String resourceRoot) {
        return ofResource(resourceRoot, QuilMarketDataBuilder.class.getClassLoader());
    }

    /**
     * Creates an instance from a given classpath resource root location, using the given class loader
     * to find the resource.
     * <p>
     * This is designed to handle resource roots which may physically correspond to a directory on
     * disk, or be located within a jar file.
     *
     * @param resourceRoot  the resource root path
     * @param classLoader  the class loader with which to find the resource
     * @return the market data builder
     */
    public static QuilMarketDataBuilder ofResource(String resourceRoot, ClassLoader classLoader) {
        // classpath resources are forward-slash separated
        String qualifiedRoot = resourceRoot;
        qualifiedRoot = qualifiedRoot.startsWith("/") ? qualifiedRoot.substring(1) : qualifiedRoot;
        qualifiedRoot = qualifiedRoot.startsWith("\\") ? qualifiedRoot.substring(1) : qualifiedRoot;
        qualifiedRoot = qualifiedRoot.endsWith("/") ? qualifiedRoot : qualifiedRoot + "/";
        URL url = classLoader.getResource(qualifiedRoot);
        if (url == null) {
            throw new IllegalArgumentException(Messages.format("Classpath resource not found: {}", qualifiedRoot));
        }
        if (url.getProtocol() != null && "jar".equals(url.getProtocol().toLowerCase(Locale.ENGLISH))) {
            // Inside a JAR
            int classSeparatorIdx = url.getFile().indexOf("!");
            if (classSeparatorIdx == -1) {
                throw new IllegalArgumentException(Messages.format("Unexpected JAR file URL: {}", url));
            }
            String jarPath = url.getFile().substring("file:".length(), classSeparatorIdx);
            File jarFile;
            try {
                jarFile = new File(jarPath);
            } catch (Exception e) {
                throw new IllegalArgumentException(Messages.format("Unable to create file for JAR: {}", jarPath),
                        e);
            }
            return new JarMarketDataBuilder(jarFile, resourceRoot);
        } else if (url.getProtocol() != null && "igfs".equals(url.getProtocol().toLowerCase(Locale.ENGLISH))) {

            log.info("Loading MarketData from " + url.toString());

            String rootPath = url.toString().replace("igfs:", "");

            return new IgfsMarketDataBuilder(new IgfsPath(rootPath));

        } else {
            // Resource is on disk
            File file;
            try {
                file = new File(url.toURI());
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException(Messages.format("Unexpected file location: {}", url), e);
            }
            return new DirectoryMarketDataBuilder(file.toPath());
        }
    }

    /**
     * Creates an instance from a given directory root.
     *
     * @param rootPath  the root directory
     * @return the market data builder
     */
    public static QuilMarketDataBuilder ofPath(Path rootPath) {
        return new DirectoryMarketDataBuilder(rootPath);
    }

    public static QuilMarketDataBuilder ofIgfsPath(IgfsPath rootPath) {

        log.info("Loading MarketData from " + rootPath.toString());

        return new IgfsMarketDataBuilder(rootPath);
    }

    //-------------------------------------------------------------------------
    /**
     * Builds a market data snapshot from this environment.
     *
     * @param marketDataDate  the date of the market data
     * @return the snapshot
     */
    public ImmutableMarketData buildSnapshot(LocalDate marketDataDate) {
        ImmutableMarketDataBuilder builder = ImmutableMarketData.builder(marketDataDate);
        loadFixingSeries(builder);
        loadRatesCurves(builder, marketDataDate);
        loadQuotes(builder, marketDataDate);
        loadFxRates(builder);
        return builder.build();
    }

    /**
     * Gets the rates market lookup to use with this environment.
     *
     * @param marketDataDate  the date of the market data
     * @return the rates lookup
     */
    public RatesMarketDataLookup ratesLookup(LocalDate marketDataDate) {
        SortedMap<LocalDate, CurveGroup> curves = loadAllRatesCurves();
        return RatesMarketDataLookup.of(curves.get(marketDataDate));
    }

    /**
     * Gets all rates curves.
     *
     * @return the map of all rates curves
     */
    public SortedMap<LocalDate, CurveGroup> loadAllRatesCurves() {
        if (!subdirectoryExists(CURVES_DIR)) {
            throw new IllegalArgumentException("No rates curves directory found");
        }
        ResourceLocator curveGroupsResource = getResource(CURVES_DIR, CURVES_GROUPS_FILE);
        if (curveGroupsResource == null) {
            throw new IllegalArgumentException(
                    Messages.format("Unable to load rates curves: curve groups file not found at {}/{}", CURVES_DIR,
                            CURVES_GROUPS_FILE));
        }
        ResourceLocator curveSettingsResource = getResource(CURVES_DIR, CURVES_SETTINGS_FILE);
        if (curveSettingsResource == null) {
            throw new IllegalArgumentException(
                    Messages.format("Unable to load rates curves: curve settings file not found at {}/{}",
                            CURVES_DIR, CURVES_SETTINGS_FILE));
        }
        ListMultimap<LocalDate, CurveGroup> curveGroups = RatesCurvesCsvLoader.loadAllDates(curveGroupsResource,
                curveSettingsResource, getRatesCurvesResources());

        // There is only one curve group in the market data file so this will always succeed
        Map<LocalDate, CurveGroup> curveGroupMap = Maps.transformValues(curveGroups.asMap(),
                groups -> groups.iterator().next());
        return new TreeMap<>(curveGroupMap);
    }

    //-------------------------------------------------------------------------
    private void loadFixingSeries(ImmutableMarketDataBuilder builder) {
        if (!subdirectoryExists(HISTORICAL_FIXINGS_DIR)) {
            log.debug("No historical fixings directory found");
            return;
        }
        try {

            Collection<ResourceLocator> fixingSeriesResources = getAllResources(HISTORICAL_FIXINGS_DIR);
            Map<ObservableId, LocalDateDoubleTimeSeries> fixingSeries = FixingSeriesCsvLoader
                    .load(fixingSeriesResources);
            builder.addTimeSeriesMap(fixingSeries);
        } catch (Exception e) {
            log.error("Error loading fixing series", e);
        }
    }

    private void loadRatesCurves(ImmutableMarketDataBuilder builder, LocalDate marketDataDate) {
        if (!subdirectoryExists(CURVES_DIR)) {
            log.debug("No rates curves directory found");
            return;
        }

        ResourceLocator curveGroupsResource = getResource(CURVES_DIR, CURVES_GROUPS_FILE);
        if (curveGroupsResource == null) {
            log.error("Unable to load rates curves: curve groups file not found at {}/{}", CURVES_DIR,
                    CURVES_GROUPS_FILE);
            return;
        }

        ResourceLocator curveSettingsResource = getResource(CURVES_DIR, CURVES_SETTINGS_FILE);
        if (curveSettingsResource == null) {
            log.error("Unable to load rates curves: curve settings file not found at {}/{}", CURVES_DIR,
                    CURVES_SETTINGS_FILE);
            return;
        }
        try {
            Collection<ResourceLocator> curvesResources = getRatesCurvesResources();
            List<CurveGroup> ratesCurves = RatesCurvesCsvLoader.load(marketDataDate, curveGroupsResource,
                    curveSettingsResource, curvesResources);

            for (CurveGroup group : ratesCurves) {
                // add entry for each group
                builder.addValue(CurveGroupId.of(group.getName()), group);
                // add entry for higher level discount curve name
                group.getDiscountCurves().forEach(
                        (ccy, curve) -> builder.addValue(CurveId.of(group.getName(), curve.getName()), curve));
                // add entry for higher level forward curve name
                group.getForwardCurves().forEach(
                        (idx, curve) -> builder.addValue(CurveId.of(group.getName(), curve.getName()), curve));
            }

        } catch (Exception e) {
            log.error("Error loading rates curves", e);
        }
    }

    // load quotes
    private void loadQuotes(ImmutableMarketDataBuilder builder, LocalDate marketDataDate) {
        if (!subdirectoryExists(QUOTES_DIR)) {
            log.debug("No quotes directory found");
            return;
        }

        ResourceLocator quotesResource = getResource(QUOTES_DIR, QUOTES_FILE);
        if (quotesResource == null) {
            log.error("Unable to load quotes: quotes file not found at {}/{}", QUOTES_DIR, QUOTES_FILE);
            return;
        }

        try {
            Map<QuoteId, Double> quotes = QuotesCsvLoader.load(marketDataDate, quotesResource);
            builder.addValueMap(quotes);

        } catch (Exception ex) {
            log.error("Error loading quotes", ex);
        }
    }

    private void loadFxRates(ImmutableMarketDataBuilder builder) {
        // TODO - load from CSV file - format to be defined
        builder.addValue(
                FxRateId.of(com.opengamma.strata.basics.currency.Currency.GBP,
                        com.opengamma.strata.basics.currency.Currency.USD),
                FxRate.of(com.opengamma.strata.basics.currency.Currency.GBP,
                        com.opengamma.strata.basics.currency.Currency.USD, 1.61));
    }

    //-------------------------------------------------------------------------
    private Collection<ResourceLocator> getRatesCurvesResources() {
        return getAllResources(CURVES_DIR).stream().filter(res -> !res.getLocator().endsWith(CURVES_GROUPS_FILE))
                .filter(res -> !res.getLocator().endsWith(CURVES_SETTINGS_FILE)).collect(toImmutableList());
    }

    //-------------------------------------------------------------------------
    /**
     * Gets all available resources from a given subdirectory.
     *
     * @param subdirectoryName  the name of the subdirectory
     * @return a collection of locators for the resources in the subdirectory
     */
    protected abstract Collection<ResourceLocator> getAllResources(String subdirectoryName);

    /**
     * Gets a specific resource from a given subdirectory.
     *
     * @param subdirectoryName  the name of the subdirectory
     * @param resourceName  the name of the resource
     * @return a locator for the requested resource
     */
    protected abstract ResourceLocator getResource(String subdirectoryName, String resourceName);

    /**
     * Checks whether a specific subdirectory exists.
     *
     * @param subdirectoryName  the name of the subdirectory
     * @return whether the subdirectory exists
     */
    protected abstract boolean subdirectoryExists(String subdirectoryName);

}