Valuing a CLP swap under USD collateral

Consider a five-year swap that receives 5.5% fixed and pays ICP floating on 935 million CLP, with USD collateral. Its value depends on the ICP projection curve, a USD-collateralized CLP discount curve and spot FX. We value the trade in USD, then reconstruct the result from its CLP cashflows.

The local loader supplies the illustrative USD/CLP bootstrap market dated 24 February 2026. Spot is 935 CLP per USD, so the notional equals USD 1 million at inception. Run the cells in order after the shared setup.

Computational study. Canonical notebook · Companion files and setup. Download this notebook.

This page renders saved outputs; the documentation build does not execute it. Run the canonical notebook from its own directory with the checkout-built binding to reproduce the computation. Each study records its market inputs and numerical assumptions.

import pandas as pd
import quantsupport as qs
from market_data import load_currency_market

market = load_currency_market()
ref = market.quotes.reference_date
print("Market reference date:", ref)
pd.DataFrame(
    {"configured_curve": [curve.to_dict()["market_index"] for curve in market.curves]}
)
Market reference date: 2026-02-24
configured_curve
0 SOFR
1 {'Collateral': ['CLP', 'USD']}
2 ICP

FX orientation

FxStore.add(base, quote, rate) stores quote-currency units per base unit. We enter USD-to-CLP spot as 935, meaning one USD buys 935 CLP. Reverse lookup returns 1 / 935, so 9,350,000 CLP converts to 10,000 USD.

The first currency in the FX pair and the context’s valuation base currency serve different roles. Here the CSA policy selects USD for the valuation, while both contractual legs pay CLP.

fx = qs.FxStore()
fx.add(qs.Currency.USD, qs.Currency.CLP, 935.0)

clp_to_usd = fx.rate(qs.Currency.CLP, qs.Currency.USD)
usd_to_clp = fx.rate(qs.Currency.USD, qs.Currency.CLP)

pd.DataFrame(
    [
        {
            "from": "CLP",
            "to": "USD",
            "amount": 9_350_000,
            "fx_rate": clp_to_usd,
            "converted_amount": 9_350_000 * clp_to_usd,
        },
        {
            "from": "USD",
            "to": "CLP",
            "amount": 10_000,
            "fx_rate": usd_to_clp,
            "converted_amount": 10_000 * usd_to_clp,
        },
        {
            "from": "USD",
            "to": "USD",
            "amount": 10_000,
            "fx_rate": fx.rate(qs.Currency.USD, qs.Currency.USD),
            "converted_amount": 10_000 * fx.rate(qs.Currency.USD, qs.Currency.USD),
        },
    ]
)
from to amount fx_rate converted_amount
0 CLP USD 9350000 0.00107 10000.0
1 USD CLP 10000 935.00000 9350000.0
2 USD USD 10000 1.00000 10000.0

Keep projection, collateral, and reporting roles explicit

We receive a 5.5% fixed coupon and pay ICP floating coupons on a five-year swap with 935 million CLP notional, equivalent to USD 1 million at today’s spot. Both contractual legs pay CLP; matching principal flows cancel between them. The USD CSA uses SOFR as its remuneration index and selects USD as the context’s base currency.

Market object

Role

ICP curve

Project the CLP floating coupons

SOFR curve

USD collateral remuneration and bootstrap dependency

Collateral(CLP, USD) curve

Discount CLP cashflows under USD collateral

FxStore

Convert CLP amounts into USD at spot

The collateral-adjusted curve is built from FX-forward and cross-currency-swap quotes. It includes the cross-currency basis. Discounting on the ICP projection curve instead would change the collateral assumptions of the valuation.

collateral_index = qs.MarketIndex.collateral(qs.Currency.CLP, qs.Currency.USD)
swap = qs.Swap(
    identifier="CLP-SWAP-USD-CSA-5Y",
    start_date=ref,
    maturity_date=ref + "5Y",
    notional=935_000_000,
    fixed_rate=0.055,
    currency=qs.Currency.CLP,
    market_index=qs.MarketIndex.ICP,
    fixed_leg_frequency=qs.Frequency.Semiannual,
    floating_leg_frequency=qs.Frequency.Semiannual,
)
trade = qs.Trade(swap, ref, qs.Side.LongReceive)

Let the native pricer convert into the base currency

Pass both the FX store and the USD CSA policy to PricingContext. Inside with context:, valuation requests build the required curves and their dependencies. For this swap, the policy makes result.price a USD PV, although result.cashflows retains the original CLP payment amounts.

For each payment date, the pricer applies:

\[ PV_{USD} = \sum_i s_i\,CF_{CLP,i}\,S_{CLP\rightarrow USD}\, P_{CLP\mid USD}(T_i). \]

Here s_i is +1 for the received fixed leg and -1 for the paid floating leg. The cashflow table already includes these leg signs and reverses initial disbursements: for a Swap, leg 0 is fixed and leg 1 is floating. The following calculation applies discount factors and the FX rate to reconcile the native PV. All curve queries stay inside the active context; the numeric table can be used after it closes.

