FXRates#

class rateslib.fx.FXRates(fx_rates, settlement=NoInput.blank, base=NoInput.blank)#

Bases: _WithState

Object to store and calculate FX rates for a consistent settlement date.

Parameters:
  • fx_rates (dict[str, float]) – Dict whose keys are 6-character currency pairs, and whose values are the relevant rates.

  • settlement (datetime, optional) – The settlement date for the FX rates.

  • base (str, optional) –

    The base currency (3-digit code). If not given defaults to either:

    • the base currency defined in defaults, if it is present in the list of currencies,

    • the first currency detected.

Notes

Note

When this class uses Dual numbers to represent sensitivities of values to certain FX rates the variable names are called “fx_cc1cc2” where “cc1” is left hand currency and “cc2” is the right hand currency in the currency pair. See the examples contained in class methods for clarification.

Examples

An FX rates market of n currencies is completely defined by n-1 independent FX pairs.

Below we define an FX rates market in 4 currencies with 3 FX pairs,

In [1]: fxr = FXRates({"eurusd": 1.1, "gbpusd": 1.25, "usdjpy": 100})

In [2]: fxr.currencies
Out[2]: {'usd': 0, 'eur': 1, 'gbp': 2, 'jpy': 3}

In [3]: fxr.rate("gbpjpy")
Out[3]: <Dual: 125.000000, (fx_gbpusd, fx_usdjpy), [100.0, 1.2]>

Ill defined FX markets will raise ValueError and are either overspecified,

In [4]: try:
   ...:     FXRates({"eurusd": 1.1, "gbpusd": 1.25, "usdjpy": 100, "gbpjpy": 125})
   ...: except ValueError as e:
   ...:     print(e)
   ...: 
FX Array cannot be solved. `fx_rates` is overspecified.

or are underspecified,

In [5]: try:
   ...:     FXRates({"eurusd": 1.1, "gbpjpy": 125})
   ...: except ValueError as e:
   ...:     print(e)
   ...: 
FX Array cannot be solved. `fx_rates` is underspecified.

or use redundant, co-dependent information,

In [6]: try:
   ...:     FXRates({"eurusd": 1.1, "usdeur": 0.90909, "gbpjpy": 125})
   ...: except ValueError as e:
   ...:     print(e)
   ...: 
FX Array cannot be solved. There are degenerate FX rate pairs.
For example ('eurusd' + 'usdeur') or ('usdeur', 'eurjpy', 'usdjpy').

Attributes Summary

base

The assumed base currency of the object which may be used as the default base currency in npv calculations when otherwise omitted.

currencies

A dict whose keys are the currencies contained in the object and the value is the ordered index of that currencies in other attributes such as fx_array and currencies_list.

currencies_list

An list of currencies available in the object.

fx_array

An array containing all of the FX pairs/crosses available on the object.

fx_rates

The dict of currency pairs and their FX rates that define the object.

fx_vector

A vector of currency FX rates all relative to the stated base currency.

pairs

A list of the currency pairs that define the object.

pairs_settlement

A dict aggregating each FX pair and its settlement date.

q

The number of currencies contained in the object.

settlement

The settlement date of the FX rates that define the object.

variables

The names of the variables associated with the object for automatic differentiation (AD) purposes.

Methods Summary

convert(value, domestic[, foreign, on_error])

Convert an amount of a domestic currency into a foreign currency.

convert_positions(array[, base])

Convert an array of currency cash positions into a single base currency.

positions(value[, base])

Convert a base value with FX rate sensitivities into an array of cash positions.

rate(pair)

Return a specified FX rate for a given currency pair.

rates_table()

Return a DataFrame of all FX rates in the object.

restate(pairs[, keep_ad])

Create a new FXRates class using other (or fewer) currency pairs as majors.

to_json()

Return a JSON representation of the object.

update([fx_rates])

Update all or some of the FX rates of the instance with new market data.

Attributes Documentation

base#

The assumed base currency of the object which may be used as the default base currency in npv calculations when otherwise omitted.

The base currency has index 0 in the currencies dict and is that which the fx_vector is defined relative to.

currencies#

A dict whose keys are the currencies contained in the object and the value is the ordered index of that currencies in other attributes such as fx_array and currencies_list.

currencies_list#

An list of currencies available in the object. Aligns with currencies.

fx_array#

An array containing all of the FX pairs/crosses available on the object.

fx_rates#

The dict of currency pairs and their FX rates that define the object.

fx_vector#

A vector of currency FX rates all relative to the stated base currency.

pairs#

A list of the currency pairs that define the object. The number of pairs is one less than q.

pairs_settlement#

A dict aggregating each FX pair and its settlement date. In an FXRates object all pairs settle on the same settlement date.

q#

The number of currencies contained in the object.

settlement#

The settlement date of the FX rates that define the object.

variables#

The names of the variables associated with the object for automatic differentiation (AD) purposes.

Methods Documentation

convert(value, domestic, foreign=NoInput.blank, on_error='ignore')#

Convert an amount of a domestic currency into a foreign currency.

Parameters:
  • value (float or Dual) – The amount of the domestic currency to convert.

  • domestic (str) – The domestic currency (3-digit code).

  • foreign (str, optional) – The foreign currency to convert to (3-digit code). Uses instance base if not given.

  • on_error (str in {"ignore", "warn", "raise"}) – The action taken if either domestic or foreign are not contained in the FX framework. “ignore” and “warn” will still return None.

Return type:

Dual or None

Examples

In [1]: fxr = FXRates({"usdnok": 8.0})

In [2]: fxr.convert(1000000, "nok", "usd")
Out[2]: <Dual: 125000.000000, (fx_usdnok), [-15625.0]>

