FXForwards#

class rateslib.fx.FXForwards(fx_rates, fx_curves, base=NoInput.blank)#

Bases: object

Class for storing and calculating FX forward rates.

Parameters:
  • fx_rates (FXRates, or list of such) – An FXRates object with an associated settlement date. If multiple settlement dates are relevant, e.g. GBPUSD (T+2) and USDCAD(T+1), then a list of FXRates object is allowed to create a no arbitrage framework.

  • fx_curves (dict) – A dict of DF Curve objects defined by keys of two currency labels. First, by the currency in which cashflows occur (3-digit code), combined with the currency by which the future cashflow is collateralised in a derivatives sense (3-digit code). There must also be a curve in each currency for local discounting, i.e. where the cashflow and collateral currency are the same. See examples.

  • base (str, optional) – The base currency (3-digit code). If not given defaults to the base currency of the first fx_rates object.

Notes

\[\begin{split}f_{DOMFOR,i} &= \text{Forward domestic-foreign FX rate fixing on maturity date, }m_i \\ F_{DOMFOR,0} &= \text{Immediate settlement market domestic-foreign FX rate} \\ v_{dom:dom,i} &= \text{Local domestic-currency DF on maturity date, }m_i \\ w_{dom:for,i} &= \text{XCS adjusted domestic-currency DF on maturity date, }m_i \\\end{split}\]

Examples

The most basic FXForwards object is created from a spot FXRates object and two local currency discount curves.

In [1]: from rateslib.fx import FXRates, FXForwards

In [2]: from rateslib.curves import Curve
In [3]: fxr = FXRates({"eurusd": 1.1}, settlement=dt(2022, 1, 3))

In [4]: eur_local = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.91})

In [5]: usd_local = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.95})

In [6]: fxf = FXForwards(fxr, {"usdusd": usd_local, "eureur": eur_local, "eurusd": eur_local})

Note that in the above the eur_local curve has also been used as the curve for EUR cashflows collateralised in USD, which is necessary for calculation of forward FX rates and cross-currency basis. With this assumption the cross-currency basis is implied to be zero at all points along the curve.

fx_rates#
Type:

FXRates or list

fx_curves#
Type:

dict

immediate#
Type:

datetime

currencies#
Type:

dict

q#
Type:

int

currencies_list#
Type:

list

transform#
Type:

ndarray

base#
Type:

str

fx_rates_immediate#
Type:

FXRates

Methods Summary

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

Convert an amount of a domestic currency, as of a settlement date into a foreign currency, valued on another date.

convert_positions(array[, base])

Convert an input of currency cash positions into a single base currency value.

copy()

An FXForwards copy creates a new object with copied references.

curve(cashflow, collateral[, convention, ...])

Return a cash collateral curve.

from_json(fx_forwards, **kwargs)

Loads an FXForwards object from JSON.

plot(pair[, right, left, fx_swap])

Plot given forward FX rates.

positions(value[, base, aggregate])

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

rate(pair[, settlement, path, return_path])

Return the fx forward rate for a currency pair.

swap(pair, settlements[, path])

Return the FXSwap mid-market rate for the given currency pair.

to_json()

update([fx_rates, fx_curves, base])

Update the FXForward object with the latest FX rates and FX curves values.

Methods Documentation

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

Convert an amount of a domestic currency, as of a settlement date into a foreign currency, valued on another date.

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.

  • settlement (datetime, optional) – The date of the assumed domestic currency cashflow. If not given is assumed to be immediate settlement.

  • value_date (datetime, optional) – The date for which the domestic cashflow is to be projected to. If not given is assumed to be equal to the settlement.

  • collateral (str, optional) – The collateral currency to project the cashflow if value_date is different to settlement. If they are the same this is not needed. If not given defaults to domestic.

  • 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]: fxr1 = FXRates({"eurusd": 1.05}, settlement=dt(2022, 1, 3))

In [2]: fxr2 = FXRates({"usdcad": 1.1}, settlement=dt(2022, 1, 2))

