I’m trying to extend FxSingleTrade to add my own custom measure by following this guide: Adding a New Measure
So far I’ve created an ExtendedMeasures class, implemented FxSingleTradeForwardPointsFunction and registered with:
CalculationFunctions functions = StandardComponents.calculationFunctions().composedWith(CalculationFunctions
.of(new FxFlexibleForwardTradeCalculationFunction(), new FxSingleTradeForwardPointsFunction()));
The error I’m getting is: Unable to get a value from a failure result: Measure ‘FxSwapRate’ is not supported by function ‘FxSingleTradeCalculationFunction’
My code is in Github here: Strata Extensions and there is a JUnit test FxForwardTest that demonstrates this issue.
You need to extend AbstractDerivedCalculationFunction instead of implementing CalculationFunction. You set up similar things, but typically depend on Measures.RESOLVED_TARGET. I’ve updated the docs with more info: http://strata.opengamma.io/add_measure/
It worked but then broke other stuff such as NDF and FxSwap. In your example the constructor is private, so for mine I made the constructor public and registered it this way:
This worked for my test case but now other FX types are broken with a NPE thrown in DerivedCalculationFunctions.wrap.
I added a test for FxNdf to demonstrate the NPE an pushed it to github: Strata Extensions
To fix, it’s sufficient to use getOrDefault as opposed to get (or check for null):
@SuppressWarnings("unchecked")
private <T extends CalculationTarget, R> CalculationFunction<? super T> wrap(CalculationFunction<? super T> fn, T target) {
List<DerivedCalculationFunction<?, ?>> derivedFunctions =
functionsByTargetType.getOrDefault(target.getClass(), ImmutableList.of());
CalculationFunction<? super T> wrappedFn = fn;
for (DerivedCalculationFunction<?, ?> derivedFn : derivedFunctions) {
// These casts are necessary because the type information is lost when the functions are stored in the map.
// They are safe because T is the target type which is is the map key and R isn't actually used
CalculationFunction<T> wrappedFnCast = (CalculationFunction<T>) wrappedFn;
DerivedCalculationFunction<T, R> derivedFnCast = (DerivedCalculationFunction<T, R>) derivedFn;
wrappedFn = new DerivedCalculationFunctionWrapper<>(derivedFnCast, wrappedFnCast);
}
return wrappedFn;
}
We don’t have a formal snapshot repo I’m afraid, nor do we guarantee particular timelines for releases. So I think building it locally is best for now.
OK, thanks. At the moment I’m grafting Quantlib underneath Strata to allow me to price things that are missing such as: Callable/Cancellable swaps, Bermudan Swaptions etc. As a consequence I will be creating a lot of CalculationFunctions. It would be convenient if they could be automatically registered either through a Spring like reflection mechanism, or by specifying them in an .ini file that can be read in (as opposed to doing this in code). Is there already a way to extend CalculationFunctions dynamically?