Skip to content
All library documents

Expressing NPV Sensitivity in Different FX Rate Bases

Article Quant Q&A · Author: Sentinel

Summary

The document explains how to calculate first-order FX sensitivities when a pricing function’s inputs use one set of exchange rates but the desired risk measures use another. It represents portfolio value as amounts in their local currencies, then converts the resulting positions into a reporting currency using a chosen set of FX majors. The sensitivities depend on that choice of FX basis.

An example with USD, EUR, and SEK shows that converting the same positions using EURUSD and EURSEK produces different derivatives than restating the FX system using USDSEK and EURSEK, while the reported value stays the same. The explanation uses automatic differentiation to propagate exposures through cross rates. Its practical recommendation is to derive value in local currencies first and apply base-currency conversion as the final step. The example illustrates the method, but the document does not give a general procedure for extracting sensitivities from every black-box pricing function.

Key ideas

  • Represent portfolio value as a vector of amounts in local currencies before converting to a reporting currency.
  • FX sensitivities depend on which exchange rates are selected as the system’s majors.
  • Cross rates inherit sensitivity to the exchange rates used to construct them.
  • Automatic differentiation can propagate FX exposures through the conversion array.
  • Calculate local-currency value first, then apply base-currency conversion as the final step.

Tags

Full text
# NPV function sensitivity to FX rates, when those rates are not in the variables of the function


# NPV function sensitivity to FX rates, when those rates are not in the variables of the function












How do I calculate a sensitivity of NPV function to FX rate to the reporting (base) currency, when that FX rate is not in the variables of the said function?

For example,

$$f(C_1, C_2, DF_1, DF_2, [c_2/c_1], [c_b/c_2]) = (C_1\times DF_1\times [c_2/c_1]+C_2\times DF_2)\times [c_b/c_2]$$

where $[c_2/c_1]$ – FX rate of $c_2$ currency per one unit of $c_1$ currency, $[c_b/c_2]$ – FX rate of a base currency per one unit of $c_2$ currency, $DF$ – discount factor, $C$ – amount in appropriate currency.

The function $f$ is a black box. I need the sensitivity of $f$ to $[c_b/c_1]$ and $[c_b/c_2]$.

- $\frac{\partial f}{\partial[c_b/c_2]}$ can be calculated numerically, but how do I calculate $\frac{\partial f}{\partial[c_b/c_1]}$?

- In this example I know that the correct answer is $\frac{\partial f}{\partial[c_b/c_1]} = C_1\times DF_1$, but what if the function is much more complex and I do not see what is inside of $f$?

## Answer by Attack68 (score 1, accepted)

https://quant.stackexchange.com/a/85200

I think of this problem in the following way.

You have an NPV, which is a vector of values expressed in a number of local currencies (e.g. consider the two legs of a USD/EUR cross-currency swap, and you express this value in a third, base accounting currency SEK):

$$ P = \begin{matrix} USD \\ EUR \\ SEK \end{matrix} \begin{bmatrix} 100 \\ -150 \\ 0 \end{bmatrix} $$

This representation is convertible into a single value with first order sensitivity to FX rates. But the sensitivity depends upon which are the "majors" of your FX system.

$$ P \rightarrow -696 \; SEK \qquad \text{with EURUSD 1.15 and EURSEK 11.05} $$

As an example in rateslib you can see the following values:

```
from rateslib import *  # Python 3.12, rateslib 2.1.1

fxr = FXRates({"eurusd": 1.15, "eursek": 11.05})
print(fxr.currencies)  # ->  USD, EUR, SEK
print(fxr.convert_positions([100, -150.0, 0], base="sek"))
###
<Dual: -696.630435, (fx_eurusd, fx_eursek), [-835.5, -63.0]>
###
```

So the value is -696 SEK with first order derivative sensitivity to the EURUSD FX rate and the EURSEK FX rate of -835 and -63 respectively.

It does this by building an FX rates array with exposures of each of those "crosses" with sensitivities expressed relative to the "majors". These sensitivities are stored as Dual number data types as part of the auto-diff framework. For the `FXRates` object above the FX array looks like this:

```
[[<Dual: 1.000, (), []>                              <Dual: 0.869, (fx_eurusd), [-0.8]> <Dual: 9.608, (fx_eurusd, fx_eursek), [-8.4, 0.9]>]
 [<Dual: 1.150, (fx_eurusd), [1.0]>                  <Dual: 1.000, (), []>              <Dual: 11.050, (fx_eursek), [1.0]>]
 [<Dual: 0.104, (fx_eurusd, fx_eursek), [0.1, -0.0]> <Dual: 0.090, (fx_eursek), [-0.0]> <Dual: 1.000, (), []>]]
```

One observes, for example, that the USDSEK (1/EURUSD * EURSEK) rate is 9.608 and it has sensitivity directly to both the EURUSD and the EURSEK FX rates, which one would expect.

If you choose to re-express this with sensitivities to other FX rates you will observe different quantities:

```
fxr2 = fxr.restate(["usdsek", "eursek"])
print(fxr2.currencies)  # ->  USD, SEK, EUR
print(fxr2.convert_positions([100, 0, -150], base="sek"))
###
<Dual: -696.630435, (fx_usdsek, fx_eursek), [100.0, -150.0]>
###
```

The value is obviously the same but the first order sensitivities are now expressed relative to USDSEK and EURSEK. These are also trivial to comprehend: since there is 100USD, if the USDSEK rate increases by 1.0 the value changes by 100 SEK, and on the other hand if the EURSEK FX rate increases by 1.0 the values changes by -150 SEK, since there is -150 EUR value initially.

As a general answer, I always first derive local currency value for a pricing function and consider the base accounting conversion as the final step.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.