com.opengamma.integration.copier.snapshot.reader.FileSnapshotReader.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.integration.copier.snapshot.reader.FileSnapshotReader.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.integration.copier.snapshot.reader;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;

import com.opengamma.core.marketdatasnapshot.CurveKey;
import com.opengamma.core.marketdatasnapshot.CurveSnapshot;
import com.opengamma.core.marketdatasnapshot.UnstructuredMarketDataSnapshot;
import com.opengamma.core.marketdatasnapshot.ValueSnapshot;
import com.opengamma.core.marketdatasnapshot.VolatilitySurfaceKey;
import com.opengamma.core.marketdatasnapshot.VolatilitySurfaceSnapshot;
import com.opengamma.core.marketdatasnapshot.YieldCurveKey;
import com.opengamma.core.marketdatasnapshot.YieldCurveSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableCurveSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableUnstructuredMarketDataSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableVolatilitySurfaceSnapshot;
import com.opengamma.core.marketdatasnapshot.impl.ManageableYieldCurveSnapshot;
import com.opengamma.financial.analytics.volatility.surface.BloombergFXOptionVolatilitySurfaceInstrumentProvider;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.integration.copier.sheet.reader.CsvSheetReader;
import com.opengamma.integration.copier.snapshot.SnapshotColumns;
import com.opengamma.integration.copier.snapshot.SnapshotType;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.Tenor;
import com.opengamma.util.tuple.Pair;

/**
 * Reads a snapshot from an imported file
 */
public class FileSnapshotReader implements SnapshotReader {

    private static final Logger s_logger = LoggerFactory.getLogger(FileSnapshotReader.class);

    private CsvSheetReader _sheetReader;
    private Map<CurveKey, CurveSnapshot> _curves;
    private UnstructuredMarketDataSnapshot _global;
    private Map<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> _surface;
    private Map<YieldCurveKey, YieldCurveSnapshot> _yieldCurve;
    private String _name;
    private String _basisName;

    public FileSnapshotReader(String filename) {
        _sheetReader = new CsvSheetReader(filename);
        iterateSheetRows();
    }

    private void iterateSheetRows() {

        _curves = new HashMap<>();
        _surface = new HashMap<>();
        _yieldCurve = new HashMap<>();

        //Temporary maps for data structures
        HashMap<String, ManageableCurveSnapshot> curvesBuilder = new HashMap<>();
        HashMap<String, Pair<YieldCurveKey, ManageableYieldCurveSnapshot>> yieldCurveBuilder = new HashMap<>();
        HashMap<String, Pair<VolatilitySurfaceKey, ManageableVolatilitySurfaceSnapshot>> surfaceBuilder = new HashMap<>();
        ManageableUnstructuredMarketDataSnapshot globalBuilder = new ManageableUnstructuredMarketDataSnapshot();

        while (true) {
            Map<String, String> currentRow = _sheetReader.loadNextRow();

            // When rows are complete create snapshot elements from temporary structures
            if (currentRow == null) {
                for (Map.Entry<String, ManageableCurveSnapshot> entry : curvesBuilder.entrySet()) {
                    _curves.put(new CurveKey(entry.getKey()), entry.getValue());
                }
                for (Map.Entry<String, Pair<YieldCurveKey, ManageableYieldCurveSnapshot>> entry : yieldCurveBuilder
                        .entrySet()) {
                    _yieldCurve.put(entry.getValue().getFirst(), entry.getValue().getSecond());
                }
                for (Map.Entry<String, Pair<VolatilitySurfaceKey, ManageableVolatilitySurfaceSnapshot>> entry : surfaceBuilder
                        .entrySet()) {
                    _surface.put(entry.getValue().getFirst(), entry.getValue().getSecond());
                }
                _global = globalBuilder;
                return;
            }

            String type = currentRow.get(SnapshotColumns.TYPE.get());

            switch (SnapshotType.from(type)) {
            case NAME:
                _name = currentRow.get(SnapshotColumns.NAME.get());
                break;
            case BASIS_NAME:
                _basisName = currentRow.get(SnapshotColumns.NAME.get());
                break;
            case CURVE:
                buildCurves(curvesBuilder, currentRow);
                break;
            case YIELD_CURVE:
                buildYieldCurves(yieldCurveBuilder, currentRow);
                break;
            case GOBAL_VALUES:
                buildGlobalValues(globalBuilder, currentRow);
                break;
            case VOL_SURFACE:
                buildSurface(surfaceBuilder, currentRow);
                break;
            default:
                s_logger.error("Unknown snapshot element of type {}", type);
                break;
            }
        }
    }

    private void buildGlobalValues(ManageableUnstructuredMarketDataSnapshot globalBuilder,
            Map<String, String> currentRow) {
        globalBuilder.putValue(createExternalIdBundle(currentRow), currentRow.get(SnapshotColumns.VALUE_NAME.get()),
                createValueSnapshot(currentRow));
    }

    private void buildSurface(
            HashMap<String, Pair<VolatilitySurfaceKey, ManageableVolatilitySurfaceSnapshot>> surfaceBuilder,
            Map<String, String> currentRow) {
        String name = currentRow.get(SnapshotColumns.NAME.get());

        if (!surfaceBuilder.containsKey(name)) {
            ManageableVolatilitySurfaceSnapshot surface = new ManageableVolatilitySurfaceSnapshot();
            VolatilitySurfaceKey key = new VolatilitySurfaceKey(
                    UniqueId.parse(currentRow.get(SnapshotColumns.SURFACE_TARGET.get())),
                    currentRow.get(SnapshotColumns.NAME.get()),
                    currentRow.get(SnapshotColumns.SURFACE_INSTRUMENT_TYPE.get()),
                    currentRow.get(SnapshotColumns.SURFACE_QUOTE_TYPE.get()),
                    currentRow.get(SnapshotColumns.SURFACE_QUOTE_UNITS.get()));
            HashMap values = new HashMap<Pair<Object, Object>, ValueSnapshot>();

            values.put(Pair.of(currentRow.get(SnapshotColumns.SURFACE_X.get()),
                    currentRow.get(SnapshotColumns.SURFACE_Y.get())), createValueSnapshot(currentRow));
            surface.setValues(values);
            surfaceBuilder.put(name, Pair.of(key, surface));
        } else {
            surfaceBuilder.get(name).getSecond().getValues().put(createOrdinatePair(currentRow),
                    createValueSnapshot(currentRow));
        }

    }

    private void buildYieldCurves(
            HashMap<String, Pair<YieldCurveKey, ManageableYieldCurveSnapshot>> yieldCurveBuilder,
            Map<String, String> currentRow) {
        String name = currentRow.get(SnapshotColumns.NAME.get());

        if (!yieldCurveBuilder.containsKey(name)) {
            ManageableYieldCurveSnapshot curve = new ManageableYieldCurveSnapshot();
            ManageableUnstructuredMarketDataSnapshot snapshot = new ManageableUnstructuredMarketDataSnapshot();
            YieldCurveKey key = new YieldCurveKey(
                    Currency.of(currentRow.get(SnapshotColumns.YIELD_CURVE_CURRENCY.get())),
                    currentRow.get(SnapshotColumns.NAME.get()));

            curve.setValuationTime(Instant.parse(currentRow.get(SnapshotColumns.INSTANT.get())));
            snapshot.putValue(createExternalIdBundle(currentRow), currentRow.get(SnapshotColumns.VALUE_NAME.get()),
                    createValueSnapshot(currentRow));
            curve.setValues(snapshot);
            yieldCurveBuilder.put(name, Pair.of(key, curve));
        } else {
            yieldCurveBuilder.get(name).getSecond().getValues().putValue(createExternalIdBundle(currentRow),
                    currentRow.get(SnapshotColumns.VALUE_NAME.get()), createValueSnapshot(currentRow));
        }
    }

    private void buildCurves(HashMap<String, ManageableCurveSnapshot> curvesBuilder,
            Map<String, String> currentRow) {
        String name = currentRow.get(SnapshotColumns.NAME.get());

        if (!curvesBuilder.containsKey(name)) {
            ManageableCurveSnapshot curve = new ManageableCurveSnapshot();
            ManageableUnstructuredMarketDataSnapshot snapshot = new ManageableUnstructuredMarketDataSnapshot();

            curve.setValuationTime(Instant.parse(currentRow.get(SnapshotColumns.INSTANT.get())));
            snapshot.putValue(createExternalIdBundle(currentRow), currentRow.get(SnapshotColumns.VALUE_NAME.get()),
                    createValueSnapshot(currentRow));
            curve.setValues(snapshot);
            curvesBuilder.put(name, curve);
        } else {
            curvesBuilder.get(name).getValues().putValue(createExternalIdBundle(currentRow),
                    currentRow.get(SnapshotColumns.VALUE_NAME.get()), createValueSnapshot(currentRow));
        }

    }

