# ---
# 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]
# # Traits market-data examples
#
# This notebook shows:
#
# - typed identifiers
# - quotes, curves, and fixings
# - reference-data records
# - pricing specs and analytics-curve bundles

# %%
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.core import Currency, Date, Frequency  # noqa: E402
from fuggers_py.engine import CurveBuilder  # noqa: E402
from fuggers_py.data import (
    BondReferenceData,
    BondType,
    CallScheduleEntry,
    CurveId,
    CurveInputs,
    CurvePoint,
    FloatingRateTerms,
    InMemoryFixingSource,
    InMemoryQuoteSource,
    IndexFixing,
    InstrumentId,
    IssuerType,
    PricingSpec,
    QuoteSide,
    RawQuote,
)

# %% [markdown]
# ## Construct typed identifiers

# %%
fixed_id = InstrumentId("SCENARIO-A-FIXED")
curve_id = CurveId("usd.discount")
fixed_id, curve_id

# %% [markdown]
# ## Construct quotes, curve inputs, and fixings

# %%
quote = RawQuote(
    instrument_id=fixed_id,
    value=Decimal("101.25"),
    side=QuoteSide.MID,
    as_of=Date.from_ymd(2026, 1, 15),
    currency=Currency.USD,
)

curve_inputs = CurveInputs.from_points(
    curve_id,
    Date.from_ymd(2026, 1, 15),
    [
        CurvePoint(Decimal("0.25"), Decimal("0.0450")),
        CurvePoint(Decimal("1.00"), Decimal("0.0435")),
        CurvePoint(Decimal("2.00"), Decimal("0.0415")),
        CurvePoint(Decimal("5.00"), Decimal("0.0395")),
        CurvePoint(Decimal("10.00"), Decimal("0.0400")),
    ],
)

fixing_source = InMemoryFixingSource(
    [
        IndexFixing("SOFR", Date.from_ymd(2026, 1, 13), Decimal("0.0410")),
        IndexFixing("SOFR", Date.from_ymd(2026, 1, 14), Decimal("0.0410")),
    ]
)

quote_source = InMemoryQuoteSource([quote])

quote_source.get_quote(fixed_id), curve_inputs.tenors(), fixing_source.get_fixing("SOFR", Date.from_ymd(2026, 1, 14))

# %% [markdown]
# ## Build reference-data objects

# %%
fixed_reference = BondReferenceData(
    instrument_id=fixed_id,
    bond_type=BondType.FIXED_RATE,
    issuer_type=IssuerType.CORPORATE,
    issue_date=Date.from_ymd(2024, 1, 15),
    maturity_date=Date.from_ymd(2031, 1, 15),
    currency=Currency.USD,
    coupon_rate=Decimal("0.0450"),
    frequency=Frequency.SEMI_ANNUAL,
    sector="CORPORATE",
    rating="A",
)

callable_reference = BondReferenceData(
    instrument_id=InstrumentId("SCENARIO-B-CALLABLE"),
    bond_type=BondType.CALLABLE,
    issuer_type=IssuerType.CORPORATE,
    issue_date=Date.from_ymd(2023, 1, 15),
    maturity_date=Date.from_ymd(2033, 1, 15),
    currency=Currency.USD,
    coupon_rate=Decimal("0.0500"),
    frequency=Frequency.SEMI_ANNUAL,
    call_schedule=(
        CallScheduleEntry(Date.from_ymd(2028, 1, 15), Decimal("100.00")),
        CallScheduleEntry(Date.from_ymd(2029, 1, 15), Decimal("100.00")),
    ),
)

frn_reference = BondReferenceData(
    instrument_id=InstrumentId("SCENARIO-C-FRN"),
    bond_type=BondType.FLOATING_RATE,
    issuer_type=IssuerType.CORPORATE,
    issue_date=Date.from_ymd(2025, 1, 15),
    maturity_date=Date.from_ymd(2028, 1, 15),
    currency=Currency.USD,
    floating_rate_terms=FloatingRateTerms(
        index_name="SOFR",
        spread=Decimal("0.0125"),
        reset_frequency=Frequency.QUARTERLY,
        current_reference_rate=Decimal("0.0410"),
    ),
)

type(fixed_reference.to_instrument()).__name__, type(callable_reference.to_instrument()).__name__, type(frn_reference.to_instrument()).__name__

# %% [markdown]
# ## Construct pricing specs and analytics curves

# %%
curve_builder = CurveBuilder()
discount_curve = curve_builder.add_zero_curve(curve_id, list(curve_inputs.points), curve_inputs.reference_date)
forward_curve = curve_builder.add_forward_curve(
    CurveId("usd.forward"),
    [
        CurvePoint(Decimal("0.25"), Decimal("0.0430")),
        CurvePoint(Decimal("0.50"), Decimal("0.0420")),
        CurvePoint(Decimal("1.00"), Decimal("0.0405")),
        CurvePoint(Decimal("2.00"), Decimal("0.0390")),
        CurvePoint(Decimal("3.00"), Decimal("0.0385")),
    ],
    Date.from_ymd(2026, 1, 15),
)

analytics_curves = AnalyticsCurves(discount_curve=discount_curve, forward_curve=forward_curve)
pricing_spec = PricingSpec(quote_side=QuoteSide.MID, compute_spreads=True, compute_key_rates=True)

pricing_spec, analytics_curves.get("discount"), analytics_curves.get("forward")
