# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:percent
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.19.1
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# %% [markdown]
# # Curve calibration
#
# Bootstrap a discount curve from a compact set of money-market and swap quotes,
# then inspect the resulting fit and implied zero rates.

# %%
from __future__ import annotations

import sys
from decimal import Decimal
from pathlib import Path

root = Path.cwd()
if (root / "src").exists():
    sys.path.insert(0, str(root / "src"))
elif (root.parent / "src").exists():
    sys.path.insert(0, str(root.parent / "src"))

from fuggers_py.bonds.types import Tenor  # noqa: E402
from fuggers_py.core import Date, Frequency  # noqa: E402
from fuggers_py.curves import (  # noqa: E402
    Deposit,
    InstrumentSet,
    Ois,
    SequentialBootstrapper,
    Swap,
    ValueTypeKind,
)


# %% [markdown]
# ## Build the calibration set

# %%
reference_date = Date.from_ymd(2024, 1, 2)
instruments = InstrumentSet(
    [
        Deposit(reference_date=reference_date, tenor=Tenor.parse("1M"), quote=Decimal("0.0510")),
        Deposit(reference_date=reference_date, tenor=Tenor.parse("3M"), quote=Decimal("0.0520")),
        Ois(reference_date=reference_date, tenor=Tenor.parse("1Y"), quote=Decimal("0.0495")),
        Swap(
            reference_date=reference_date,
            tenor=Tenor.parse("2Y"),
            quote=Decimal("0.0460"),
            fixed_frequency=Frequency.SEMI_ANNUAL,
        ),
        Swap(
            reference_date=reference_date,
            tenor=Tenor.parse("5Y"),
            quote=Decimal("0.0430"),
            fixed_frequency=Frequency.SEMI_ANNUAL,
        ),
    ]
)
[instrument.maturity_date() for instrument in instruments.instruments]


# %% [markdown]
# ## Bootstrap and inspect the fit

# %%
bootstrapper = SequentialBootstrapper(
    reference_date=reference_date,
    instruments=instruments,
    value_type_kind=ValueTypeKind.DISCOUNT_FACTOR,
)
result = bootstrapper.bootstrap()

fit_table = [
    {
        "maturity": item.instrument.maturity_date(),
        "market_quote": item.market_quote,
        "model_quote": item.model_quote,
        "residual": item.residual,
    }
    for item in result.instrument_results
]
fit_table


# %% [markdown]
# ## Query calibrated discount factors and zero rates

# %%
curve = result.curve
query_dates = [
    reference_date.add_months(6),
    reference_date.add_years(1),
    reference_date.add_years(3),
    reference_date.add_years(5),
]
curve_snapshot = [
    {
        "date": date,
        "discount_factor": curve.discount_factor(date),
        "zero_rate": curve.zero_rate(date).value(),
    }
    for date in query_dates
]
curve_snapshot
