All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.market.sensitivity.CurveSensitivities Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.market.sensitivity;

import static com.opengamma.strata.collect.Guavate.toImmutableSet;
import static java.util.stream.Collectors.joining;

import java.io.Serializable;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collector;

import org.joda.beans.Bean;
import org.joda.beans.BeanBuilder;
import org.joda.beans.ImmutableBean;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaBean;
import org.joda.beans.MetaProperty;
import org.joda.beans.gen.BeanDefinition;
import org.joda.beans.gen.PropertyDefinition;
import org.joda.beans.impl.direct.DirectMetaBean;
import org.joda.beans.impl.direct.DirectMetaProperty;
import org.joda.beans.impl.direct.DirectMetaPropertyMap;
import org.joda.beans.impl.direct.DirectPrivateBeanBuilder;

import com.google.common.collect.ImmutableMap;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.FxConvertible;
import com.opengamma.strata.basics.currency.FxRateProvider;
import com.opengamma.strata.collect.MapStream;
import com.opengamma.strata.data.MarketDataName;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.param.CurrencyParameterSensitivitiesBuilder;
import com.opengamma.strata.market.param.ParameterMetadata;
import com.opengamma.strata.product.PortfolioItemInfo;
import com.opengamma.strata.product.PortfolioItemSummary;
import com.opengamma.strata.product.PortfolioItemType;
import com.opengamma.strata.product.ProductType;