    private Pair<Object, Object> createOrdinatePair(Map<String, String> currentRow) {
        String x = currentRow.get(SnapshotColumns.SURFACE_X.get());
        String[] y = currentRow.get(SnapshotColumns.SURFACE_Y.get()).split("\\|");
        Object surfaceX = null;
        Object surfaceY = null;

        if (x != null) {
            if (NumberUtils.isNumber(x)) {
                surfaceX = NumberUtils.createDouble(x);
            } else {
                try {
                    surfaceX = Tenor.parse(x);
                } catch (IllegalArgumentException e) {
                    s_logger.error("Volatility surface X ordinate {} should be a Double, Tenor or empty.", x);
                }
            }
        }

        if (y != null) {
            if (y.length == 1 && NumberUtils.isNumber(y[0])) {
                surfaceY = NumberUtils.createDouble(y[0]);
            } else {
                try {
                    surfaceY = createYOrdinatePair(y);
                } catch (IllegalArgumentException e) {
                    s_logger.error(
                            "Volatility surface Y ordinate {} should be a Double, Pair<Number, FXVolQuoteType> or empty.",
                            x);
                }
            }
        }

        return Pair.of(surfaceX, surfaceY);
    }

    // Bloomberg FX option volatility surface codes given a tenor, quote type (ATM, butterfly, risk reversal) and distance from ATM.
    private Pair<Number, BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType> createYOrdinatePair(
            String[] yPair) {
        Number firstElement = null;
        BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType secondElement = null;
        if (NumberUtils.isNumber(yPair[0])) {
            firstElement = NumberUtils.createDouble(yPair[0]);
        }
        switch (yPair[1]) {
        case "ATM":
            secondElement = BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType.ATM;
            break;
        case "RISK_REVERSAL":
            secondElement = BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType.RISK_REVERSAL;
            break;
        case "BUTTERFLY":
            secondElement = BloombergFXOptionVolatilitySurfaceInstrumentProvider.FXVolQuoteType.BUTTERFLY;
            break;
        }
        return Pair.of(firstElement, secondElement);
    }

    private ValueSnapshot createValueSnapshot(Map<String, String> currentRow) {
        String market = currentRow.get(SnapshotColumns.MARKET_VALUE.get());
        String override = currentRow.get(SnapshotColumns.OVERRIDE_VALUE.get());
        Object marketValue = null;
        Object overrideValue = null;

        // marketValue can only be Double, LocalDate or empty
        if (market != null) {
            if (NumberUtils.isNumber(market)) {
                marketValue = NumberUtils.createDouble(market);
            } else {
                try {
                    marketValue = LocalDate.parse(market);
                } catch (IllegalArgumentException e) {
                    s_logger.error("Market value {} should be a Double, LocalDate or empty.", market);
                }
            }
        }

        //overrideValue can only be Double, LocalDate or empty
        if (override != null) {
            if (NumberUtils.isNumber(override)) {
                overrideValue = NumberUtils.createDouble(override);
            } else {
                try {
                    overrideValue = LocalDate.parse(override);
                } catch (IllegalArgumentException e) {
                    s_logger.error("Override value {} should be a Double, LocalDate or empty.", override);
                }
            }
        }

        return new ValueSnapshot(marketValue, overrideValue);
    }

    private ExternalIdBundle createExternalIdBundle(Map<String, String> currentRow) {
        Iterable<String> iterable = Arrays.asList(currentRow.get(SnapshotColumns.ID_BUNDLE.get()).split("\\|"));
        return ExternalIdBundle.parse(iterable);
    }

    @Override
    public Map<CurveKey, CurveSnapshot> readCurves() {
        return _curves;
    }

    @Override
    public UnstructuredMarketDataSnapshot readGlobalValues() {
        return _global;
    }

    @Override
    public Map<VolatilitySurfaceKey, VolatilitySurfaceSnapshot> readVolatilitySurfaces() {
        return _surface;
    }

    @Override
    public Map<YieldCurveKey, YieldCurveSnapshot> readYieldCurves() {
        return _yieldCurve;
    }

    @Override
    public void close() {
        _sheetReader.close();
    }

    @Override
    public String getName() {
        return _name;
    }

    @Override
    public String getBasisViewName() {
        return _basisName;
    }
}