> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuring measures using Spring Beans

This page describes the mechanism introduced in MR 3.1.0 that allows you to customize the measure configuration through Spring Beans.

It also provides an example of adding customization using the new mechanism.

## Concept

Measures in Atoti Market Risk are now configured as replaceable qualified Spring Beans, with the Atoti Server post-processing chain being composed through the use of qualified parameters in the bean creation methods.

### Bean annotations

All measure beans in Atoti Market Risk have custom annotations, per cube. These annotations attach a Copper context to the bean and make instantiation conditional on the cube being enabled.

#### Available annotations

<table><thead><tr><th>Annotation</th><th>Condition</th><th>Cube</th></tr></thead><tbody><tr><td>SensitivitiesCopperContextBean</td><td>BeanEnabledSensitivitiesCube</td><td>Sensitivity Cube</td></tr><tr><td>SensitivitiesSummaryCopperContextBean</td><td>BeanEnabledSensitivitiesSummaryCube</td><td>Sensitivity Summary Cube</td></tr><tr><td>VarCopperContextBean</td><td>BeanEnabledVaRCube</td><td>VaR-ES Cube</td></tr><tr><td>VarSummaryCopperContextBean</td><td>BeanEnabledVaRSummaryCube</td><td>VaR-ES Summary Cube</td></tr><tr><td>PnLCopperContextBean</td><td>BeanEnabledPnLCube</td><td>PLCube</td></tr><tr><td>PnLSummaryCopperContextBean</td><td>BeanEnabledPnLSummaryCube</td><td>PL Summary Cube</td></tr><tr><td>MarketDataCopperContextBean</td><td>BeanEnabledMarketDataCube</td><td>Market Data Cube</td></tr></tbody></table>

### The Resolver objects

Each cube in Atoti Market Risk uses an implementation of the `IMeasureResolver` interface that defines the annotation to use for the measures intended for that cube.

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @Bean
    @Qualifier(SP_QUALIFIER__VAR_MEASURES_RESOLVER)
    @Conditional(BeanEnabledVaRCube.class)
    public IMeasureResolver varResolver(ICopperContextScopeManager scopeManager, ConfigurableListableBeanFactory beanFactory) {
        return new MeasureResolver(scopeManager, beanFactory, VarCopperContextBean.class);
    }
