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 the MR Accelerator are now configured as replaceable qualified Spring Beans, with the ActivePivot post-processing chain being composed through the use of qualified parameters in the bean creation methods.
Bean annotations
All measure beans in the MR Accelerator 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
Annotation | Condition | Cube |
---|---|---|
SensitivitiesCopperContextBean | BeanEnabledSensitivitiesCube | Sensitivity Cube |
SensitivitiesSummaryCopperContextBean | BeanEnabledSensitivitiesSummaryCube | Sensitivity Summary Cube |
VarCopperContextBean | BeanEnabledVaRCube | VaR-ES Cube |
VarSummaryCopperContextBean | BeanEnabledVaRSummaryCube | VaR-ES Summary Cube |
PnLCopperContextBean | BeanEnabledPnLCube | PLCube |
PnLSummaryCopperContextBean | BeanEnabledPnLSummaryCube | PL Summary Cube |
MarketDataCopperContextBean | BeanEnabledMarketDataCube | Market Data Cube |
The Resolver objects
Each cube in the MR Accelerator uses an implementation of the IMeasureResolver
interface that defines the annotation to use for the measures intended for that cube.
@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
Qualifier | Condition | Annotation |
---|---|---|
SP_QUALIFIER__SENSITIVITY_MEASURES_RESOLVER | BeanEnabledSensitivitiesCube | SensitivitiesCopperContextBean |
SP_QUALIFIER__SENSITIVITY_SUMMARY_MEASURES_RESOLVER | BeanEnabledSensitivitiesSummaryCube | SensitivitiesSummaryCopperContextBean |
SP_QUALIFIER__VAR_MEASURES_RESOLVER | BeanEnabledVaRCube | VarCopperContextBean |
SP_QUALIFIER__VAR_SUMMARY_MEASURES_RESOLVER | BeanEnabledVaRSummaryCube | VarSummaryCopperContextBean |
SP_QUALIFIER__PNL_MEASURES_RESOLVER | BeanEnabledPnLCube | PnLCopperContextBean |
SP_QUALIFIER__PNL_SUMMARY_MEASURES_RESOLVER | BeanEnabledPnLSummaryCube | PnLSummaryCopperContextBean |
SP_QUALIFIER__MARKET_DATA_MEASURES_RESOLVER | BeanEnabledMarketDataCube | MarketDataCopperContextBean |
The Consumer<ICopperContext>
beans
For each cube, a Consumer<ICopperContext>
bean is created, which is responsible for calling the measure creation objects in the correct order.
The possible measure creation objects are:
Object | Method | Description |
---|---|---|
Consumer<ICopperContext> copperCube |
Consumer::accept |
Optional Consumer responsible for setting up Copper-defined hierarchies. |
IMeasureResolver measureResolver |
IMeasureResolver::measures |
IMeasureResolver object responsible for beans defined using the mechanism described on this page. |
List<Consumer<ICopperContext>> additionalMeasures |
Consumer::accept |
Optional List of Consumers for additional measures. |
The optional objects are not available on the Summary cubes.
To replace the default copperCube
and additionalMeasures
Consumers
, the following qualifiers are available:
Qualifier | Cube |
---|---|
SP_QUALIFIER__SENSITIVITY_COPPER_CUBE | Sensitivity Cube |
SP_QUALIFIER__ADDITIONAL_SENSITIVITY_MEASURES | Sensitivity Cube |
SP_QUALIFIER__VAR_COPPER_CUBE | VaR-ES Cube |
SP_QUALIFIER__ADDITIONAL_VAR_MEASURES | VaR-ES Cube |
SP_QUALIFIER__PNL_COPPER_CUBE | PLCube |
SP_QUALIFIER__ADDITIONAL_PNL_MEASURES | PLCube |
SP_QUALIFIER__MARKET_DATA_COPPER_CUBE | Market Data Cube |
SP_QUALIFIER__ADDITIONAL_MARKET_DATA_MEASURES | Market Data Cube |
The Consumer<ICopperContext>
beans used by the cube configuration classes use the following qualifiers:
Qualifier | Cube | Condition |
---|---|---|
SP_QUALIFIER__SENSITIVITY_MEASURES | Sensitivity Cube | BeanEnabledSensitivitiesCube |
SP_QUALIFIER__SENSITIVITY_SUMMARY_MEASURES | Sensitivity Summary Cube | BeanEnabledSensitivitiesSummaryCube |
SP_QUALIFIER__VAR_MEASURES | VaR-ES Cube | BeanEnabledVaRCube |
SP_QUALIFIER__VAR_SUMMARY_MEASURES | VaR-ES Summary Cube | BeanEnabledVaRSummaryCube |
SP_QUALIFIER__PNL_MEASURES | PLCube | BeanEnabledPnLCube |
SP_QUALIFIER__PNL_SUMMARY_MEASURES | PL Summary Cube | BeanEnabledPnLSummaryCube |
SP_QUALIFIER__MARKET_DATA_MEASURES | Market Data Cube | BeanEnabledMarketDataCube |
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:
Object | Cube | Description |
---|---|---|
MarketDataMeasureParameters | Market Data Cube | Measure parameters for the Market Data cube, containing cube levels, members and formatters. |
MarketDataMeasureNames | Market Data Cube | Constants and naming methods for the Market Data cube. |
PnLMeasureParameters | PLCube, PL Summary Cube | Measure parameters for the PL and PL Summary cubes, containing cube levels and formatters. |
PnLMeasureNames | PLCube, PL Summary Cube | Constants and naming methods for the PL and PL Summary cubes. |
SensiMeasureParameters | Sensitivity Cube, Sensitivity Summary Cube | 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. |
SensiMeasureNames | Sensitivity Cube, Sensitivity Summary Cube | Constants and naming methods for the Sensitivity and Sensitivity Summary cubes. |
DividendMeasureNames | Sensitivity Cube, Sensitivity Summary Cube | Constants and naming methods specific to the Dividend measures in the Sensitivity and Sensitivity Summary cubes. |
VaRMeasureParameters | VaR-ES Cube, VaR-ES Summary Cube | 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. |
VaRMetricParametersAndNames | VaR-ES Cube, VaR-ES Summary Cube | 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). |
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:
Qualifier | Type | Description |
---|---|---|
SP_QUALIFIER__MARKET_DATA_MEASURE_PARAMETERS | MarketDataMeasureParameters | Measure parameters for the Market Data cube. |
SP_QUALIFIER__PNL_MEASURE_PARAMETERS | PnLMeasureParameters | Measure parameters for the PL and PL Summary cubes. |
SP_QUALIFIER__VAR_CUBE_MEASURE_PARAMETERS | VaRMeasureParameters | Measure parameters for the VaR-ES and VaR-ES Summary cubes. |
SP_QUALIFIER__ES_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the ES metric. |
SP_QUALIFIER__ETG_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the ETG metric. |
SP_QUALIFIER__HD_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the Harrel-Davis VaR metric. |
SP_QUALIFIER__VAE_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the VaE metric. |
SP_QUALIFIER__VAR_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the VaR metric. |
SP_QUALIFIER__WES_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the Weighted ES metric. |
SP_QUALIFIER__WETG_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the Weighted ETG metric. |
SP_QUALIFIER__WVAE_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the Weighted VaE metric. |
SP_QUALIFIER__WVAR_PARAMETERS | VaRMetricParametersAndNames | The constants, naming methods, and postprocessor for the Weighted VaR metric. |
SP_QUALIFIER__BASE_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the common and aggregated Sensitivity measure chains. |
SP_QUALIFIER__DELTA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Delta measure chains. |
SP_QUALIFIER__GAMMA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Gamma measure chains. |
SP_QUALIFIER__VEGA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Vega measure chains. |
SP_QUALIFIER__VANNA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Vanna measure chains. |
SP_QUALIFIER__VOLGA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Volga measure chains. |
SP_QUALIFIER__THETA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Theta measure chains. |
SP_QUALIFIER__CROSS_GAMMA_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Cross Gamma measure chains. |
SP_QUALIFIER__CASH_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Cash measure chains. |
SP_QUALIFIER__CORRELATION_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Correlation measure chains. |
SP_QUALIFIER__DIVIDEND_MEASURE_PARAMETERS | SensiMeasureParameters | Required measure parameters for the Dividend measure chains. |
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 forFunction#apply(measures)
that allows the usage ofvarargs
MeasureCreator#noUnderlying()
- an alias forFunction#apply(null)
The following factory classes are available:
Cube | Factory | Abstract class | Interface | Description |
---|---|---|---|---|
Market Data Cube | MarketDataFactory | AMarketDataFactory | IMarketDataMeasures | All MeasureCreator objects used in creating measures for the Market Data cube. |
PLCube, PL Summary Cube | PnLFactory | APnLFactory | IPnLMeasures | All MeasureCreator objects used in creating measures for the PL and PL Summary cubes. |
Sensitivity Cube, Sensitivity Summary Cube | SensiFactory | ASensiFactory | IBaseMeasures | MeasureCreator objects for creating measures not split by sensitivity type. |
IDayToDayMeasures | MeasureCreator objects for creating day-to-day difference measures. | |||
ILadderExpansionMeasures | MeasureCreator objects for creating ladder measures. | |||
INativeCurrency | MeasureCreator objects for creating sensitivity measures in the native currency. | |||
IPnLExplainTaylorVaRMeasures | MeasureCreator objects for creating PnL Explain and Taylor VaR measures, by sensitivity and aggregated. | |||
ISensitivityMarketDataMeasures | MeasureCreator objects for creating market data measures for the Sensitivity and Sensitivity Summary cubes. | |||
ISensitivityMeasures | MeasureCreator objects for creating the top-level, post-FX sensitivity measures. | |||
ISplitMeasures | MeasureCreator objects for creating corporate split measures. | |||
VaR-ES Cube, VaR-ES Summary Cube | VaRFactory | AVaRFactory | IContextualMeasures | MeasureCreator objects for creating measures with the confidence level controlled through a context value. |
IContextualRiskClassMeasures | MeasureCreator objects for creating measures with the confidence level controlled through a context value, split by configurable risk class. | |||
IFixedConfidenceMeasures | MeasureCreator objects for creating measures per configurable confidence levels. | |||
IIncrementalMeasures | MeasureCreator objects for creating Incremental, LEstimator, Component VaR and Component VaR Delta measures. | |||
IRiskClassFixedConfidenceMeasures | MeasureCreator objects for creating measures per configurable confidence levels, split by configurable risk class. | |||
IVaRESMeasures | MeasureCreator objects for creating measures not split by metric type. |
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)
- 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
andCopperMeasure[]
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:
@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:
@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:
@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:
Package | Factory |
---|---|
com.activeviam.mr.marketdata.measures.chains |
A single MarketDataFactory . |
com.activeviam.mr.pnl.measures.chains.complete |
The common PnLFactory . |
com.activeviam.mr.pnl.measures.chains.summary |
The common PnLFactory . |
com.activeviam.mr.productcontrol.measures.chains |
The common PnLFactory . |
com.activeviam.mr.sensi.measures.chains.complete |
A SensiFactory instance per sensitivity type, providing the correct Parameters and Names. |
com.activeviam.mr.sensi.measures.chains.summary |
A SensiFactory instance per sensitivity type, providing the correct Parameters and Names. |
com.activeviam.mr.var.measures.chains.complete |
A VaRFactory instance per metric type, providing the correct Parameters and Names. |
com.activeviam.mr.var.measures.chains.summary |
A VaRFactory instance per metric type, providing the correct Parameters and Names. |
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 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
@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:
@SensitivitiesCopperContextBean
@Qualifier(SENSI + NATIVE_INTERMEDIATE)
@Primary
public CopperMeasure deltaSensiNativeIntermediate() {
return null;
}
- Replacing the bean and returning the underlier:
@SensitivitiesCopperContextBean
@Qualifier(SENSI + NATIVE_VECTOR_EXPAND)
@Conditional(BeanScalar.class)
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.