Replacing the FX Rates Bean

The FX Rates service controls how currency conversion is performed across all cubes. By default, Atoti FRTB creates a ScenarioFxRates bean that reads rates from the FXRates datastore table and supports scenario-specific FX vectors for IMA Expected Shortfall and Stress Calibration.

Default configuration

The bean is defined in FxRatesServiceConfig:

@Bean
@Qualifier("fxRates")
public IScenarioFxRates fxRates(
        @Qualifier(ES_SCENARIO_TYPE) ScenarioFxRates.IDirectScenarioFxRates esScenarioFxRates,
        @Qualifier(STRESS_CALIBRATION_SCENARIO_TYPE) ScenarioFxRates.IDirectScenarioFxRates stressCalibrationScenarioFxRates
) {
    return new ScenarioFxRates(commonCcy, Map.of(
            ES_SCENARIO_TYPE, esScenarioFxRates,
            STRESS_CALIBRATION_SCENARIO_TYPE, stressCalibrationScenarioFxRates
    ));
}

This bean is then injected into every FX post-processor and FX analysis hierarchy by FRTBPostProcessorConfig.apManagerInitPrerequisitePluginInjections():

injectAll(IFXRatesAware.class, fxRates);
injectAll(IScenarioFxRates.Aware.class, fxRates);

No changes to FRTBPostProcessorConfig are needed when replacing the bean — the injection calls automatically pick up whichever IScenarioFxRates bean Spring resolves.

Replacing the FX Rates bean

To provide a custom FX rates implementation (for example, parameter-set-specific rates), create a new @Configuration class that extends FxRatesServiceConfig and override the fxRates() bean method:

@Configuration
public class CustomFxRatesConfig extends FxRatesServiceConfig {

    @Override
    @Bean
    @Qualifier("fxRates")
    public IScenarioFxRates fxRates(
            @Qualifier(ES_SCENARIO_TYPE) ScenarioFxRates.IDirectScenarioFxRates esScenarioFxRates,
            @Qualifier(STRESS_CALIBRATION_SCENARIO_TYPE) ScenarioFxRates.IDirectScenarioFxRates stressCalibrationScenarioFxRates
    ) {
        return new MyCustomScenarioFxRates(commonCcy, Map.of(
                ES_SCENARIO_TYPE, esScenarioFxRates,
                STRESS_CALIBRATION_SCENARIO_TYPE, stressCalibrationScenarioFxRates
        ));
    }
}

The custom implementation must implement IScenarioFxRates (or extend ScenarioFxRates). The two key methods to implement or override are:

Method Purpose
getFxRate(...) Returns the FX rate for a given currency pair. The leafCoordinates parameter carries any extra coordinates registered by updateLeafCoordinatesFunction (e.g. the parameter set).
updateLeafCoordinatesFunction(...) Registers extra leaf levels that the FX post-processor should resolve at query time. Return a LocationFunction whose getRequiredLevels() declares the extra levels and whose apply() extracts the coordinate from the query location.

Example: parameter-set-specific FX rates

To return different FX rates depending on the Parameter Set dimension, the custom implementation should:

  1. Override updateLeafCoordinatesFunction to register the Parameter Set level as an extra leaf level using a LocationFunction:
@Override
public LocationFunction updateLeafCoordinatesFunction(
        IActivePivot pivot, Properties properties,
        String ppPluginKey, LocationFunction userFunction) {

    ILevelInfo parameterSetLevel = HierarchiesUtil.getLevel(pivot,
            new LevelIdentifier(PARAMETERS_SET_DIM, PARAMETER_SET_HIERARCHY, PARAMETER_SET_LVL));

    return new LocationFunction() {
        @Override
        public @NonNull List<Object> apply(
                @NonNull ILocation location, @NonNull IQueryCache cache) {
            return List.of(
                    LocationUtil.isAtOrBelowLevel(location, parameterSetLevel)
                            ? LocationUtil.getCoordinate(location, parameterSetLevel)
                            : "BCBS");
        }

        @Override
        public @NonNull Collection<ILevelInfo> getRequiredLevels() {
            return List.of(parameterSetLevel);
        }
    };
}
  1. Override getFxRate to read the parameter set from leafCoordinates and return the appropriate rate:
@Override
public Double getFxRate(
        IDatabaseVersion datastore, LocalDate asOfDate,
        String baseCcy, String counterCcy, int maxFallbackDays,
        IDateShift dateInfo, IActivePivot activePivot,
        List<Object> leafCoordinates) {

    String parameterSet = leafCoordinates.isEmpty()
            ? "BCBS"
            : leafCoordinates.getFirst().toString();

    // Look up parameter-set-specific rate, falling back to default
    return lookupRate(parameterSet, baseCcy, counterCcy, asOfDate);
}
Class Module Description
FxRatesServiceConfig frtb-activepivot Default bean definition
FRTBPostProcessorConfig frtb-activepivot Injection into post-processors
ScenarioFxRates frtb-core Default implementation (extends FxRates)
IScenarioFxRates frtb-core Interface adding scenario FX vector support
IFxRates common-accelerator-library Base interface for FX rate retrieval
LocationFunction common-accelerator-library Interface for registering extra leaf levels