```

The `IMeasureResolver` interface performs the following actions:

* Collects all annotated beans.
* Groups them by `@Qualifier`.
* Selects the `@Primary` bean for each individual `@Qualifier`.
* Publishes the beans on the Copper context, ordered by dependency relationship.

#### Available Resolvers

<table><thead><tr><th>Qualifier</th><th>Condition</th><th>Annotation</th></tr></thead><tbody><tr><td>SP\_QUALIFIER\_\_SENSITIVITY\_MEASURES\_RESOLVER</td><td>BeanEnabledSensitivitiesCube</td><td>SensitivitiesCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_SENSITIVITY\_SUMMARY\_MEASURES\_RESOLVER</td><td>BeanEnabledSensitivitiesSummaryCube</td><td>SensitivitiesSummaryCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_MEASURES\_RESOLVER</td><td>BeanEnabledVaRCube</td><td>VarCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_SUMMARY\_MEASURES\_RESOLVER</td><td>BeanEnabledVaRSummaryCube</td><td>VarSummaryCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_MEASURES\_RESOLVER</td><td>BeanEnabledPnLCube</td><td>PnLCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_SUMMARY\_MEASURES\_RESOLVER</td><td>BeanEnabledPnLSummaryCube</td><td>PnLSummaryCopperContextBean</td></tr><tr><td>SP\_QUALIFIER\_\_MARKET\_DATA\_MEASURES\_RESOLVER</td><td>BeanEnabledMarketDataCube</td><td>MarketDataCopperContextBean</td></tr></tbody></table>

### The `MeasurePublisher` beans

For each cube, a `MeasurePublisher` bean is created, which is responsible for calling the measure creation objects in the correct order.

The possible measure creation objects are:

<table><thead><tr><th>Object</th><th>Method</th><th>Description</th></tr></thead><tbody><tr><td><code>CopperCubePublisher copperCube</code></td><td><code>CopperCubePublisher::accept</code></td><td>Optional publisher responsible for setting up Copper-defined hierarchies.</td></tr><tr><td><code>IMeasureResolver measureResolver</code></td><td><code>IMeasureResolver::measures</code></td><td><code>IMeasureResolver</code> object responsible for beans defined using the mechanism described on this page.</td></tr><tr><td><code>List\<MeasurePublisher> additionalMeasures</code></td><td><code>MeasurePublisher::accept</code></td><td>Optional <code>List</code> of publishers for additional measures.</td></tr></tbody></table>

The optional objects are not available on the Summary cubes.

To replace the default `copperCube` and `additionalMeasures` publishers, the following qualifiers are available:

<table><thead><tr><th>Qualifier</th><th>Cube</th></tr></thead><tbody><tr><td>SP\_QUALIFIER\_\_SENSITIVITY\_COPPER\_CUBE</td><td>Sensitivity Cube</td></tr><tr><td>SP\_QUALIFIER\_\_ADDITIONAL\_SENSITIVITY\_MEASURES</td><td>Sensitivity Cube</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_COPPER\_CUBE</td><td>VaR-ES Cube</td></tr><tr><td>SP\_QUALIFIER\_\_ADDITIONAL\_VAR\_MEASURES</td><td>VaR-ES Cube</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_COPPER\_CUBE</td><td>PLCube</td></tr><tr><td>SP\_QUALIFIER\_\_ADDITIONAL\_PNL\_MEASURES</td><td>PLCube</td></tr><tr><td>SP\_QUALIFIER\_\_MARKET\_DATA\_COPPER\_CUBE</td><td>Market Data Cube</td></tr><tr><td>SP\_QUALIFIER\_\_ADDITIONAL\_MARKET\_DATA\_MEASURES</td><td>Market Data Cube</td></tr></tbody></table>

The `MeasurePublisher` beans used by the cube configuration classes use the following qualifiers:

<table><thead><tr><th>Qualifier</th><th>Cube</th><th>Condition</th></tr></thead><tbody><tr><td>SP\_QUALIFIER\_\_SENSITIVITY\_MEASURES</td><td>Sensitivity Cube</td><td>BeanEnabledSensitivitiesCube</td></tr><tr><td>SP\_QUALIFIER\_\_SENSITIVITY\_SUMMARY\_MEASURES</td><td>Sensitivity Summary Cube</td><td>BeanEnabledSensitivitiesSummaryCube</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_MEASURES</td><td>VaR-ES Cube</td><td>BeanEnabledVaRCube</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_SUMMARY\_MEASURES</td><td>VaR-ES Summary Cube</td><td>BeanEnabledVaRSummaryCube</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_MEASURES</td><td>PLCube</td><td>BeanEnabledPnLCube</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_SUMMARY\_MEASURES</td><td>PL Summary Cube</td><td>BeanEnabledPnLSummaryCube</td></tr><tr><td>SP\_QUALIFIER\_\_MARKET\_DATA\_MEASURES</td><td>Market Data Cube</td><td>BeanEnabledMarketDataCube</td></tr><tr><td>SP\_QUALIFIER\_\_COMMON\_MEASURES</td><td>Combined Cube</td><td>BeanEnabledCommonCube</td></tr></tbody></table>

### Parameter objects

The cube-specific measure chains rely on parameter objects that contain:

* Configuration properties (usually cube levels, members, formatters)
* Parameters required for creating measures (e.g. formula providers, the market data retrieval service, the number of axes for a sensitivity)
* Constants for use in `@Qualifier` annotations
* Methods for naming measures

The following object types are available:

<table><thead><tr><th>Object</th><th>Cube</th><th>Description</th></tr></thead><tbody><tr><td>MarketDataMeasureParameters</td><td>Market Data Cube</td><td>Measure parameters for the Market Data cube, containing cube levels, members and formatters.</td></tr><tr><td>MarketDataMeasureNames</td><td>Market Data Cube</td><td>Constants and naming methods for the Market Data cube.</td></tr><tr><td>PnLMeasureParameters</td><td>PLCube, PL Summary Cube</td><td>Measure parameters for the PL and PL Summary cubes, containing cube levels and formatters.</td></tr><tr><td>PnLMeasureNames</td><td>PLCube, PL Summary Cube</td><td>Constants and naming methods for the PL and PL Summary cubes.</td></tr><tr><td>SensiMeasureParameters</td><td>Sensitivity Cube, Sensitivity Summary Cube</td><td>Measure parameters for the Sensitivity and Sensitivity Summary cubes, containing cube levels, members, formatters, formula providers, the number of axes for a sensitivity, the maturity converter and the market data retrieval service together with custom parameters for the service.</td></tr><tr><td>SensiMeasureNames</td><td>Sensitivity Cube, Sensitivity Summary Cube</td><td>Constants and naming methods for the Sensitivity and Sensitivity Summary cubes.</td></tr><tr><td>DividendMeasureNames</td><td>Sensitivity Cube, Sensitivity Summary Cube</td><td>Constants and naming methods specific to the Dividend measures in the Sensitivity and Sensitivity Summary cubes.</td></tr><tr><td>VaRMeasureParameters</td><td>VaR-ES Cube, VaR-ES Summary Cube</td><td>Measure parameters for the VaR-ES and VaR-ES Summary cubes, containing cube levels, members and formatters, as well as configurable confidence levels and risk classes.</td></tr><tr><td>VaRMetricParametersAndNames</td><td>VaR-ES Cube, VaR-ES Summary Cube</td><td>Constants and naming methods for the VaR-ES and VaR-ES Summary cubes, together with the postprocessor object specific to each VaR metric (VaR, Harrel-Davis VaR, VaE, ES, ETG, Weighted VaR, Weighted VaE, Weighted ES, and Weighted ETG).</td></tr></tbody></table>

The `[...]MeasureParameters` and VaR-ES Cube metric-specific `[...]Names` objects are exposed as beans. For the other cubes, the `[...]Names` objects are created using the parameter beans.

To replace the beans, the following qualifiers are available:

<table><thead><tr><th>Qualifier</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>SP\_QUALIFIER\_\_MARKET\_DATA\_MEASURE\_PARAMETERS</td><td>MarketDataMeasureParameters</td><td>Measure parameters for the Market Data cube.</td></tr><tr><td>SP\_QUALIFIER\_\_PNL\_MEASURE\_PARAMETERS</td><td>PnLMeasureParameters</td><td>Measure parameters for the PL and PL Summary cubes.</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_CUBE\_MEASURE\_PARAMETERS</td><td>VaRMeasureParameters</td><td>Measure parameters for the VaR-ES and VaR-ES Summary cubes.</td></tr><tr><td>SP\_QUALIFIER\_\_ES\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the ES metric.</td></tr><tr><td>SP\_QUALIFIER\_\_ETG\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the ETG metric.</td></tr><tr><td>SP\_QUALIFIER\_\_HD\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the Harrel-Davis VaR metric.</td></tr><tr><td>SP\_QUALIFIER\_\_VAE\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the VaE metric.</td></tr><tr><td>SP\_QUALIFIER\_\_VAR\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the VaR metric.</td></tr><tr><td>SP\_QUALIFIER\_\_WES\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the Weighted ES metric.</td></tr><tr><td>SP\_QUALIFIER\_\_WETG\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the Weighted ETG metric.</td></tr><tr><td>SP\_QUALIFIER\_\_WVAE\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the Weighted VaE metric.</td></tr><tr><td>SP\_QUALIFIER\_\_WVAR\_PARAMETERS</td><td>VaRMetricParametersAndNames</td><td>The constants, naming methods, and postprocessor for the Weighted VaR metric.</td></tr><tr><td>SP\_QUALIFIER\_\_BASE\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the common and aggregated Sensitivity measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_DELTA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Delta measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_GAMMA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Gamma measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_VEGA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Vega measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_VANNA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Vanna measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_VOLGA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Volga measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_THETA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Theta measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_CROSS\_GAMMA\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Cross Gamma measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_CORRELATION\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Correlation measure chains.</td></tr><tr><td>SP\_QUALIFIER\_\_DIVIDEND\_MEASURE\_PARAMETERS</td><td>SensiMeasureParameters</td><td>Required measure parameters for the Dividend measure chains.</td></tr></tbody></table>

### Factories

The logic for creating Copper-based measures is contained within collections of interfaces split by logical measure sub-chain (e.g. `ILadderExpansionMeasures`, `IRiskClassFixedConfidenceMeasures`).

For each cube, an abstract factory class implements the specific interfaces and stores the Parameters and Names objects required. Concrete classes extend the abstract class and define common helper methods.

The methods contained within the factory interfaces are mostly of the type `MeasureCreator`, an interface alias for `Function<CopperMeasure[], CopperMeasure>`. The function takes an array of underlying measures and returns a single resulting measure.
The alias also defines two additional methods:

* `MeasureCreator#on(CopperMeasure... measures)` - an alias for `Function#apply(measures)` that allows the usage of `varargs`
* `MeasureCreator#noUnderlying()` - an alias for `Function#apply(null)`

