# ---
# 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]
# # Tutorial: fuggers_py.analytics.yields examples
#
# This notebook demonstrates yield analytics:
#
# - Current yield
# - Simple yield
# - Yield solver/engine roundtrips
# - Short-date thresholds
# - Money-market yield helper

# %%
# Setup cell
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"))

# %% [markdown]
# ## Imports

# %%
from fuggers_py.analytics.yields import (  # noqa: E402
    ShortDateCalculator,
    StandardYieldEngine,
    YieldSolver,
    bond_equivalent_yield,
    current_yield,
    current_yield_from_amount,
    money_market_yield,
    simple_yield,
)
from fuggers_py.bonds.instruments import FixedBondBuilder  # noqa: E402
from fuggers_py.analytics.functions import yield_to_maturity_with_convention  # noqa: E402
from fuggers_py.bonds.types import YieldCalculationRules, YieldConvention  # noqa: E402
from fuggers_py.core import Currency, Date, Frequency, Price  # noqa: E402

# %% [markdown]
# ## Build a fixed-rate bond

# %%
issue = Date.from_ymd(2015, 6, 15)
maturity = Date.from_ymd(2025, 6, 15)

bond = (
    FixedBondBuilder.new()
    .with_issue_date(issue)
    .with_maturity_date(maturity)
    .with_coupon_rate(Decimal("0.075"))
    .with_frequency(Frequency.SEMI_ANNUAL)
    .with_currency(Currency.USD)
    .with_rules(YieldCalculationRules.us_corporate())
    .build()
)

bond

# %% [markdown]
# ## Current yield (Boeing-style example)

# %%
cy = current_yield(Decimal("0.075"), Decimal("110.503"))
cy_amount = current_yield_from_amount(Decimal("7.5"), Decimal("110.503"))
cy, cy_amount

# %% [markdown]
# ## Simple yield examples

# %%
simple_discount = simple_yield(Decimal("5.0"), Decimal("95.0"), Decimal("100.0"), Decimal("5.0"))
simple_premium = simple_yield(Decimal("5.0"), Decimal("105.0"), Decimal("100.0"), Decimal("5.0"))
simple_discount, simple_premium

# %% [markdown]
# ## Yield engine roundtrip

# %%
engine = StandardYieldEngine()
settlement = Date.from_ymd(2020, 6, 15)
clean_price = Decimal("105")
accrued = bond.accrued_interest(settlement)

result = engine.yield_from_price(
    bond.cash_flows(),
    clean_price=clean_price,
    accrued=accrued,
    settlement_date=settlement,
    rules=bond.rules(),
)

roundtrip_dirty = engine.dirty_price_from_yield(
    bond.cash_flows(),
    yield_rate=result.yield_value,
    settlement_date=settlement,
    rules=bond.rules(),
)
roundtrip_clean = roundtrip_dirty - float(accrued)

result, roundtrip_clean

# %% [markdown]
# ## Yield solver (direct cashflow inputs)

# %%
solver = YieldSolver()
solver.solve(
    dirty_price=100.0,
    cashflows=[5.0, 105.0],
    times=[0.5, 1.0],
    frequency=2,
)

# %% [markdown]
# ## Short-date thresholds

# %%
short_calc = ShortDateCalculator.new()
short_calc.use_money_market_below(1 / 24), short_calc.is_short_dated(0.5), short_calc.is_short_dated(1.1)

# %% [markdown]
# ## Money-market yield helper

# %%
mm_yield = money_market_yield(100, 98, 90)
mm_yield

# %% [markdown]
# ## Convention handling (fail-fast on non-street)
#
# The analytics port supports `STREET_CONVENTION` only and will raise a
# `NotImplementedAnalytics` error for other conventions.

# %%
yield_to_maturity_with_convention(
    bond,
    Price.new(Decimal("105"), bond.currency()),
    settlement,
    YieldConvention.STREET_CONVENTION,
)