In [3]: fxf = FXForwards(
   ...:     fx_rates=[fxr1, fxr2],
   ...:     fx_curves={
   ...:         "usdusd": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "eureur": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "cadcad": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "usdeur": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "cadusd": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:     }
   ...: )
   ...: 

In [4]: fxf.convert(1000, "usd", "cad")
Out[4]: <Dual: 1100.000000, (fx_usdcad, fx_eurusd), [1000.0, 0.0]>
convert_positions(array, base=NoInput.blank)#

Convert an input of currency cash positions into a single base currency value.

Parameters:
  • array (list, 1d ndarray of floats, or Series, or DataFrame) – The cash positions to simultaneously convert to base currency value. If a DataFrame, must be indexed by currencies (3-digit lowercase) and the column headers must be settlement dates. If a Series, must be indexed by currencies (3-digit lowercase). If a 1d array or sequence, must be ordered by currency as defined in the attribute FXForward.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}, settlement=dt(2022, 1, 1))

In [2]: usdusd = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99})

In [3]: noknok = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.995})

In [4]: fxf = FXForwards(fxr, {"usdusd": usdusd, "noknok": noknok, "nokusd": noknok})

In [5]: fxf.currencies
Out[5]: {'usd': 0, 'nok': 1}

In [6]: fxf.convert_positions([0, 1000000], "usd")
Out[6]: <Dual: 125000.000000, (fx_usdnok), [-15625.0]>
In [7]: fxr.convert_positions(Series([1000000, 0], index=["nok", "usd"]), "usd")
Out[7]: <Dual: 1000000.000000, (fx_usdnok), [-0.0]>
In [8]: positions = DataFrame(index=["usd", "nok"], data={
   ...:     dt(2022, 6, 2): [0, 1000000],
   ...:     dt(2022, 9, 7): [0, -1000000],
   ...: })
   ...: 

In [9]: fxf.convert_positions(positions, "usd")
Out[9]: <Dual: 166.054676, (fx_usdnok), [-20.8]>
copy()#

An FXForwards copy creates a new object with copied references.

curve(cashflow, collateral, convention=None, modifier=False, calendar=False, id=None)#

Return a cash collateral curve.

Parameters:
  • cashflow (str) – The currency in which cashflows are represented (3-digit code).

  • collateral (str, or list/tuple of such) – The currency of the CSA against which cashflows are collateralised (3-digit code). If a list or tuple will return a CompositeCurve in multi-CSA mode.

  • convention (str) – The day count convention used for calculating rates. If None defaults to the convention in the local cashflow currency.

  • modifier (str, optional) – The modification rule, in {“F”, “MF”, “P”, “MP”}, for determining rates. If False will default to the modifier in the local cashflow currency.

  • calendar (calendar or str, optional) – The holiday calendar object to use. If str, lookups named calendar from static data. Used for determining rates. If False will default to the calendar in the local cashflow currency.

  • id (str, optional) – The identifier attached to any constructed ProxyCurve.

Return type:

Curve, ProxyCurve or CompositeCurve

Notes

If the curve already exists within the attribute fx_curves that curve will be returned.

Otherwise, returns a ProxyCurve which determines and rates and DFs via the chaining method and the below formula,

\[w_{dom:for,i} = \frac{f_{DOMFOR,i}}{F_{DOMFOR,0}} v_{for:for,i}\]

The returned curve contains contrived methods to calculate rates and DFs from the combination of curves and FX rates that are available within the given FXForwards instance.

classmethod from_json(fx_forwards, **kwargs)#

Loads an FXForwards object from JSON.

Parameters:

fx_forwards (str) – JSON string describing the FXForwards class. Typically constructed with to_json().

Return type:

FXForwards

Notes

This method also creates new FXRates and Curve objects from JSON. These new objects can be accessed from the attributes of the FXForwards instance.

plot(pair, right=NoInput.blank, left=NoInput.blank, fx_swap=False)#

Plot given forward FX rates.