The following factory classes are available:

<table><thead><tr><th>Cube</th><th>Factory</th><th>Abstract class</th><th>Interface</th><th>Description</th></tr></thead><tbody><tr><td>Market Data Cube</td><td>MarketDataFactory</td><td>AMarketDataFactory</td><td>IMarketDataMeasures</td><td>All MeasureCreator objects used in creating measures for the Market Data cube.</td></tr><tr><td>PLCube, PL Summary Cube</td><td>PnLFactory</td><td>APnLFactory</td><td>IPnLMeasures</td><td>All MeasureCreator objects used in creating measures for the PL and PL Summary cubes.</td></tr><tr><td>Sensitivity Cube, Sensitivity Summary Cube</td><td>SensiFactory</td><td>ASensiFactory</td><td>IBaseMeasures</td><td>MeasureCreator objects for creating measures not split by sensitivity type.</td></tr><tr><td /><td /><td /><td>IBucketedMeasures</td><td>MeasureCreator objects for measures that can be bucketed on time pillars.</td></tr><tr><td /><td /><td /><td>IDayToDayMeasures</td><td>MeasureCreator objects for creating day-to-day difference measures.</td></tr><tr><td /><td /><td /><td>ILadderExpansionMeasures</td><td>MeasureCreator objects for creating ladder measures.</td></tr><tr><td /><td /><td /><td>INamedDayToDayMeasures</td><td>MeasureCreator objects for day-to-day measures.</td></tr><tr><td /><td /><td /><td>INativeCurrencyMeasures</td><td>MeasureCreator objects for creating sensitivity measures in the native currency.</td></tr><tr><td /><td /><td /><td>ISensitivityMeasures</td><td>MeasureCreator objects for creating the top-level, post-FX sensitivity measures.</td></tr><tr><td /><td /><td /><td>ISplitMeasures</td><td>MeasureCreator objects for creating corporate split measures.</td></tr><tr><td>Sensitivity Cube</td><td>PnLExplainFactory</td><td>APnLExplainFactory</td><td>IAggregateMeasures</td><td>MeasureCreator objects for creating aggregated top level measures (e.g. with a plus operation).</td></tr><tr><td /><td /><td /><td>IBasePnLExplainMeasures</td><td>MeasureCreator objects for creating measures not split by sensitivity type.</td></tr><tr><td /><td /><td /><td>IBucketedMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IFilteredMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>INamedDayToDayMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IPnLExplainMeasures</td><td>MeasureCreator objects for creating PnL Explain measures, by sensitivity and aggregated.</td></tr><tr><td /><td /><td /><td>ISensitivityMarketDataMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>ISplitMeasures</td><td>See above.</td></tr><tr><td>Sensitivity Cube</td><td>TaylorFactory</td><td>ATaylorFactory</td><td>IAggregateMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IBucketedMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IContextualMeasures</td><td>MeasureCreator objects for creating measures with the confidence level controlled through a context value.</td></tr><tr><td /><td /><td /><td>IFilteredMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IFixedConfidenceMeasures</td><td>MeasureCreator objects for creating measures per configurable confidence levels.</td></tr><tr><td /><td /><td /><td>IIncrementalMeasures</td><td>MeasureCreator objects for creating Incremental, LEstimator, Component VaR and Component VaR Delta measures.</td></tr><tr><td /><td /><td /><td>INamedDayToDayMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IShiftMeasures</td><td>MeasureCreator objects for creating market shift measures.</td></tr><tr><td /><td /><td /><td>ISplitMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IStatisticalMeasures</td><td>MeasureCreator for measures that perform statistical operations on vectors (e.g. min, max, mean).</td></tr><tr><td /><td /><td /><td>ITaylorVaRMeasures</td><td>MeasureCreator objects for creating Taylor VaR measures, by sensitivity and aggregated.</td></tr><tr><td /><td /><td /><td>IVaRESMeasures</td><td>MeasureCreator objects for creating measures not split by metric type.</td></tr><tr><td>VaR-ES Cube, VaR-ES Summary Cube</td><td>VaRFactory</td><td>AVaRFactory</td><td>IContextualMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IContextualRiskClassMeasures</td><td>MeasureCreator objects for creating measures with the confidence level controlled through a context value, split by configurable risk class.</td></tr><tr><td /><td /><td /><td>IFixedConfidenceMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IIncrementalMeasures</td><td>See above.</td></tr><tr><td /><td /><td /><td>IRiskClassFixedConfidenceMeasures</td><td>MeasureCreator objects for creating measures per configurable confidence level, split by configurable risk class.</td></tr><tr><td /><td /><td /><td>IVaRESMeasures</td><td>See above.</td></tr></tbody></table>

