# ---
# 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]
# # Portfolio analytics 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.bonds.instruments import FixedBond, ZeroCouponBond  # noqa: E402
from fuggers_py.bonds.types import CreditRating, RatingInfo, Sector, SectorInfo  # noqa: E402
from fuggers_py.core import Currency, Date, Frequency  # noqa: E402
from fuggers_py.curves import DiscountCurveBuilder  # noqa: E402
from fuggers_py.portfolio import (  # noqa: E402
    AnalyticsConfig,
    Bucketing,
    CashPosition,
    Classification,
    Portfolio,
    PortfolioAnalytics,
    PortfolioBuilder,
    Position,
    Stress,
    bucket_by_sector,
    calculate_etf_nav,
    calculate_portfolio_analytics,
)

# %% [markdown]
# ## Build a small three-bond portfolio

# %%
ref = Date.from_ymd(2024, 1, 1)
curve = (
    DiscountCurveBuilder(reference_date=ref)
    .add_zero_rate(1.0, Decimal("0.03"))
    .add_zero_rate(10.0, Decimal("0.04"))
    .build()
)
portfolio = Portfolio.new(
    [
        Position(
            FixedBond.new(issue_date=ref, maturity_date=ref.add_years(3), coupon_rate=Decimal("0.04"), frequency=Frequency.SEMI_ANNUAL),
            quantity=Decimal("2"),
            label="bond_1",
        ),
        Position(
            FixedBond.new(issue_date=ref, maturity_date=ref.add_years(7), coupon_rate=Decimal("0.05"), frequency=Frequency.SEMI_ANNUAL),
            quantity=Decimal("1.5"),
            label="bond_2",
        ),
        Position(
            ZeroCouponBond(_issue_date=ref, _maturity_date=ref.add_years(2)),
            quantity=Decimal("3"),
            label="zero",
        ),
    ],
    currency=Currency.USD,
)

# %% [markdown]
# ## Portfolio PV, duration, DV01, and buckets

# %%
analytics = PortfolioAnalytics(portfolio)
metrics = analytics.metrics(curve, ref)
print("Portfolio dirty PV:", metrics.dirty_pv)
print("Portfolio duration:", metrics.duration)
print("Portfolio DV01:", metrics.dv01)
print("Portfolio weights:", metrics.weights)

print("\nBucket exposures:")
for bucket in Bucketing(portfolio).bucket_dv01(curve, ref):
    print(bucket)

# %% [markdown]
# ## Parallel +10bp stress and DV01 comparison

# %%
stress = Stress(portfolio).parallel_shift(curve, ref, bump_bps=Decimal("10"))
print("Stress result:", stress)

# %% [markdown]
# ## Upstream-style holdings, sector buckets, and ETF NAV

# %%
builder = PortfolioBuilder().with_currency(Currency.USD)
builder.add_position(
    Position(
        FixedBond.new(issue_date=ref, maturity_date=ref.add_years(4), coupon_rate=Decimal("0.045"), frequency=Frequency.SEMI_ANNUAL),
        quantity=Decimal("1.25"),
        label="corp_credit",
        classification=Classification(sector=Sector.CORPORATE, rating=CreditRating.BBB, currency=Currency.USD),
        rating_info=RatingInfo(rating=CreditRating.BBB),
        sector_info=SectorInfo(sector=Sector.CORPORATE),
        liquidity_score=Decimal("0.75"),
    )
)
builder.add_position(
    Position(
        FixedBond.new(issue_date=ref, maturity_date=ref.add_years(8), coupon_rate=Decimal("0.05"), frequency=Frequency.SEMI_ANNUAL),
        quantity=Decimal("0.8"),
        label="gov_duration",
        classification=Classification(sector=Sector.GOVERNMENT, rating=CreditRating.AA, currency=Currency.USD),
        rating_info=RatingInfo(rating=CreditRating.AA),
        sector_info=SectorInfo(sector=Sector.GOVERNMENT),
        liquidity_score=Decimal("0.95"),
    )
)
builder.add_position(CashPosition(amount=Decimal("25"), currency=Currency.USD))
portfolio_v2 = builder.build()

summary = calculate_portfolio_analytics(portfolio_v2, curve=curve, settlement_date=ref, config=AnalyticsConfig(settlement_date=ref))
print("Sector buckets:", {k: len(v) for k, v in bucket_by_sector(portfolio_v2).items()})
print("Portfolio summary:", summary)
print("ETF NAV per share:", calculate_etf_nav(portfolio_v2, curve=curve, settlement_date=ref, shares_outstanding=Decimal("10")))