context = qs.PricingContext(
    quotes=market.quotes, curves=market.curves, fx=fx, csa_policy=market.csa_policy
)

with context:
    result = context.evaluate(trade, [qs.Request.Value, qs.Request.Cashflows])
    base_currency = context.base_currency
    conversion_rate = context.fx.rate(swap.currency, base_currency)
    discount_curve = context.curve(collateral_index)
    cashflows = result.cashflows.copy()
    cashflows["leg"] = cashflows["leg_index"].map(
        {0: "receive fixed", 1: "pay floating"}
    )
    cashflows["signed_amount_clp"] = cashflows["amount"]
    cashflows["discount_factor"] = cashflows["payment_date"].map(
        discount_curve.discount_factor
    )
    cashflows["pv_clp"] = cashflows["signed_amount_clp"] * cashflows["discount_factor"]
    cashflows["fx_clp_to_usd"] = conversion_rate
    cashflows["pv_usd"] = cashflows["pv_clp"] * conversion_rate

cashflows.sort_values(["payment_date", "leg_index"])[
    [
        "payment_date",
        "leg",
        "currency",
        "signed_amount_clp",
        "discount_factor",
        "fx_clp_to_usd",
        "pv_usd",
    ]
].head(8)
payment_date leg currency signed_amount_clp discount_factor fx_clp_to_usd pv_usd
0 2026-02-24 receive fixed CLP -9.350000e+08 1.000000 0.00107 -1000000.000000
12 2026-02-24 pay floating CLP 9.350000e+08 1.000000 0.00107 1000000.000000
2 2026-08-24 receive fixed CLP 2.585535e+07 0.963357 0.00107 26639.504550
14 2026-08-24 pay floating CLP -2.327727e+07 0.963357 0.00107 -23983.239411
3 2027-02-24 receive fixed CLP 2.628389e+07 0.950521 0.00107 26720.201442
15 2027-02-24 pay floating CLP -2.216951e+07 0.950521 0.00107 -22537.521210
4 2027-08-24 receive fixed CLP 2.585535e+07 0.929084 0.00107 25691.763794
16 2027-08-24 pay floating CLP -2.112135e+07 0.929084 0.00107 -20987.713675

Reconcile the position PV in both units

Summing the signed, discounted payments gives this USD-collateralized position expressed in CLP. Multiplying that amount by CLP-to-USD spot produces the native USD value. This is the same collateral agreement expressed in two currencies; valuing the swap under a CLP CSA would require a different discounting policy.

local_pv_clp = cashflows["pv_clp"].sum()
reconstructed_pv_usd = cashflows["pv_usd"].sum()

pd.DataFrame(
    [
        {
            "measure": "PV expressed in CLP under USD collateral",
            "currency": "CLP",
            "value": local_pv_clp,
        },
        {
            "measure": "Converted cashflow PV",
            "currency": "USD",
            "value": reconstructed_pv_usd,
        },
        {
            "measure": "Native result.price",
            "currency": str(base_currency),
            "value": result.price,
        },
        {
            "measure": "Reconciliation difference",
            "currency": "USD",
            "value": reconstructed_pv_usd - result.price,
        },
    ]
)
measure currency value
0 PV expressed in CLP under USD collateral CLP 4.790493e+07
1 Converted cashflow PV USD 5.123522e+04
2 Native result.price USD 5.123522e+04
3 Reconciliation difference USD -7.275958e-12

Principal exchanges

The matching fixed and floating principal exchanges have opposite signs and cancel at each date. We check that cancellation and isolate the coupon PV. Expressing the result in CLP or USD retains the same USD collateral agreement.

principal_flows = cashflows.loc[cashflows["type"].isin(["Disbursement", "Redemption"])]
principal_by_date = principal_flows.groupby("payment_date")["signed_amount_clp"].sum()
coupon_pv_usd = cashflows.loc[
    ~cashflows["type"].isin(["Disbursement", "Redemption"]), "pv_usd"
].sum()
print(f"USD-collateralized PV: CLP {local_pv_clp:,.2f} = USD {result.price:,.2f}.")
print(f"At {usd_to_clp:g} CLP per USD, one CLP is worth USD {conversion_rate:.9f}.")
print(f"Net principal PV: USD {principal_flows['pv_usd'].sum():.3e}.")
USD-collateralized PV: CLP 47,904,926.39 = USD 51,235.22.
At 935 CLP per USD, one CLP is worth USD 0.001069519.
Net principal PV: USD 0.000e+00.

The native result.price is already in USD: use it directly in a USD portfolio report. Applying CLP-to-USD FX to it again would convert twice. Retain the CLP currency labels when displaying contractual cashflows, and add separate USD columns when presenting their converted values.

Continue with portfolio valuation and risk for aggregation, or valuation catalog for the analytics available on other contracts.