/**
 * Sensitivity to a set of curves, used to pass risk into calculations.
 * 

* Sometimes it is useful to pass in a representation of risk rather than explicitly * listing the current portfolio of trades and/or positions. * This target is designed to allow this. *

* A map of sensitivities is provided, allowing both delta and gamma to be included if desired. */ @BeanDefinition(builderScope = "private") public final class CurveSensitivities implements Sensitivities, FxConvertible, ImmutableBean, Serializable { /** * An empty instance. */ private static final CurveSensitivities EMPTY = new CurveSensitivities(PortfolioItemInfo.empty(), ImmutableMap.of()); /** * The additional information. *

* This allows additional information to be attached to the sensitivities. */ @PropertyDefinition(validate = "notNull", overrideGet = true) private final PortfolioItemInfo info; /** * The sensitivities, keyed by type. *

* The map allows sensitivity to different types to be expressed. * For example, there might be both delta and gamma sensitivity. */ @PropertyDefinition(validate = "notNull") private final ImmutableMap typedSensitivities; //------------------------------------------------------------------------- /** * Obtains an empty instance. * * @return the empty sensitivities instance */ public static CurveSensitivities empty() { return EMPTY; } /** * Returns a builder that can be used to create an instance of {@code CurveSensitivities}. *

* The builder takes into account the parameter metadata when creating the sensitivity map. * As such, the parameter metadata added to the builder must not be empty. * * @param info the additional information * @return the builder */ public static CurveSensitivitiesBuilder builder(PortfolioItemInfo info) { return new CurveSensitivitiesBuilder(info); } /** * Obtains an instance from a single set of sensitivities. * * @param info the additional information * @param type the type of the sensitivities * @param sensitivities the sensitivities * @return the sensitivities instance */ public static CurveSensitivities of( PortfolioItemInfo info, CurveSensitivitiesType type, CurrencyParameterSensitivities sensitivities) { return new CurveSensitivities(info, ImmutableMap.of(type, sensitivities)); } /** * Obtains an instance from a map of sensitivities. * * @param info the additional information * @param typedSensitivities the map of sensitivities by type * @return the sensitivities instance */ public static CurveSensitivities of( PortfolioItemInfo info, Map typedSensitivities) { return new CurveSensitivities(info, ImmutableMap.copyOf(typedSensitivities)); } /** * Returns a collector that merges sensitivities. * * @return a collector that can merge sensitivities */ public static Collector toMergedSensitivities() { return Collector.of( () -> builder(PortfolioItemInfo.empty()), CurveSensitivitiesBuilder::add, CurveSensitivitiesBuilder::combine, CurveSensitivitiesBuilder::build); } //----------------------------------------------------------------------- /** * Gets a sensitivity instance by type, throwing an exception if not found. * * @param type the type to get * @return the sensitivity * @throws IllegalArgumentException if the type is not found */ public CurrencyParameterSensitivities getTypedSensitivity(CurveSensitivitiesType type) { CurrencyParameterSensitivities sens = typedSensitivities.get(type); if (sens == null) { throw new IllegalArgumentException("Unable to find sensitivities: " + type); } return sens; } /** * Finds a sensitivity instance by type, returning empty if not found. * * @param type the type to find * @return the sensitivity, empty if not found */ public Optional findTypedSensitivity(CurveSensitivitiesType type) { return Optional.ofNullable(typedSensitivities.get(type)); } //------------------------------------------------------------------------- /** * Merges this set of sensitivities with another set. *

* This returns a new curve sensitivities with a combined map of typed sensitivities. * Any sensitivities of the same type will be combined as though using * {@link CurrencyParameterSensitivities#mergedWith(CurrencyParameterSensitivities)}. * * @param other the other parameter sensitivities * @return an instance based on this one, with the other instance added */ public CurveSensitivities mergedWith(Map other) { // this uses a collector to merge all the instances at once which is more efficient than reduction // because it creates a single CurrencyParameterSensitivitiesBuilder ImmutableMap combinedSens = MapStream.concat(MapStream.of(typedSensitivities), MapStream.of(other)) .toMapGrouping(mergeSensitivities()); return new CurveSensitivities(info, combinedSens); } // collector to merge sensitivities private static Collector mergeSensitivities() { return Collector.of( CurrencyParameterSensitivities::builder, CurrencyParameterSensitivitiesBuilder::add, (l, r) -> l.add(r.build()), CurrencyParameterSensitivitiesBuilder::build); } /** * Combines this set of sensitivities with another set. *

* This returns a new curve sensitivities with a combined map of typed sensitivities. * Any sensitivities of the same type will be combined as though using * {@link CurrencyParameterSensitivities#mergedWith(CurrencyParameterSensitivities)}. * The identifier and attributes of this instance will take precedence. * * @param other the other parameter sensitivities * @return an instance based on this one, with the other instance added */ public CurveSensitivities mergedWith(CurveSensitivities other) { return new CurveSensitivities( info.combinedWith(other.info), mergedWith(other.typedSensitivities).getTypedSensitivities()); } //------------------------------------------------------------------------- /** * Checks and adjusts the market data names. *

* The supplied function is invoked for each market data name in this sensitivities. * A typical use case would be to convert index names to curve names valid for an underlying system. * * @param nameFn the function for checking and adjusting the name * @return the adjusted sensitivity * @throws RuntimeException if the function throws an exception */ public CurveSensitivities withMarketDataNames(Function, MarketDataName> nameFn) { return new CurveSensitivities( info, MapStream.of(typedSensitivities) .mapValues(sens -> sens.withMarketDataNames(nameFn)) .toMap()); } /** * Checks and adjusts the parameter metadata. *

* The supplied function is invoked for each parameter metadata in this sensitivities. * If the function returns the same metadata for two different inputs, the sensitivity value will be summed. * A typical use case would be to normalize parameter metadata tenors to be valid for an underlying system. * * @param mdFn the function for checking and adjusting the metadata * @return the adjusted sensitivity * @throws RuntimeException if the function throws an exception */ public CurveSensitivities withParameterMetadatas(UnaryOperator mdFn) { return new CurveSensitivities( info, MapStream.of(typedSensitivities) .mapValues(sens -> sens.withParameterMetadatas(mdFn)) .toMap()); } //------------------------------------------------------------------------- /** * Converts the sensitivities in this instance to an equivalent in the specified currency. *

* Any FX conversion that is required will use rates from the provider. * * @param resultCurrency the currency of the result * @param rateProvider the provider of FX rates * @return the sensitivity object expressed in terms of the result currency * @throws RuntimeException if no FX rate could be found */ @Override public CurveSensitivities convertedTo(Currency resultCurrency, FxRateProvider rateProvider) { return new CurveSensitivities( info, MapStream.of(typedSensitivities) .mapValues(v -> v.convertedTo(resultCurrency, rateProvider)) .toMap()); } //------------------------------------------------------------------------- @Override public PortfolioItemSummary summarize() { String typesStr = typedSensitivities.keySet().stream() .map(CurveSensitivitiesType::toString) .sorted() .collect(joining(", ", "CurveSensitivities[", "]")); return PortfolioItemSummary.of( getId().orElse(null), PortfolioItemType.SENSITIVITIES, ProductType.SENSITIVITIES, typedSensitivities.values().stream() .flatMap(s -> s.getSensitivities().stream()) .map(s -> s.getCurrency()) .collect(toImmutableSet()), typesStr); } @Override public CurveSensitivities withInfo(PortfolioItemInfo info) { return new CurveSensitivities(info, typedSensitivities); } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code CurveSensitivities}. * @return the meta-bean, not null */ public static CurveSensitivities.Meta meta() { return CurveSensitivities.Meta.INSTANCE; } static { MetaBean.register(CurveSensitivities.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private CurveSensitivities( PortfolioItemInfo info, Map typedSensitivities) { JodaBeanUtils.notNull(info, "info"); JodaBeanUtils.notNull(typedSensitivities, "typedSensitivities"); this.info = info; this.typedSensitivities = ImmutableMap.copyOf(typedSensitivities); } @Override public CurveSensitivities.Meta metaBean() { return CurveSensitivities.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the additional information. *

* This allows additional information to be attached to the sensitivities. * @return the value of the property, not null */ @Override public PortfolioItemInfo getInfo() { return info; } //----------------------------------------------------------------------- /** * Gets the sensitivities, keyed by type. *

* The map allows sensitivity to different types to be expressed. * For example, there might be both delta and gamma sensitivity. * @return the value of the property, not null */ public ImmutableMap getTypedSensitivities() { return typedSensitivities; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { CurveSensitivities other = (CurveSensitivities) obj; return JodaBeanUtils.equal(info, other.info) && JodaBeanUtils.equal(typedSensitivities, other.typedSensitivities); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(info); hash = hash * 31 + JodaBeanUtils.hashCode(typedSensitivities); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("CurveSensitivities{"); buf.append("info").append('=').append(JodaBeanUtils.toString(info)).append(',').append(' '); buf.append("typedSensitivities").append('=').append(JodaBeanUtils.toString(typedSensitivities)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code CurveSensitivities}. */ public static final class Meta extends DirectMetaBean { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code info} property. */ private final MetaProperty info = DirectMetaProperty.ofImmutable( this, "info", CurveSensitivities.class, PortfolioItemInfo.class); /** * The meta-property for the {@code typedSensitivities} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> typedSensitivities = DirectMetaProperty.ofImmutable( this, "typedSensitivities", CurveSensitivities.class, (Class) ImmutableMap.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "info", "typedSensitivities"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 3237038: // info return info; case 153032499: // typedSensitivities return typedSensitivities; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new CurveSensitivities.Builder(); } @Override public Class beanType() { return CurveSensitivities.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code info} property. * @return the meta-property, not null */ public MetaProperty info() { return info; } /** * The meta-property for the {@code typedSensitivities} property. * @return the meta-property, not null */ public MetaProperty> typedSensitivities() { return typedSensitivities; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 3237038: // info return ((CurveSensitivities) bean).getInfo(); case 153032499: // typedSensitivities return ((CurveSensitivities) bean).getTypedSensitivities(); } return super.propertyGet(bean, propertyName, quiet); } @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { metaProperty(propertyName); if (quiet) { return; } throw new UnsupportedOperationException("Property cannot be written: " + propertyName); } } //----------------------------------------------------------------------- /** * The bean-builder for {@code CurveSensitivities}. */ private static final class Builder extends DirectPrivateBeanBuilder { private PortfolioItemInfo info; private Map typedSensitivities = ImmutableMap.of(); /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 3237038: // info return info; case 153032499: // typedSensitivities return typedSensitivities; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 3237038: // info this.info = (PortfolioItemInfo) newValue; break; case 153032499: // typedSensitivities this.typedSensitivities = (Map) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public CurveSensitivities build() { return new CurveSensitivities( info, typedSensitivities); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("CurveSensitivities.Builder{"); buf.append("info").append('=').append(JodaBeanUtils.toString(info)).append(',').append(' '); buf.append("typedSensitivities").append('=').append(JodaBeanUtils.toString(typedSensitivities)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy