Fixings are thrown out, breaking valuation of several instruments
Hi,
A bug seems to have been introduced with ORE 13 which is causing fixings to be disregarded because they are not registered as required. This means it is no longer possible to value a portfolio of e.g. FX average forwards . I believe the behavior stems from this commit, specifically in MarketDataLoader::populateFixings: https://github.com/OpenSourceRisk/Engine/commit/d0e0c00e502856d23512bd70e63743d627dd37aa.
The cause After the changes, the default behavior is no longer to load all fixings provided. Instead, it:
-
asks the portfolio for its required fixings. (See lines 170-175 below). This always returns an empty map because the trades have not been built yet, consistent with the warning in the docstring of
Trade::fixings. -
asks some market data objects (specifically IndexForwardingCurves, Zero/YoYInflationCurves, and CommodityCurves) if they require fixings (see lines 178-180 below). If you have, say, USD-SOFR under your IndexForwardingCurves, then your SOFR fixings will be marked as necessary. On the other hand, if your market only has discounting and generic yield curves, no fixings are flagged for usage.
Then, only if steps 1 and/or 2 yielded any required fixings, the condition on line 191 will evaluate to true. If so, MarketDataCsvLoaderImpl::retrieveFixings will trigger and by default load any other fixings provided to ORE in the CSV.
Thus, if I run a portfolio of only FX average forwards (assuming no index, inflation, or commodity curves are used), it will not keep any of the FX fixings provided and then they cannot be priced. This can happen for any portfolio not using the curve types mentioned.
https://github.com/OpenSourceRisk/Engine/blob/df9d7683c008489376f2f8ccad3113e8f057b9b8/OREAnalytics/orea/app/marketdataloader.cpp#L162-L194
The solution Hoping for your input here! I imagine step 1 should be able to retrieve the trades' required fixings, then the condition would correctly evaluate to true and load them in. I can naively avoid the issue like this for the time being by forcing fixings to be retrieved (but that's likely not the way to go for a proper solution):
Any feedback on this would be much appreciated. I can provide a minimal input data set to replicate the issue, if you're interested.
I also want to offer a major thank you for the work that went into the 13th release; it is very valuable to us!
Kind regards, Fredrik
Hi @gbfredrik, sorry for the very late response. In case we load all fixings, which is the default when running ore app, we should always call impl()->retrieveFixings(), i.e.:
if ((inputs_->allFixings() || fixings_.size() > 0) && impl_)
impl()->retrieveFixings(loader_, fixings_, lastAvailableFixingLookupMap);
In case allFixings() is false we need to build the portfolio against a dummy market before asking it for its required fixings. I will make the related code changes now and we will release them in version 14 which is due at the beginning of November.
Many thanks for the heads up!
Hi @pcaspers, Thanks for getting back on this issue! We're looking forward to the release.
/Fredrik