API ReferenceFX API Reference

FX Instruments

Cross-currency swaps, FX forwards, and non-deliverable instruments.

All types are available via flat import:

from vade import XCS, FXForward, NDF, NDIRS, NDXCS

Or via product-path import:

from vade.instruments.fx import XCS, FXForward, NDF, NDIRS, NDXCS

See Conventions for all accepted string parameter values.

Contents: XCS | FXForward | NDF | NDIRS | NDXCS


XCS

Cross Currency Swap with 4-curve pricing model. Python wrapper composing legs across currencies.

See also: Cross-Currency Swaps Guide for cross-currency pricing workflows.

Alias: XCS = CrossCurrencySwap

Constructor

XCS(
    *,
    effective=None,
    termination=None,
    frequency="q",
    leg1_currency="EUR",
    leg2_currency="USD",
    leg1_notional=1_000_000.0,
    leg2_notional=1_100_000.0,
    initial_fx_rate=1.1,
    fixed_rate=None,
    notional_exchange=True,
    convention="act360",
    leg2_convention=None,
    fixing_method="rfr_payment_delay",
    spread=0.0,
    modifier="mf",
    stub="shortfront",
    mtm_leg=None,
)

Parameters

NameTypeDefaultDescription
effectivedatetime.date or NoneNoneStart date
terminationdate, str, or NoneNoneEnd date or tenor string
frequencystr"q"Payment frequency
leg1_currencystr"EUR"Leg 1 currency code
leg2_currencystr"USD"Leg 2 currency code
leg1_notionalfloat1_000_000.0Leg 1 notional amount
leg2_notionalfloat1_100_000.0Leg 2 notional amount
initial_fx_ratefloat1.1Initial FX rate (leg2/leg1)
fixed_ratefloat or NoneNoneFixed rate on one leg (if applicable)
notional_exchangeboolTrueWhether to exchange notionals at start and end
conventionstr"act360"Day count convention for leg 1
leg2_conventionstr or NoneNoneDay count convention for leg 2 (defaults to convention)
fixing_methodstr"rfr_payment_delay"Rate fixing method
spreadfloat0.0Spread on leg 2 (basis points)
modifierstr"mf"Business day adjustment rule
stubstr"shortfront"Stub period preference
mtm_legint or NoneNoneMark-to-market reset leg (1 or 2)

See Conventions for accepted values for frequency, convention, fixing_method, modifier, and stub.

Methods

XCS methods require four separate curves (discount and forecast for each currency) plus FXRates.

MethodReturnsDescription
.rate(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates, metric="leg2")floatCross-currency basis spread
.npv(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates)floatNet present value
.cashflows(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast)DataFramePeriod-level cashflow table

Example

import datetime
from vade import XCS, DiscountCurve, FXRates

eur_disc = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.97, datetime.date(2026, 1, 1): 0.94},
    interpolation="log_linear", convention="act365f", id="eur_disc",
)
eur_fcast = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.97, datetime.date(2026, 1, 1): 0.94},
    interpolation="log_linear", convention="act365f", id="eur_fcast",
)
usd_disc = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.96, datetime.date(2026, 1, 1): 0.92},
    interpolation="log_linear", convention="act365f", id="usd_disc",
)
usd_fcast = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.96, datetime.date(2026, 1, 1): 0.92},
    interpolation="log_linear", convention="act365f", id="usd_fcast",
)
fx = FXRates({"eurusd": 1.10}, settlement=datetime.date(2024, 1, 1))

xcs = XCS(
    effective=datetime.date(2024, 1, 1),
    termination="2Y",
    frequency="q",
    leg1_currency="EUR",
    leg2_currency="USD",
    leg1_notional=1_000_000.0,
    leg2_notional=1_100_000.0,
    initial_fx_rate=1.10,
    convention="act360",
)
float(xcs.rate(eur_disc, eur_fcast, usd_disc, usd_fcast, fx))  # cross-currency basis spread
float(xcs.npv(eur_disc, eur_fcast, usd_disc, usd_fcast, fx))  # NPV in base currency

FXForward

FX Forward instrument. Rust-backed.

See also: FX Rates & Forwards Guide for FX forward pricing.

Constructor

FXForward(
    *,
    pair="eurusd",
    notional=1_000_000.0,
    delivery=None,
    currency="USD",
)

