# ---
# 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]
# # OAS examples

# %%
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.analytics.spreads import OASCalculator  # noqa: E402
from fuggers_py.bonds.instruments import CallType, CallableBondBuilder, FixedBond  # noqa: E402
from fuggers_py.bonds.options import HullWhiteModel  # noqa: E402
from fuggers_py.core import Date, Frequency  # noqa: E402
from fuggers_py.curves import DiscountCurveBuilder  # noqa: E402

# %% [markdown]
# ## Build a callable bond and discount curve

# %%
settlement = Date.from_ymd(2024, 1, 1)
base_bond = FixedBond.new(
    issue_date=settlement,
    maturity_date=settlement.add_years(5),
    coupon_rate=Decimal("0.05"),
    frequency=Frequency.SEMI_ANNUAL,
)
callable_bond = (
    CallableBondBuilder.new()
    .with_base_bond(base_bond)
    .add_call(call_date=settlement.add_years(2), call_price=Decimal("101.00"), call_type=CallType.EUROPEAN)
    .add_call(call_date=settlement.add_years(3), call_price=Decimal("100.50"), call_type=CallType.EUROPEAN)
    .build()
)
curve = (
    DiscountCurveBuilder(reference_date=settlement)
    .add_zero_rate(1.0, Decimal("0.04"))
    .add_zero_rate(10.0, Decimal("0.04"))
    .build()
)

# %% [markdown]
# ## Build the Hull-White model and OAS calculator

# %%
model = HullWhiteModel(mean_reversion=Decimal("0.03"), volatility=Decimal("0.01"), term_structure=curve)
calculator = OASCalculator(model=model)

# %% [markdown]
# ## Compute OAS and option risk measures

# %%
market_price = Decimal("101.47670133056229")
oas = calculator.calculate(callable_bond, market_price, settlement)
print("OAS:", oas)
print("Price from OAS:", calculator.price_with_oas(callable_bond, oas, settlement))
print("Effective duration:", calculator.effective_duration(callable_bond, oas, settlement))
print("Effective convexity:", calculator.effective_convexity(callable_bond, oas, settlement))
print("Option value:", calculator.option_value(callable_bond, oas, settlement))