### Chains

Chain classes are configuration classes that leverage measure factories to define a measure chain as a collection of beans.

A typical measure definition consists of:

* The cube-specific bean annotation (see [Bean annotations](#bean_annotations))
* A `@Qualifier` annotation specific to the measure.
* ***(OPTIONAL)*** A `@MeasureGroup` annotation marking the measure to be part of a group.
* ***(OPTIONAL)*** A `@Conditional` annotation to enable/disable creating the measure depending on the project configuration.
* The type of the bean (`CopperMeasure` and `CopperMeasure[]` are currently supported).
* Underlying measures as qualified parameters of the method.
* The logic for creating the measure, within the method body.

#### Examples

A measure defined as part of the `PNL_EXPLAIN_NEXT_DATE` group:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @SensitivitiesCopperContextBean
    @Qualifier(SENSI + PNL_EXPLAIN_NEXT_DATE)
    @MeasureGroup(PNL_EXPLAIN_NEXT_DATE)
    public CopperMeasure correlationPnlExplainNextDate(@Qualifier(SENSI + PNL_EXPLAIN_NATIVE_NEXT_DATE) CopperMeasure pnlExplainNativeNextDate) {
        return getFactory().pnlExplainNextDate().on(pnlExplainNativeNextDate);
    }
```

A measure operating on all measures part of the `PNL_EXPLAIN_NEXT_DATE` group:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @SensitivitiesCopperContextBean
    @Qualifier(AGGREGATE_PNL_EXPLAIN_NATIVE_NEXT_DATE)
    public CopperMeasure pnlExplainNativeNextDate(@MeasureGroup(PNL_EXPLAIN_NATIVE_NEXT_DATE) CopperMeasure[] sensitivitiesPnlExplainNativeNextDate) {
        return getFactory().aggregateMeasures(SensiMeasureNames::getAggregatePnlExplainNativeNextDate).on(sensitivitiesPnlExplainNativeNextDate);
    }
```

A measure bean generating multiple measures based on project configuration:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @VarCopperContextBean
    @Qualifier(METRIC + CONFIDENCE)
    public CopperMeasure[] esMetricConfidence(@Qualifier(VAR_FX_VECTOR) CopperMeasure varEsVarFxVector) {
        CopperMeasure[] returnArray = new CopperMeasure[getConfidenceLevels().size()];
        for (int i = 0; i < getConfidenceLevels().size(); i++) {
            returnArray[i] = getFactory().metricConfidence(getConfidenceLevels().get(i)).on(varEsVarFxVector);
        }
        return returnArray;
    }
```

The following packages contain `[...]Chain` classes implementing the relevant interfaces:

<table><thead><tr><th>Package</th><th>Factory</th></tr></thead><tbody><tr><td><code>com.activeviam.mr.marketdata.measures.chains</code></td><td>A single <code>MarketDataFactory</code>.</td></tr><tr><td><code>com.activeviam.mr.pnl.measures.chains.complete</code></td><td>The common <code>PnLFactory</code>.</td></tr><tr><td><code>com.activeviam.mr.pnl.measures.chains.summary</code></td><td>The common <code>PnLFactory</code>.</td></tr><tr><td><code>com.activeviam.mr.productcontrol.measures.chains</code></td><td>The common <code>PnLFactory</code>.</td></tr><tr><td><code>com.activeviam.mr.sensi.measures.chains.complete</code></td><td>A <code>SensiFactory</code> instance per sensitivity type, providing the correct Parameters and Names.</td></tr><tr><td /><td>A <code>PnLExplainFactory</code> instance per sensitivity type, providing the correct Parameters and Names.</td></tr><tr><td /><td>A <code>TaylorFactory</code> instance per sensitivity type, providing the correct Parameters and Names.</td></tr><tr><td><code>com.activeviam.mr.sensi.measures.chains.summary</code></td><td>A <code>SensiFactory</code> instance per sensitivity type, providing the correct Parameters and Names.</td></tr><tr><td><code>com.activeviam.mr.var.measures.chains.complete</code></td><td>A <code>VaRFactory</code> instance per metric type, providing the correct Parameters and Names.</td></tr><tr><td><code>com.activeviam.mr.var.measures.chains.summary</code></td><td>A <code>VaRFactory</code> instance per metric type, providing the correct Parameters and Names.</td></tr></tbody></table>

Each package contains one or more `[...]Chain` classes, split by logical measure sub-chain. As multiple measures can make use of the same factory `MeasureCreator` method, a single factory interface can result in multiple `[...]Chain` classes.

The Sensitivity and VaR-ES measures are further duplicated by sensitivity type and VaR metric, respectively. Each sensitivity type and VaR metric has a base abstract class that defines specific Parameters objects to be used in creating the relevant Factory.

Summary cubes also have a (sometimes smaller) set of `[...]Chain` classes, with potentially missing measures.

## Customization mechanism and examples

The internal configuration described in the [Concept](#concept) section enables the customization of measures through standalone bean definitions anywhere in the project configuration.

To customize a measure chain, you can replace individually qualified measures by defining a bean with the same annotations, marked as `@Primary`. Making the configuration class extend one of the `A[...]Chain` abstract classes gives access to the factory, names and parameters objects specific to that chain, through `getFactory()`, `getFactory().getNames()` and `getParameters()`.

While all internally defined measures make use of the factories, this is not a requirement.

### Replacing the PnLVectorExpand measure

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@Configuration
public class CustomMeasuresConfig extends AVaRESChain {

    private static final int[] MULTIPLIERS = new int[]{2, 3, 5};

    @VarCopperContextBean
    @Qualifier(PNL_VECTOR_EXPAND)
    @Primary
    public CopperMeasure expandRename(@Qualifier(PNL_VECTOR_EXPAND) CopperMeasure pnlVectorExpand) {
        return pnlVectorExpand.as("PnLVectorExpandOld");
    }

    @VarCopperContextBean
    @Qualifier("MultiplePnLVectorExpand")
    @Primary
    public CopperMeasure[] multiply(@Qualifier(PNL_VECTOR_EXPAND) CopperMeasure pnlVectorExpand) {
        CopperMeasure[] returnArray = new CopperMeasure[MULTIPLIERS.length];
        for (int i = 0; i < MULTIPLIERS.length; i++) {
            returnArray[i] = pnlVectorExpand.multiply(Copper.constant(MULTIPLIERS[i])).as("PnLVectorExpand x " + MULTIPLIERS[i]);
        }
        return returnArray;
    }

    @VarCopperContextBean
    @Qualifier("Aggregate PnL Vector Expand")
    @Primary
    public CopperMeasure aggregatePnLVectorExpand(@Qualifier("MultiplePnLVectorExpand") CopperMeasure[] multipliedPnLVectorExpand) {
        return Arrays.stream(multipliedPnLVectorExpand).reduce(CopperMeasure::plus).get().as(PNL_VECTOR_EXPAND);
    }

    @VarCopperContextBean
    @Qualifier(PNL_VECTOR_EXPAND_NEIGHBOUR_VALUE)
    @Primary
    public CopperMeasure customVarEsPnlVectorExpandNeighbourValue(@Qualifier("Aggregate PnL Vector Expand") CopperMeasure varEsPnlVectorExpand) {
        return getFactory().pnlVectorExpandNeighbour().on(varEsPnlVectorExpand);
    }
}
```

In this example we’re renaming the initial PnLVectorExpand measure to PnLVectorExpandOld, creating PnLVectorExpand x 2, PnLVectorExpand x 3 and
PnLVectorExpand x 5 measures and summing them up to replace the initial PnLVectorExpand measure.

Finally, to ensure our new bean is in the correct position in the chain, we replace the `PNL_VECTOR_EXPAND_NEIGHBOUR_VALUE` bean and use
`Aggregate PnL Vector Expand` instead of `PNL_VECTOR_EXPAND` as the underlier.

### Replacing a subchain

If the use-case requires replacing a longer part of a measure chain (e.g. skipping several intermediate steps), the intermediate beans also have
to be explicitly replaced. Two options are available:

* Replacing the bean and returning null:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @SensitivitiesCopperContextBean
    @Qualifier(SENSI + NATIVE_INTERMEDIATE)
    @Primary
    public CopperMeasure deltaSensiNativeIntermediate() {
        return null;
    }
```

* Replacing the bean and returning the underlier:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
    @SensitivitiesCopperContextBean
    @Qualifier(SENSI + NATIVE_VECTOR_EXPAND)
    public CopperMeasure deltaSkipVectorNativeExpand(@Qualifier(SENSI + NATIVE_SUM_TECHNICAL_FILTERED) CopperMeasure sumTechnicalFiltered) {
        return sumTechnicalFiltered;
    }
```

If the intermediate measures are likely to be used as underliers in other parts of the chain, return the underlier to avoid NullPointerException issues.

### Suggested Further Reading

* [Adding cube hierarchies](./add-a-new-cube-hierarchy)
* [Configuring schema selections using Spring Beans](./configure-schema-selections)
* [Configuring sources using Spring Beans](./configure-sources)
* [Adding a new KPI](./add-a-new-kpi)
* [Adding data loading or unloading topics](./add-a-new-data-loading-unloading-topic)

## Custom Measures Warning

Atoti Market Risk cubes and their summary variants (for example the `VaR-ES Cube` and the `VaR-ES Summary Cube`) are created as a horizontal distribution. This enables Atoti Market Risk to show a single measure (for example `VaR`) with some dates coming from the full cube and other date contributions from the summary cube. This is a useful feature, but it comes with a warning. Atoti Server expects that all cubes in a horizontal distribution have exactly identical measure chains. If they do not, this can lead to errors or incorrect results when queries are executed on a query cube with both cubes. The measure chains in Atoti Market Risk are not identical between main and summary cubes, but we have taken care to avoid these failure scenarios. We strongly recommend that, if you are using summary cubes, you add any new measures both to the main and summary cubes.

<Warning>
  Measure chain differences between main and summary cubes may lead to runtime errors or incorrect query results.
</Warning>
