FXRates#
- class rateslib.fx.FXRates(fx_rates, settlement=NoInput.blank, base=NoInput.blank)#
Bases:
object
Object to store and calculate FX rates for a consistent settlement date.
- Parameters:
fx_rates (dict) – Dict whose keys are 6-character domestic-foreign 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_domfor” where “dom” is a domestic currency and “for” is a foreign currency. 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
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.
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
()update
([fx_rates])Update all or some of the FX rates of the instance with new market data.
Attributes Documentation
- base#
- currencies_list#
- fx_array#
- fx_rates#
- fx_vector#
- pairs#
- pairs_settlement#
- q#
- settlement#
- variables#
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
orforeign
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:
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 thebase
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.00 nok 1000000.00 dtype: float64 In [3]: fxr.positions(100, base="nok") Out[3]: usd 0.00 nok 100.00 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:
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:
Notes
This will redefine the pairs to which delta risks are expressed in
Dual
outputs.If
pairs
match the existing object andkeep_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 eur gbp usd 1.00 0.89 0.80 eur 1.12 1.00 0.90 gbp 1.25 1.11 1.00
- to_json()#
- 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.
- Return type:
None
Notes
Warning
Rateslib is an object-oriented library that uses complex associations. It is best practice to create objects and any associations and then use the
update
methods to push new market data to them. Recreating objects with new data will break object-oriented associations and possibly lead to undetected market data based pricing errors.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]: 4673999056
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 (however, any linked objects should also be updated to cascade new calculations).In [3]: linked_obj = fxr In [4]: fxr.update({"eurusd": 1.06}) In [5]: id(fxr) # <- SAME as above Out[5]: 4673999056 In [6]: linked_obj.rate("eurusd") Out[6]: <Dual: 1.060000, (fx_eurusd), [1.0]>
Do not do the following because overwriting a variable name will not eliminate the previous object from memory. Linked objects will still refer to the previous FXRates class still in memory.
In [7]: fxr = FXRates({"eurusd": 1.05}, settlement=dt(2022, 1, 3), base="usd") In [8]: id(fxr) # <- NEW memory id, linked objects still associated with old fxr in memory Out[8]: 4673997424 In [9]: linked_obj.rate("eurusd") # will NOT return rate from the new `fxr` object Out[9]: <Dual: 1.060000, (fx_eurusd), [1.0]>
Examples
In [10]: fxr = FXRates({"usdeur": 0.9, "eurnok": 8.5}) In [11]: fxr.rate("usdnok") Out[11]: <Dual: 7.650000, (fx_usdeur, fx_eurnok), [8.5, 0.9]> In [12]: fxr.update({"usdeur": 1.0}) In [13]: fxr.rate("usdnok") Out[13]: <Dual: 8.500000, (fx_usdeur, fx_eurnok), [8.5, 1.0]>