Parameters

NameTypeDefaultDescription
pairstr"eurusd"Currency pair (e.g., "eurusd", "gbpusd")
notionalfloat1_000_000.0Notional amount
deliverydatetime.date or NoneNoneDelivery date
currencystr"USD"Settlement currency

Methods

FXForward methods take a discount curve, forecast curve, and FXRates.

MethodReturnsDescription
.rate(disc_curve, forecast_curve, fx_rates)floatForward FX rate
.npv(disc_curve, forecast_curve, fx_rates)floatNet present value
.cashflows(disc_curve, forecast_curve, fx_rates)DataFramePeriod-level cashflow table

Example

import datetime
from vade import FXForward, DiscountCurve, FXRates

eur_curve = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.97},
    interpolation="log_linear", convention="act365f", id="eur_curve",
)
usd_curve = DiscountCurve(
    {datetime.date(2024, 1, 1): 1.0, datetime.date(2025, 1, 1): 0.96},
    interpolation="log_linear", convention="act365f", id="usd_curve",
)
fx = FXRates({"eurusd": 1.10}, settlement=datetime.date(2024, 1, 1))

fxf = FXForward(
    pair="eurusd",
    notional=1_000_000.0,
    delivery=datetime.date(2024, 7, 1),
    currency="USD",
)
float(fxf.rate(usd_curve, eur_curve, fx))  # forward FX rate
float(fxf.npv(usd_curve, eur_curve, fx))  # NPV of the forward position

Non-Deliverable Instruments

Non-deliverable (ND) instruments settle in a convertible currency rather than the restricted currency in which cashflows accrue. FX conversion uses per-period fixings (known or IRP-implied).


NDF

Non-Deliverable Forward: single-currency net settlement of an FX forward. Subclass of FXForward.

See also: Non-Deliverable Instruments Guide for NDF, NDIRS, and NDXCS workflows.

Constructor

NDF(
    *,
    spec=None,           # Market convention ("usdbrl_ndf", "usdkrw_ndf", ...)
    effective=None,      # Effective / trade date
    delivery=None,       # Settlement date
    pair="usdbrl",       # FX pair (restricted vs settlement)
    notional=1_000_000.0,
    currency="USD",      # Notional currency
    settlement_currency="usd",
    contracted_rate=None,  # Agreed FX rate (None = at-market)
    fx_fixings=None,     # dict[date, float] for known fixings
)

Methods

MethodSignatureReturns
rate(disc_curve, forecast_curve, fx_rates)Implied forward rate (IRP)
npv(disc_curve, forecast_curve, fx_rates)Net settlement NPV in settlement currency
cashflows(disc_curve, forecast_curve, fx_rates)Polars DataFrame
spread(disc_curve, forecast_curve, fx_rates)Spread to contracted rate
pillar_date()Delivery date
to_json()JSON-serializable dict
from_json(data)Reconstruct NDF from dict

Example

import datetime
from vade import NDF, DiscountCurve, FXRates

ndf = NDF(
    spec="usdbrl_ndf",
    effective=datetime.date(2025, 6, 16),
    delivery=datetime.date(2025, 9, 16),
    notional=1_000_000.0,
    contracted_rate=5.25,
)

usd = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2026, 6, 16): 0.96},
    interpolation="log_linear", convention="act360",
)
brl = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2026, 6, 16): 0.88},
    interpolation="log_linear", convention="act360",
)
fxr = FXRates({"usdbrl": 5.20}, settlement=datetime.date(2025, 6, 16))

fair_rate = ndf.rate(usd, brl, fxr)
npv = ndf.npv(usd, brl, fxr)
assert abs(float(fair_rate)) < 10
assert abs(float(npv)) < 1e8

NDIRS

Non-Deliverable Interest Rate Swap: IRS where cashflows accrue in a restricted currency but settle in a convertible currency via per-period FX conversion. Subclass of InterestRateSwap.

Uses a 3-curve model: settlement discount, restricted forecast, restricted discount.

Constructor

NDIRS(
    *,
    spec=None,             # Market convention ("usdbrl_ndirs", ...)
    effective=None,
    termination=None,      # date or tenor string ("5Y")
    frequency="s",
    fixed_rate=0.0,
    notional=1_000_000.0,
    convention="act360",
    settlement_currency="usd",
    pair="usdbrl",
    fx_fixings=None,       # dict[date, float] known FX fixings
)