Parameters:
  • pair (str) – The FX pair to determine rates for (6-digit code).

  • right (datetime or str, optional) – The right bound of the graph. If given as str should be a tenor format defining a point measured from the initial node date of the curve. Defaults to the terminal date of the FXForwards object.

  • left (datetime or str, optional) – The left bound of the graph. If given as str should be a tenor format defining a point measured from the initial node date of the curve. Defaults to the immediate FX settlement date.

  • fx_swap (bool) – Whether to plot as the FX rate or as FX swap points relative to the initial FX rate on the left side of the chart. Default is False.

Returns:

(fig, ax, line)

Return type:

Matplotlib.Figure, Matplotplib.Axes, Matplotlib.Lines2D

positions(value, base=NoInput.blank, aggregate=False)#

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

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.

  • aggregate (bool, optional) – Whether to aggregate positions across all settlement dates and yield a single column Series.

Return type:

DataFrame or Series

Examples

In [1]: fxr1 = FXRates({"eurusd": 1.05}, settlement=dt(2022, 1, 3))

In [2]: fxr2 = FXRates({"usdcad": 1.1}, settlement=dt(2022, 1, 2))

In [3]: fxf = FXForwards(
   ...:     fx_rates=[fxr1, fxr2],
   ...:     fx_curves={
   ...:         "usdusd": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "eureur": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "cadcad": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "usdeur": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:         "cadusd": Curve({dt(2022, 1, 1):1.0, dt(2022, 2, 1): 0.999}),
   ...:     }
   ...: )
   ...: 

In [4]: fxf.positions(
   ...:     value=Dual(100000, ["fx_eurusd", "fx_usdcad"], [-100000, -150000]),
   ...:     base="usd",
   ...: )
   ...: 
Out[4]: 
     2022-01-01  2022-01-02  2022-01-03
cad        0.00   181500.00        0.00
eur        0.00        0.00  -100000.00
usd   100000.00  -165000.00   105000.00
rate(pair, settlement=NoInput.blank, path=NoInput.blank, return_path=False)#

Return the fx forward rate for a currency pair.

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

  • settlement (datetime, optional) – The settlement date of currency exchange. If not given defaults to immediate settlement.

  • path (list of dict, optional) – The chain of currency collateral curves to traverse to calculate the rate. This is calculated automatically and this argument is provided for internal calculation to avoid repeatedly calculating the same path. Use of this argument in normal circumstances is not recommended.

  • return_path (bool) – If True returns the path in a tuple alongside the rate. Use of this argument in normal circumstances is not recommended.

Return type:

float, Dual, Dual2 or tuple

Notes

Uses the formula,

\[f_{DOMFOR, i} = \frac{w_{dom:for, i}}{v_{for:for, i}} F_{DOMFOR,0} = \frac{v_{dom:dom, i}}{w_{for:dom, i}} F_{DOMFOR,0}\]

where \(v\) is a local currency discount curve and \(w\) is a discount curve collateralised with an alternate currency.

Where curves do not exist in the relevant currencies we chain rates available given the available curves.

\[f_{DOMFOR, i} = f_{DOMALT, i} ... f_{ALTFOR, i}\]
swap(pair, settlements, path=NoInput.blank)#

Return the FXSwap mid-market rate for the given currency pair.

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

  • settlements (list of datetimes,) – The settlement date of currency exchanges.

  • path (list of dict, optional) – The chain of currency collateral curves to traverse to calculate the rate. This is calculated automatically and this argument is provided for internal calculation to avoid repeatedly calculating the same path. Use of this argument in normal circumstances is not recommended.

Return type:

Dual

to_json()#
update(fx_rates=NoInput.blank, fx_curves=NoInput.blank, base=NoInput.blank)#

Update the FXForward object with the latest FX rates and FX curves values.

The update method is primarily used to allow synchronous updating within a Solver.

