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 ofFXRates
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 spotFXRates
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_curves#
- Type:
dict
- immediate#
- Type:
datetime
- currencies#
- Type:
dict
- q#
- Type:
int
- currencies_list#
- Type:
list
- transform#
- Type:
ndarray
- base#
- Type:
str
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 tosettlement
. If they are the same this is not needed. If not given defaults todomestic
.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]: 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:
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:
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:
Notes
This method also creates new
FXRates
andCurve
objects from JSON. These new objects can be accessed from the attributes of theFXForwards
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 thebase
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:
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:
- 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 ofFXRates
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, withFXRates
andCurve
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 theFXRates
orCurve
objects has itself been updated.Examples
Updating a component
FXRates
instance before updating theFXForwards
.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 newFXRates
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 theFXForwards
.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]>