# ---
# 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]
# # Callable and puttable bonds
#
# Build a bond with both issuer call rights and investor put rights, then
# inspect workout dates and yield measures.

# %%
from __future__ import annotations

import sys
from dataclasses import replace
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.instruments import CallableBondBuilder, FixedBond  # noqa: E402
from fuggers_py.bonds.types import YieldCalculationRules  # noqa: E402
from fuggers_py.core import Date, Frequency  # noqa: E402


# %% [markdown]
# ## Build the base bond and embedded option schedules

# %%
issue_date = Date.from_ymd(2024, 2, 20)
base_bond = FixedBond.new(
    issue_date=issue_date,
    maturity_date=issue_date.add_years(7),
    coupon_rate=Decimal("0.0550"),
    frequency=Frequency.ANNUAL,
    rules=replace(YieldCalculationRules.us_corporate(), frequency=Frequency.ANNUAL),
)

callable_puttable = (
    CallableBondBuilder.new()
    .with_base_bond(base_bond)
    .add_call(call_date=issue_date.add_years(3), call_price=Decimal("101.0"))
    .add_put(put_date=issue_date.add_years(2), put_price=Decimal("102.0"))
    .build()
)


# %% [markdown]
# ## Inspect the option exercise map

# %%
settlement_date = Date.from_ymd(2024, 8, 1)
{
    "first_call": callable_puttable.first_call(settlement_date),
    "first_put": callable_puttable.first_put(settlement_date),
    "workout_dates": callable_puttable.workout_dates(settlement_date),
}


# %% [markdown]
# ## Compare yield outcomes

# %%
clean_price = Decimal("101.5")
yield_snapshot = {
    "ytm": callable_puttable.yield_to_maturity(clean_price, settlement_date),
    "ytc": callable_puttable.yield_to_first_call(clean_price, settlement_date),
    "ytp": callable_puttable.yield_to_first_put(clean_price, settlement_date),
    "ytw": callable_puttable.yield_to_worst(clean_price, settlement_date),
}
yield_snapshot