Methods

MethodSignatureReturns
rate(curves=[disc, forecast, leg2_disc], fx_rates=fxr)Par fixed rate
npv(curves=[disc, forecast, leg2_disc], fx_rates=fxr)NPV in settlement currency
cashflows(curves=[disc, forecast, leg2_disc], fx_rates=fxr)Polars DataFrame with settlement columns
spread(curves=[disc, forecast, leg2_disc], fx_rates=fxr)Par spread on float leg
pillar_date()Maturity date
to_json()JSON-serializable dict
from_json(data)Reconstruct NDIRS from dict

Curve arguments: disc_curve = settlement discount, forecast_curve = restricted forecast, leg2_disc_curve = restricted discount (for IRP forwards).

Example

import datetime
from vade import NDIRS, DiscountCurve, FXRates

ndirs = NDIRS(
    spec="usdbrl_ndirs",
    effective=datetime.date(2025, 6, 16),
    termination="2Y",
    fixed_rate=10.0,
    notional=1_000_000.0,
)

usd = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2028, 6, 16): 0.89},
    interpolation="log_linear", convention="act360",
)
brl = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2028, 6, 16): 0.71},
    interpolation="log_linear", convention="act360",
)
fxr = FXRates({"usdbrl": 5.20}, settlement=datetime.date(2025, 6, 16))

par_rate = ndirs.rate(curves=[usd, brl, brl], fx_rates=fxr)
npv = ndirs.npv(curves=[usd, brl, brl], fx_rates=fxr)
assert 0 < float(par_rate) < 30
assert abs(float(npv)) < 1e8

NDXCS

Non-Deliverable Cross-Currency Swap: one leg is non-deliverable with cashflows converted via per-period FX fixings and settled in a convertible currency. Supports notional exchanges and MTM resets on the ND leg. Subclass of CrossCurrencySwap.

Constructor

NDXCS(
    *,
    spec=None,               # Market convention ("usdbrl_ndxcs", ...)
    effective=None,
    termination=None,        # date or tenor string ("5Y")
    frequency="q",
    leg1_currency="USD",
    leg2_currency="BRL",
    leg1_notional=1_000_000.0,
    leg2_notional=5_000_000.0,
    initial_fx_rate=5.0,
    fixed_rate=None,         # None = float-float
    notional_exchange=True,
    settlement_currency="usd",
    nd_leg=2,                # Which leg is non-deliverable (1 or 2)
    pair=None,               # FX pair (derived from currencies if None)
    fx_fixings=None,         # dict[date, float] for ALL FX fixing needs
    mtm_leg=None,            # Optional MTM notional reset leg
)

Methods

MethodSignatureReturns
rate(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates)Par basis spread on ND leg
npv(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates)NPV in settlement currency
cashflows(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates)Polars DataFrame with settlement columns
spread(leg1_disc, leg1_forecast, leg2_disc, leg2_forecast, fx_rates)Par floating spread
pillar_date()Maturity date
to_json()JSON-serializable dict
from_json(data)Reconstruct NDXCS from dict

Example

import datetime
from vade import NDXCS, DiscountCurve, FXRates

ndxcs = NDXCS(
    effective=datetime.date(2025, 6, 16),
    termination="2Y",
    leg1_currency="USD",
    leg2_currency="BRL",
    settlement_currency="usd",
    nd_leg=2,
    pair="usdbrl",
    leg1_notional=1_000_000.0,
    leg2_notional=5_000_000.0,
    initial_fx_rate=5.0,
    frequency="q",
    convention="act360",
)

usd = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2028, 6, 16): 0.89},
    interpolation="log_linear", convention="act360",
)
brl = DiscountCurve(
    {datetime.date(2025, 6, 16): 1.0, datetime.date(2028, 6, 16): 0.71},
    interpolation="log_linear", convention="act360",
)
fxr = FXRates({"usdbrl": 5.20}, settlement=datetime.date(2025, 6, 16))

rate = ndxcs.rate(usd, usd, brl, brl, fxr)
npv = ndxcs.npv(usd, usd, brl, brl, fxr)
assert abs(float(rate)) < 500
assert abs(float(npv)) < 1e8


See Also

On this page