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

com.opengamma.strata.market.param.CrossGammaParameterSensitivity Maven / Gradle / Ivy

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

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.function.DoubleUnaryOperator;

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.ImmutableValidator;
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.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.FxConvertible;
import com.opengamma.strata.basics.currency.FxRateProvider;
import com.opengamma.strata.collect.Messages;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.collect.array.DoubleMatrix;
import com.opengamma.strata.collect.tuple.Pair;
import com.opengamma.strata.data.MarketDataName;
import com.opengamma.strata.market.curve.Curve;

/**
 * The second order parameter sensitivity for parameterized market data.
 * 

* Parameter sensitivity is the sensitivity of a value to the parameters of a * {@linkplain ParameterizedData parameterized market data} object that is used to determine the value. * The main application of this class is the parameter sensitivities for curves. * Thus {@code ParameterizedData} is typically {@link Curve}. *

* The sensitivity is expressed as a matrix. * The {@code (i,j)} component is the sensitivity of the {@code i}-th component of the {@code parameterMetadata} delta to * the {@code j}-th parameter in {@code order}. *

* The sensitivity represents a monetary value in the specified currency. */ @BeanDefinition(builderScope = "private") public final class CrossGammaParameterSensitivity implements FxConvertible, ImmutableBean, Serializable { /** * The market data name. *

* This name is used in the market data system to identify the data that the sensitivities refer to. */ @PropertyDefinition(validate = "notNull") private final MarketDataName marketDataName; /** * The list of parameter metadata. *

* There is one entry for each parameter. */ @PropertyDefinition(validate = "notNull", builderType = "List") private final ImmutableList parameterMetadata; /** * The sensitivity order. *

* This defines the order of sensitivity values, which can be used as a key to interpret {@code sensitivity}. */ @PropertyDefinition(validate = "notNull", builderType = "List, List>>") private final ImmutableList, List>> order; /** * The currency of the sensitivity. */ @PropertyDefinition(validate = "notNull") private final Currency currency; /** * The parameter sensitivity values. *

* The curve delta sensitivities to parameterized market data. * This is a {@code n x m} matrix, where {@code n} must agree with the size of {@code parameterMetadata} and * {@code m} must be the sum of parameter count in {@code order}. */ @PropertyDefinition(validate = "notNull") private final DoubleMatrix sensitivity; //------------------------------------------------------------------------- /** * Obtains an instance from the market data name, metadata, currency and sensitivity. *

* This creates a sensitivity instance which stores the second order sensitivity values to a single market data, i.e., * the block diagonal part of the full second order sensitivity matrix. *

* The market data name identifies the {@link ParameterizedData} instance that was queried. * The parameter metadata provides information on each parameter. * The size of the parameter metadata list must match the size of the sensitivity array. * * @param marketDataName the name of the market data that the sensitivity refers to * @param parameterMetadata the parameter metadata * @param currency the currency of the sensitivity * @param sensitivity the sensitivity values, one for each parameter * @return the sensitivity object */ public static CrossGammaParameterSensitivity of( MarketDataName marketDataName, List parameterMetadata, Currency currency, DoubleMatrix sensitivity) { return of(marketDataName, parameterMetadata, marketDataName, parameterMetadata, currency, sensitivity); } /** * Obtains an instance from the market data names, metadatas, currency and sensitivity. *

* This creates a sensitivity instance which stores the second order sensitivity values: the delta of a market data * to another market data. The first market data and the second market data can be the same. *

* The market data name identifies the {@link ParameterizedData} instance that was queried. * The parameter metadata provides information on each parameter. * * @param marketDataName the name of the first market data that the sensitivity refers to * @param parameterMetadata the first parameter metadata * @param marketDataNameOther the name of the second market data that the sensitivity refers to * @param parameterMetadataOther the second parameter metadata * @param currency the currency of the sensitivity * @param sensitivity the sensitivity values, one for each parameter * @return the sensitivity object */ public static CrossGammaParameterSensitivity of( MarketDataName marketDataName, List parameterMetadata, MarketDataName marketDataNameOther, List parameterMetadataOther, Currency currency, DoubleMatrix sensitivity) { return new CrossGammaParameterSensitivity(marketDataName, parameterMetadata, ImmutableList.of(Pair.of(marketDataNameOther, parameterMetadataOther)), currency, sensitivity); } /** * Obtains an instance from the market data names, metadatas, currency and sensitivity. *

* This creates a sensitivity instance which stores the second order sensitivity values: the delta of a market data * to a set of other market data. * The market data set is represented in terms of {@code List, List>>}. * which defines the order of the sensitivity values. *

* The market data name identifies the {@link ParameterizedData} instance that was queried. * The parameter metadata provides information on each parameter. * * @param marketDataName the name of the market data that the sensitivity refers to * @param parameterMetadata the parameter metadata * @param order the order * @param currency the currency of the sensitivity * @param sensitivity the sensitivity values, one for each parameter * @return the sensitivity object */ public static CrossGammaParameterSensitivity of( MarketDataName marketDataName, List parameterMetadata, List, List>> order, Currency currency, DoubleMatrix sensitivity) { return new CrossGammaParameterSensitivity(marketDataName, parameterMetadata, order, currency, sensitivity); } @ImmutableValidator private void validate() { int col = sensitivity.columnCount(); int row = sensitivity.rowCount(); if (row != parameterMetadata.size()) { throw new IllegalArgumentException("row count of sensitivity and parameter metadata size must match"); } int nParamsTotal = 0; for (Pair, List> entry : order) { nParamsTotal += entry.getSecond().size(); } if (col != nParamsTotal) { throw new IllegalArgumentException("column count of sensitivity and total parameter metadata size of order must match"); } } //------------------------------------------------------------------------- /** * Gets the number of parameters. *

* This returns the number of parameters in the {@link ParameterizedData} instance * which is the same size as the sensitivity array. * * @return the number of parameters */ public int getParameterCount() { return sensitivity.rowCount(); } /** * Gets the parameter metadata at the specified index. *

* If there is no specific parameter metadata, an empty instance will be returned. * * @param parameterIndex the zero-based index of the parameter to get * @return the metadata of the parameter * @throws IndexOutOfBoundsException if the index is invalid */ public ParameterMetadata getParameterMetadata(int parameterIndex) { return parameterMetadata.get(parameterIndex); } /** * Compares the key of two sensitivity objects, excluding the parameter sensitivity values. * * @param other the other sensitivity object * @return positive if greater, zero if equal, negative if less */ public int compareKey(CrossGammaParameterSensitivity other) { return ComparisonChain.start() .compare(marketDataName, other.marketDataName) .compare(order.toString(), other.order.toString()) .compare(currency, other.currency) .result(); } //------------------------------------------------------------------------- /** * Converts this sensitivity 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 CrossGammaParameterSensitivity convertedTo(Currency resultCurrency, FxRateProvider rateProvider) { if (currency.equals(resultCurrency)) { return this; } double fxRate = rateProvider.fxRate(currency, resultCurrency); return mapSensitivity(s -> s * fxRate, resultCurrency); } //------------------------------------------------------------------------- /** * Returns an instance with the sensitivity values multiplied by the specified factor. *

* Each value in the sensitivity array will be multiplied by the factor. * * @param factor the multiplicative factor * @return an instance based on this one, with each sensitivity multiplied by the factor */ public CrossGammaParameterSensitivity multipliedBy(double factor) { return mapSensitivity(s -> s * factor); } /** * Returns an instance with the specified operation applied to the sensitivity values. *

* Each value in the sensitivity array will be operated on. * For example, the operator could multiply the sensitivities by a constant, or take the inverse. *

   *   inverse = base.mapSensitivity(value -> 1 / value);
   * 
* * @param operator the operator to be applied to the sensitivities * @return an instance based on this one, with the operator applied to the sensitivity values */ public CrossGammaParameterSensitivity mapSensitivity(DoubleUnaryOperator operator) { return mapSensitivity(operator, currency); } // maps the sensitivities and potentially changes the currency private CrossGammaParameterSensitivity mapSensitivity(DoubleUnaryOperator operator, Currency currency) { return new CrossGammaParameterSensitivity(marketDataName, parameterMetadata, order, currency, sensitivity.map(operator)); } /** * Returns an instance with new parameter sensitivity values. * * @param sensitivity the new sensitivity values * @return an instance based on this one, with the specified sensitivity values */ public CrossGammaParameterSensitivity withSensitivity(DoubleMatrix sensitivity) { return new CrossGammaParameterSensitivity(marketDataName, parameterMetadata, order, currency, sensitivity); } //------------------------------------------------------------------------- /** * Returns the total of the sensitivity values. * * @return the total sensitivity values */ public CurrencyAmount total() { return CurrencyAmount.of(currency, sensitivity.total()); } /** * Returns the diagonal part of the sensitivity as {@code CurrencyParameterSensitivity}. * * @return the diagonal part */ public CurrencyParameterSensitivity diagonal() { CrossGammaParameterSensitivity blockDiagonal = getSensitivity(getMarketDataName()); int size = getParameterCount(); return CurrencyParameterSensitivity.of( getMarketDataName(), getParameterMetadata(), getCurrency(), DoubleArray.of(size, i -> blockDiagonal.getSensitivity().get(i, i))); } /** * Returns the sensitivity to the market data specified by {@code name}. *

* This returns a sensitivity instance which stores the sensitivity of the {@code marketDataName} delta to another * market data of {@code name}. * * @param name the name * @return the sensitivity * @throws IllegalArgumentException if the name does not match an entry */ public CrossGammaParameterSensitivity getSensitivity(MarketDataName name) { Pair> indexAndMetadata = findStartIndexAndMetadata(name); int startIndex = indexAndMetadata.getFirst(); int rowCt = getParameterCount(); int colCt = indexAndMetadata.getSecond().size(); double[][] sensi = new double[rowCt][colCt]; for (int i = 0; i < rowCt; ++i) { System.arraycopy(getSensitivity().rowArray(i), startIndex, sensi[i], 0, colCt); } return CrossGammaParameterSensitivity.of( getMarketDataName(), getParameterMetadata(), name, indexAndMetadata.getSecond(), getCurrency(), DoubleMatrix.ofUnsafe(sensi)); } private Pair> findStartIndexAndMetadata(MarketDataName name) { int startIndex = 0; for (Pair, List> entry : order) { if (entry.getFirst().equals(name)) { return Pair.of(startIndex, entry.getSecond()); } startIndex += entry.getSecond().size(); } throw new IllegalArgumentException(Messages.format("Unable to find sensitivity: {} and {}", marketDataName, name)); } //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code CrossGammaParameterSensitivity}. * @return the meta-bean, not null */ public static CrossGammaParameterSensitivity.Meta meta() { return CrossGammaParameterSensitivity.Meta.INSTANCE; } static { MetaBean.register(CrossGammaParameterSensitivity.Meta.INSTANCE); } /** * The serialization version id. */ private static final long serialVersionUID = 1L; private CrossGammaParameterSensitivity( MarketDataName marketDataName, List parameterMetadata, List, List>> order, Currency currency, DoubleMatrix sensitivity) { JodaBeanUtils.notNull(marketDataName, "marketDataName"); JodaBeanUtils.notNull(parameterMetadata, "parameterMetadata"); JodaBeanUtils.notNull(order, "order"); JodaBeanUtils.notNull(currency, "currency"); JodaBeanUtils.notNull(sensitivity, "sensitivity"); this.marketDataName = marketDataName; this.parameterMetadata = ImmutableList.copyOf(parameterMetadata); this.order = ImmutableList.copyOf(order); this.currency = currency; this.sensitivity = sensitivity; validate(); } @Override public CrossGammaParameterSensitivity.Meta metaBean() { return CrossGammaParameterSensitivity.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the market data name. *

* This name is used in the market data system to identify the data that the sensitivities refer to. * @return the value of the property, not null */ public MarketDataName getMarketDataName() { return marketDataName; } //----------------------------------------------------------------------- /** * Gets the list of parameter metadata. *

* There is one entry for each parameter. * @return the value of the property, not null */ public ImmutableList getParameterMetadata() { return parameterMetadata; } //----------------------------------------------------------------------- /** * Gets the sensitivity order. *

* This defines the order of sensitivity values, which can be used as a key to interpret {@code sensitivity}. * @return the value of the property, not null */ public ImmutableList, List>> getOrder() { return order; } //----------------------------------------------------------------------- /** * Gets the currency of the sensitivity. * @return the value of the property, not null */ public Currency getCurrency() { return currency; } //----------------------------------------------------------------------- /** * Gets the parameter sensitivity values. *

* The curve delta sensitivities to parameterized market data. * This is a {@code n x m} matrix, where {@code n} must agree with the size of {@code parameterMetadata} and * {@code m} must be the sum of parameter count in {@code order}. * @return the value of the property, not null */ public DoubleMatrix getSensitivity() { return sensitivity; } //----------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj.getClass() == this.getClass()) { CrossGammaParameterSensitivity other = (CrossGammaParameterSensitivity) obj; return JodaBeanUtils.equal(marketDataName, other.marketDataName) && JodaBeanUtils.equal(parameterMetadata, other.parameterMetadata) && JodaBeanUtils.equal(order, other.order) && JodaBeanUtils.equal(currency, other.currency) && JodaBeanUtils.equal(sensitivity, other.sensitivity); } return false; } @Override public int hashCode() { int hash = getClass().hashCode(); hash = hash * 31 + JodaBeanUtils.hashCode(marketDataName); hash = hash * 31 + JodaBeanUtils.hashCode(parameterMetadata); hash = hash * 31 + JodaBeanUtils.hashCode(order); hash = hash * 31 + JodaBeanUtils.hashCode(currency); hash = hash * 31 + JodaBeanUtils.hashCode(sensitivity); return hash; } @Override public String toString() { StringBuilder buf = new StringBuilder(192); buf.append("CrossGammaParameterSensitivity{"); buf.append("marketDataName").append('=').append(JodaBeanUtils.toString(marketDataName)).append(',').append(' '); buf.append("parameterMetadata").append('=').append(JodaBeanUtils.toString(parameterMetadata)).append(',').append(' '); buf.append("order").append('=').append(JodaBeanUtils.toString(order)).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("sensitivity").append('=').append(JodaBeanUtils.toString(sensitivity)); buf.append('}'); return buf.toString(); } //----------------------------------------------------------------------- /** * The meta-bean for {@code CrossGammaParameterSensitivity}. */ 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 marketDataName} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> marketDataName = DirectMetaProperty.ofImmutable( this, "marketDataName", CrossGammaParameterSensitivity.class, (Class) MarketDataName.class); /** * The meta-property for the {@code parameterMetadata} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty> parameterMetadata = DirectMetaProperty.ofImmutable( this, "parameterMetadata", CrossGammaParameterSensitivity.class, (Class) ImmutableList.class); /** * The meta-property for the {@code order} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty, List>>> order = DirectMetaProperty.ofImmutable( this, "order", CrossGammaParameterSensitivity.class, (Class) ImmutableList.class); /** * The meta-property for the {@code currency} property. */ private final MetaProperty currency = DirectMetaProperty.ofImmutable( this, "currency", CrossGammaParameterSensitivity.class, Currency.class); /** * The meta-property for the {@code sensitivity} property. */ private final MetaProperty sensitivity = DirectMetaProperty.ofImmutable( this, "sensitivity", CrossGammaParameterSensitivity.class, DoubleMatrix.class); /** * The meta-properties. */ private final Map> metaPropertyMap$ = new DirectMetaPropertyMap( this, null, "marketDataName", "parameterMetadata", "order", "currency", "sensitivity"); /** * Restricted constructor. */ private Meta() { } @Override protected MetaProperty metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 842855857: // marketDataName return marketDataName; case -1169106440: // parameterMetadata return parameterMetadata; case 106006350: // order return order; case 575402001: // currency return currency; case 564403871: // sensitivity return sensitivity; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder builder() { return new CrossGammaParameterSensitivity.Builder(); } @Override public Class beanType() { return CrossGammaParameterSensitivity.class; } @Override public Map> metaPropertyMap() { return metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code marketDataName} property. * @return the meta-property, not null */ public MetaProperty> marketDataName() { return marketDataName; } /** * The meta-property for the {@code parameterMetadata} property. * @return the meta-property, not null */ public MetaProperty> parameterMetadata() { return parameterMetadata; } /** * The meta-property for the {@code order} property. * @return the meta-property, not null */ public MetaProperty, List>>> order() { return order; } /** * The meta-property for the {@code currency} property. * @return the meta-property, not null */ public MetaProperty currency() { return currency; } /** * The meta-property for the {@code sensitivity} property. * @return the meta-property, not null */ public MetaProperty sensitivity() { return sensitivity; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 842855857: // marketDataName return ((CrossGammaParameterSensitivity) bean).getMarketDataName(); case -1169106440: // parameterMetadata return ((CrossGammaParameterSensitivity) bean).getParameterMetadata(); case 106006350: // order return ((CrossGammaParameterSensitivity) bean).getOrder(); case 575402001: // currency return ((CrossGammaParameterSensitivity) bean).getCurrency(); case 564403871: // sensitivity return ((CrossGammaParameterSensitivity) bean).getSensitivity(); } 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 CrossGammaParameterSensitivity}. */ private static final class Builder extends DirectPrivateBeanBuilder { private MarketDataName marketDataName; private List parameterMetadata = ImmutableList.of(); private List, List>> order = ImmutableList.of(); private Currency currency; private DoubleMatrix sensitivity; /** * Restricted constructor. */ private Builder() { } //----------------------------------------------------------------------- @Override public Object get(String propertyName) { switch (propertyName.hashCode()) { case 842855857: // marketDataName return marketDataName; case -1169106440: // parameterMetadata return parameterMetadata; case 106006350: // order return order; case 575402001: // currency return currency; case 564403871: // sensitivity return sensitivity; default: throw new NoSuchElementException("Unknown property: " + propertyName); } } @SuppressWarnings("unchecked") @Override public Builder set(String propertyName, Object newValue) { switch (propertyName.hashCode()) { case 842855857: // marketDataName this.marketDataName = (MarketDataName) newValue; break; case -1169106440: // parameterMetadata this.parameterMetadata = (List) newValue; break; case 106006350: // order this.order = (List, List>>) newValue; break; case 575402001: // currency this.currency = (Currency) newValue; break; case 564403871: // sensitivity this.sensitivity = (DoubleMatrix) newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return this; } @Override public CrossGammaParameterSensitivity build() { return new CrossGammaParameterSensitivity( marketDataName, parameterMetadata, order, currency, sensitivity); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(192); buf.append("CrossGammaParameterSensitivity.Builder{"); buf.append("marketDataName").append('=').append(JodaBeanUtils.toString(marketDataName)).append(',').append(' '); buf.append("parameterMetadata").append('=').append(JodaBeanUtils.toString(parameterMetadata)).append(',').append(' '); buf.append("order").append('=').append(JodaBeanUtils.toString(order)).append(',').append(' '); buf.append("currency").append('=').append(JodaBeanUtils.toString(currency)).append(',').append(' '); buf.append("sensitivity").append('=').append(JodaBeanUtils.toString(sensitivity)); buf.append('}'); return buf.toString(); } } //-------------------------- AUTOGENERATED END -------------------------- }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy