# Analytics Docs

`fuggers_py.analytics` provides bond and curve analytics on top of the core domain layers.

## Main areas

- pricing: price from yield, price from curve, yield from price
- yield analytics: current yield, simple yield, yield conventions, short-date helpers
- risk analytics: duration, convexity, DV01, hedge ratios, and key-rate helpers
- spread analytics: z-spread, g-spread, i-spread, OAS, discount margin, asset swap
- options analytics: Greek extraction and aggregation, implied-vs-realized volatility gaps, and vega-notional helpers
- reference-rate decomposition: repo-to-GC, GC-to-unsecured-overnight, unsecured-overnight-to-term ladders, and explicit ASW / basis / adjusted-CDS links
- balance-sheet overlays: haircut, capital, and shadow-cost adjustments composed additively on top of base spread measures
- YAS-style reporting helpers
- RV analytics: local rich/cheap ranking, bond switches, butterflies, constant-maturity benchmarks, new-issue fair values, basis-swapped bond views, deterministic global USD-SOFR yardsticks, and workflow hooks that turn external signals into bond selections and neutralized trade expressions

## Example

```python
from decimal import Decimal

from fuggers_py.analytics import calculate_modified_duration, yield_to_maturity
from fuggers_py.bonds import FixedBondBuilder
from fuggers_py.core import Currency, Date, Frequency, Price

settlement = Date.from_ymd(2026, 1, 15)
bond = (
    FixedBondBuilder.new()
    .with_issue_date(Date.from_ymd(2024, 1, 15))
    .with_maturity_date(Date.from_ymd(2031, 1, 15))
    .with_coupon_rate(Decimal("0.0450"))
    .with_frequency(Frequency.SEMI_ANNUAL)
    .with_currency(Currency.USD)
    .build()
)
price = Price.new(Decimal("101.25"), Currency.USD)

ytm = yield_to_maturity(bond, price, settlement)
duration = calculate_modified_duration(bond, ytm, settlement)
```

## Guidance

- Prefer one canonical implementation per calculation path.
- Import specialized analytics exceptions from `fuggers_py.analytics.errors`.
- Credit-specific spread risk such as CDS CS01 remains in `fuggers_py.credit.pricing`.
- Import specialized spread and yield helpers from their submodules when that makes call sites clearer.
- `fuggers_py.analytics.spreads` now also exposes reference-rate ladder helpers and a simple secured-unsecured overnight basis model without moving the full asset-swap product out of `fuggers_py.rates`.
- `fuggers_py.analytics.options` now layers on top of the rates-option pricers: it exposes reusable helpers such as `extract_option_greeks`, `add_option_greeks`, `scale_option_greeks`, `aggregate_option_greeks`, and lightweight RV signals such as implied-minus-realized volatility and vega notionals without moving pricing formulas into the analytics root.
- The spread-adjustment overlays are separate from the core pricers by design: haircut, capital, and shadow-cost assumptions stay parameterized in `fuggers_py.analytics.spreads.adjustments`, and the same additive overlay object can be reused for ASW, reference-rate, or global RV measures.
- Local RV analytics live under `fuggers_py.analytics.rv` and use the explicit sign convention `bp_residual = observed_yield - fair_yield`, so positive values screen cheap and negative values screen rich.
- The RV helpers can also express a non-USD bond as common-currency floating or fixed cashflows by reusing the `rates` asset-swap, same-currency basis, and cross-currency basis stack rather than duplicating pricing logic.
- The global USD SOFR yardstick helpers stay deterministic and transparent: they expose the ASW, local-basis, cross-currency-basis, and optional adjusted-CDS pieces explicitly instead of hiding them inside a statistical model.
- The RV workflow layer is intentionally thin and testable: `MaturitySignal` and `BondSignal` capture external factor or richness scores; `select_maturity_choice`, `select_bond_choice`, `bond_pair_trade`, `maturity_pair_trade`, `neutralize_choices`, and `neutralize_bond_pair` expose the leaf selection and neutrality steps directly without embedding signal estimation logic inside the library.
- Pricing functions expect bond prices in percent-of-par and generally return yields and spreads as raw decimals unless the API explicitly says percent, basis points, or currency amount.