Parameters:
  • fx_rates (FXRates, or list of such, optional) – An FXRates object with an associated settlement date. If multiple settlement dates are relevant, e.g. GBPUSD (T+2) and USDCAD(T+1), then a list of FXRates object is allowed to create a no arbitrage framework.

  • fx_curves (dict, optional) – A dict of DF Curve objects defined by keys of two currency labels. First, by the currency in which cashflows occur (3-digit code), combined with the currency by which the future cashflow is collateralised in a derivatives sense (3-digit code). There must also be a curve in each currency for local discounting, i.e. where the cashflow and collateral currency are the same. See examples of instance instantiation.

  • base (str, optional) – The base currency (3-digit code). If not given defaults to the base currency of the first given fx_rates object.

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.

Do not do this..

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

In [2]: fx_curves = {
   ...:     "usdusd": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.965}),
   ...:     "eureur": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.985}),
   ...:     "eurusd": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.985}),
   ...: }
   ...: 

In [3]: fxf = FXForwards(fxr, fx_curves)

In [4]: id(fxr) == id(fxf.fx_rates)  #  <- these objects are associated
Out[4]: True

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

In [6]: id(fxr) == id(fxf.fx_rates)  #  <- this association is broken by new instance
Out[6]: False

In [7]: fxf.rate("eurusd", dt(2022, 1, 3))  # <- wrong price because it is broken
Out[7]: <Dual: 1.050000, (fx_eurusd), [1.0]>

Instead do this..

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

In [9]: fx_curves = {
   ...:     "usdusd": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.965}),
   ...:     "eureur": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.985}),
   ...:     "eurusd": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.985}),
   ...: }
   ...: 

In [10]: fxf = FXForwards(fxr, fx_curves)

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

In [12]: fxf.update()

In [13]: id(fxr) == id(fxf.fx_rates)  #  <- this association is maintained
Out[13]: True

In [14]: fxf.rate("eurusd", dt(2022, 1, 3))  # <- correct new price
Out[14]: <Dual: 1.060000, (fx_eurusd), [1.0]>

For regular use, an FXForwards class has its associations, with FXRates and Curve s, set at instantiation. This means that the most common form of this method will be to call it with no new arguments, but after either one of the FXRates or Curve objects has itself been updated.

Examples

Updating a component FXRates instance before updating the FXForwards.

In [15]: uu_curve = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.96}, id="uu")

In [16]: fx_curves = {
   ....:     "usdusd": uu_curve,
   ....:     "eureur": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, id="ee"),
   ....:     "eurusd": Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.991}, id="eu"),
   ....: }
   ....: 

In [17]: fx_rates = FXRates({"usdeur": 0.9}, dt(2022, 1, 3))

In [18]: fxf = FXForwards(fx_rates, fx_curves)

In [19]: fxf.rate("usdeur", dt(2022, 7, 15))
Out[19]: <Dual: 0.885002, (fx_usdeur), [1.0]>

In [20]: fx_rates.update({"usdeur": 1.0})

In [21]: fxf.update()

In [22]: fxf.rate("usdeur", dt(2022, 7, 15))
Out[22]: <Dual: 0.983336, (fx_usdeur), [1.0]>

Updating an FXForwards instance with a new FXRates instance.

In [23]: fxf = FXForwards(FXRates({"usdeur": 0.9}, dt(2022, 1, 3)), fx_curves)

In [24]: fxf.update(FXRates({"usdeur": 1.0}, dt(2022, 1, 3)))

In [25]: fxf.rate("usdeur", dt(2022, 7, 15))
Out[25]: <Dual: 0.983336, (fx_usdeur), [1.0]>

Updating a Curve component before updating the FXForwards.

In [26]: fxf = FXForwards(FXRates({"usdeur": 0.9}, dt(2022, 1, 3)), fx_curves)

In [27]: uu_curve.nodes[dt(2023, 1, 1)] = 0.98

In [28]: fxf.update()

In [29]: fxf.rate("usdeur", dt(2022, 7, 15))
Out[29]: <Dual: 0.894704, (fx_usdeur), [1.0]>