In [3]: fxr.convert(1000000, "nok", "inr")  # <- returns None, "inr" not in fxr.
convert_positions(array, base=NoInput.blank)#

Convert an array of currency cash positions into a single base currency.

Parameters:
  • array (list, 1d ndarray of floats, or Series) – The cash positions to simultaneously convert in the base currency. Must be ordered by currency as defined in the attribute FXRates.currencies.

  • base (str, optional) – The currency to convert to (3-digit code). Uses instance base if not given.

Return type:

Dual

Examples

In [1]: fxr = FXRates({"usdnok": 8.0})

In [2]: fxr.currencies
Out[2]: {'usd': 0, 'nok': 1}

In [3]: fxr.convert_positions([0, 1000000], "usd")
Out[3]: <Dual: 125000.000000, (fx_usdnok), [-15625.0]>
positions(value, base=NoInput.blank)#

Convert a base value with FX rate sensitivities into an array of cash positions.

Parameters:
  • value (float or Dual) – The amount expressed in base currency to convert to cash positions.

  • base (str, optional) – The base currency in which value is given (3-digit code). If not given assumes the base of the object.

Return type:

Series

Examples

In [1]: fxr = FXRates({"usdnok": 8.0})

In [2]: fxr.positions(Dual(125000, ["fx_usdnok"], [-15625]), "usd")
Out[2]: 
usd          0.0
nok    1000000.0
dtype: float64

In [3]: fxr.positions(100, base="nok")
Out[3]: 
usd      0.0
nok    100.0
dtype: float64
rate(pair)#

Return a specified FX rate for a given currency pair.

Parameters:

pair (str) – The FX pair in usual domestic:foreign convention (6 digit code).

Return type:

Dual

Examples

In [1]: fxr = FXRates({"usdeur": 2.0, "usdgbp": 2.5})

In [2]: fxr.rate("eurgbp")
Out[2]: <Dual: 1.250000, (fx_usdeur, fx_usdgbp), [-0.6, 0.5]>
rates_table()#

Return a DataFrame of all FX rates in the object.

Return type:

DataFrame

restate(pairs, keep_ad=False)#

Create a new FXRates class using other (or fewer) currency pairs as majors.

Parameters:
  • pairs (list of str) – The new currency pairs with which to define the FXRates class.

  • keep_ad (bool, optional) – Keep the original derivative exposures defined by Dual, instead of redefinition. It is advised against setting this to True, it is mainly used internally.

Return type:

FXRates

Notes

This will redefine the pairs to which delta risks are expressed in Dual outputs.

If pairs match the existing object and keep_ad is requested then the existing object is returned unchanged as new copy.

Examples

Re-expressing an FXRates class with new majors, to which Dual sensitivities are measured.

In [1]: fxr = FXRates({"eurgbp": 0.9, "gbpjpy": 125, "usdjpy": 100})

In [2]: fxr.convert(100, "gbp", "usd")
Out[2]: <Dual: 125.000000, (fx_usdjpy, fx_gbpjpy), [-1.2, 1.0]>

In [3]: fxr2 = fxr.restate(["eurusd", "gbpusd", "usdjpy"])

In [4]: fxr2.convert(100, "gbp", "usd")
Out[4]: <Dual: 125.000000, (fx_gbpusd), [100.0]>

Extracting an FXRates subset from a larger object.

In [5]: fxr = FXRates({"eurgbp": 0.9, "gbpjpy": 125, "usdjpy": 100, "audusd": 0.85})

In [6]: fxr2 = fxr.restate({"eurusd", "gbpusd"})

In [7]: fxr2.rates_table()
Out[7]: 
       usd  gbp       eur
usd  1.000  0.8  0.888889
gbp  1.250  1.0  1.111111
eur  1.125  0.9  1.000000
to_json()#

Return a JSON representation of the object.

Return type:

str

update(fx_rates=NoInput.blank)#

Update all or some of the FX rates of the instance with new market data.

Parameters:

fx_rates (dict, optional) – Dict whose keys are 6-character domestic-foreign currency pairs and which are present in FXRates.pairs, and whose values are the relevant rates to update. An empty dict will be ignored and perform no update.

Return type:

None

Notes

Warning

Rateslib is an object-oriented library that uses complex associations. Although Python may not object to directly mutating attributes of an FXRates instance, this should be avoided in rateslib. Only use official update methods to mutate the values of an existing FXRates instance. This class is labelled as a mutable on update object.

Suppose an FXRates class has been instantiated and resides in memory.

In [1]: fxr = FXRates({"eurusd": 1.05, "gbpusd": 1.25}, settlement=dt(2022, 1, 3), base="usd")

In [2]: id(fxr)
Out[2]: 4703668272

This object may be linked to others, probably an FXForwards class. It can be updated with some new market data. This will preserve its memory id and association with other objects. Any FXForwards objects referencing this will detect this change and will also lazily update via rateslib’s state management.

In [3]: linked_obj = fxr

In [4]: fxr.update({"eurusd": 1.06})

In [5]: id(fxr)  # <- SAME as above
Out[5]: 4703668272

In [6]: linked_obj.rate("eurusd")
Out[6]: <Dual: 1.060000, (fx_eurusd), [1.0]>

Examples

In [7]: fxr = FXRates({"usdeur": 0.9, "eurnok": 8.5})

In [8]: fxr.rate("usdnok")
Out[8]: <Dual: 7.650000, (fx_usdeur, fx_eurnok), [8.5, 0.9]>

In [9]: fxr.update({"usdeur": 1.0})

In [10]: fxr.rate("usdnok")
Out[10]: <Dual: 8.500000, (fx_usdeur, fx_eurnok), [8.5, 1.0]>