fuggers_py.portfolio¶
Portfolio construction, aggregation, benchmark comparison, contribution, stress testing, liquidity summaries, and ETF-style outputs.
Use one-layer imports from fuggers_py.portfolio:
from fuggers_py.portfolio import Portfolio, Holding, calculate_portfolio_analytics
The public contract for this page is the fuggers_py.portfolio export list in
specs/public_api_surface.json and src/fuggers_py/portfolio/__init__.py.
The root package currently imports build_creation_basket, so direct import can
work, but that name is not in __all__ or the JSON contract. Treat it as an
importable helper outside the stable public surface.
Core Rules¶
A raw decimal means
Decimal("0.05")for 5%.A basis point is 0.01 percentage point. Fields or parameters ending in
_bpsuse basis points.Fields ending in
_pctare percentage points. For example,5means 5%.Prices are usually percent-of-par. For example, a clean price of
99.5means 99.5% of par.Currency values are in the portfolio reporting currency unless a field says otherwise.
DV01 and CS01 are currency changes for a one-basis-point move.
Portfolio weighted averages use dirty-value weights by default. Override this with
AnalyticsConfig(weighting_method=...).Benchmark active values are always portfolio minus benchmark.
In rate and spread return estimates, a positive shock means rates or spreads move up. The estimated return is usually negative when the portfolio has positive DV01 or CS01.
Most result objects are immutable records with named fields. Some also behave like mappings or sequences.
Examples below assume bond, second_bond, curve, settlement_date,
quote_outputs, and identifier objects come from the relevant bond, curve, or
quote-output pages.
Containers, Holdings, And Config¶
Holding, Position, HoldingAnalytics, PositionAnalytics¶
Holding represents one bond position. Use it when you want to attach a bond,
quantity, price or market value, analytics, and classification data to a
portfolio row.
The constructor converts quantity, market_value, accrued_interest,
liquidity_score, and fx_rate to Decimal. clean_price may be a Price
object or a decimal percent-of-par value. If analytics need a price and neither
clean_price nor market_value is present, the analytics layer needs a curve.
Useful Holding members:
par_amount: returnsquantity.market_price: returns the clean price as a percent-of-par decimal, orNone.currency: usesclassification.currencywhen present, otherwise the bond currency.name(): returnslabel, thenid, then the bond ISIN, then the bond class name.market_value_amount: returns explicitmarket_value, orclean_price * quantity, or zero.dirty_market_value: adds accrued interest times quantity to clean value.base_currency_value: returnsmarket_value_amount * fx_rate.weight_in_portfolio(total_market_value): returns clean-value weight, or zero when the total is zero.
Position is an alias for Holding. HoldingAnalytics is the per-holding
analytics record. PositionAnalytics is an alias for HoldingAnalytics.
HoldingAnalytics stores clean value, dirty value, accrued value, duration,
convexity, DV01, yields, spreads, CS01, key-rate profile, liquidity score,
weighted average life, and coupon. Values and PV fields are currency amounts.
Yields and spreads are raw decimals unless the field name says otherwise.
HoldingBuilder¶
HoldingBuilder is a mutable helper for building a Holding step by step.
build() raises ValueError if no instrument has been set.
Useful builder methods:
with_instrument(instrument)with_quantity(quantity)with_par_amount(par_amount), an alias forwith_quantity()with_clean_price(clean_price)with_market_price(market_price), an alias forwith_clean_price()with_market_value(market_value)with_accrued_interest(accrued_interest)with_analytics(analytics)with_label(label)with_id(value)with_classification(classification)with_rating_info(rating_info)with_sector_info(sector_info)with_seniority_info(seniority_info)with_liquidity_score(liquidity_score)with_fx_rate(fx_rate)build()
from decimal import Decimal
from fuggers_py import Currency
from fuggers_py.portfolio import (
Classification,
CreditRating,
HoldingBuilder,
Sector,
)
classification = Classification(
sector=Sector.CORPORATE,
rating=CreditRating.BBB,
country="US",
currency=Currency.USD,
issuer="Example Issuer",
)
holding = (
HoldingBuilder()
.with_instrument(bond)
.with_quantity(Decimal("1000000"))
.with_clean_price(Decimal("99.50"))
.with_accrued_interest(Decimal("0.75"))
.with_classification(classification)
.with_liquidity_score(Decimal("0.80"))
.with_label("EXAMPLE 5.00 2030")
.build()
)
print(holding.name())
print(holding.market_price)
print(holding.market_value_amount)
print(holding.dirty_market_value)
CashPosition¶
CashPosition represents cash inside a portfolio. amount and fx_rate are
converted to Decimal. Cash has no clean/dirty split.
Useful members:
market_value(): returns the cash amount.base_currency_value: returnsamount * fx_rate.
from decimal import Decimal
from fuggers_py import Currency
from fuggers_py.portfolio import CashPosition
cash = CashPosition(
amount=Decimal("250000"),
currency=Currency.USD,
label="operating cash",
)
print(cash.market_value())
print(cash.base_currency_value)
Portfolio, PortfolioBuilder, PortfolioMetrics¶
Portfolio is an immutable collection of bond holdings and cash positions in
one reporting currency. It stores positions in input order.
Useful Portfolio members:
Portfolio.new(positions, currency): converts a mutable list into an immutable tuple.total_quantity(): sums quantities on positions that have a quantity. Cash is ignored.holdings(): returns all positions, including cash.investable_holdings(): returns bond holdings only.cash_positions(): returns cash positions only.total_market_value(): sums clean market value for bonds and amount for cash.
PortfolioBuilder lets you add positions before creating the immutable
portfolio. with_currency() sets the reporting currency. add_position() and
add_holding() append one item. add_positions() appends many items. If no
currency is set, the first added position can set it. build() raises
ValueError if no currency was set or inferred.
PortfolioMetrics is the full portfolio analytics record. It holds clean PV,
dirty PV, accrued value, weighted duration, convexity, DV01, weights, currency,
yields, spreads, CS01, liquidity score, key-rate profile, market-value totals,
cash value, counts, duration variants, weighted average maturity, and weighted
average coupon.
from fuggers_py import Currency
from fuggers_py.portfolio import PortfolioBuilder
portfolio = (
PortfolioBuilder()
.with_currency(Currency.USD)
.add_position(holding)
.add_position(cash)
.build()
)
print(portfolio.total_quantity())
print(portfolio.total_market_value())
print([item.name() for item in portfolio.investable_holdings()])
AnalyticsConfig And WeightingMethod¶
AnalyticsConfig controls valuation date, weighting basis, key-rate tenors,
and default currency for portfolio analytics.
Fields:
settlement_date: date used for accrued interest and valuation.weighting_method: one ofDIRTY_VALUE,CLEAN_VALUE,MARKET_VALUE, orEQUAL.key_rate_tenors: tenors used to build key-rate profiles.default_currency: currency used when a default is needed.
The default weighting method is WeightingMethod.DIRTY_VALUE.
from fuggers_py.portfolio import (
AnalyticsConfig,
PortfolioAnalytics,
WeightingMethod,
)
config = AnalyticsConfig(
settlement_date=settlement_date,
weighting_method=WeightingMethod.CLEAN_VALUE,
)
metrics = PortfolioAnalytics(portfolio).metrics(
curve,
settlement_date,
config=config,
)
print(metrics.weights)
print(metrics.duration)
Classification Objects¶
These records attach grouping data to holdings.
Classification: optional sector, rating, seniority, country, currency, issuer, region, and custom fields.CreditRating: enum values fromAAAthroughD, plusNR.RatingInfo: rating plus optional agency and outlook.Sector: high-level sector enum, such asGOVERNMENT,CORPORATE,ETF,CASH, andOTHER.SectorInfo: sector plus optional issuer, country, region, and subsector.Seniority: seniority enum, such asSENIOR_SECUREDorSUBORDINATED.SeniorityInfo: seniority plussecuredboolean.RatingBucket: a label and tuple ofCreditRatingvalues.MaturityBucket: a half-open maturity range in years.
Useful methods and properties:
CreditRating.score(): lower score means stronger credit.NRreturns99.MaturityBucket.contains(years_to_maturity): checks whether a maturity is in the bucket.
from fuggers_py.portfolio import CreditRating, MaturityBucket
print(CreditRating.BBB.score())
bucket = MaturityBucket("2-5Y", 2.0, 5.0)
print(bucket.contains(3.25))
print(bucket.contains(5.0))
Risk, Yield, Spread, And Credit¶
Risk And Duration¶
RiskMetrics stores duration, modified duration, effective duration, Macaulay
duration, best duration, convexity, effective convexity, DV01, and CS01.
Functions:
calculate_risk_metrics: returnsRiskMetrics.weighted_modified_duration: returnsPortfolioMetrics.modified_duration.weighted_effective_duration: returnsPortfolioMetrics.effective_duration.weighted_macaulay_duration: returnsPortfolioMetrics.macaulay_duration.weighted_effective_convexity: returns effective convexity.weighted_best_duration: uses effective duration when present, otherwise modified duration, weighted by dirty value.
Yield¶
YieldMetrics stores YTM, YTW, YTC, current yield, and best yield as raw
decimals.
Functions:
calculate_yield_metrics: returnsYieldMetrics.weighted_best_yield: returns the portfolio best yield.
Spread¶
SpreadMetrics stores Z-spread, OAS, G-spread, I-spread, asset-swap spread,
best spread, spread duration, and CS01. Spreads are raw decimals.
Functions:
calculate_spread_metrics: returnsSpreadMetrics.weighted_z_spread,weighted_oas,weighted_g_spread,weighted_i_spread, andweighted_asw: return individual spread fields.weighted_best_spread: returns the best available spread.weighted_spread_duration: returns spread duration.
Credit Quality¶
CreditQualityMetrics stores rating distribution, sector distribution, average
rating score, average rating, investment-grade weight, high-yield weight,
default weight, unrated weight, BBB weight, BB weight, crossover weight,
quality tiers, and migration risk.
CreditMetrics is an alias for CreditQualityMetrics.
QualityTiers stores investment-grade, high-yield, distressed, defaulted, and
unrated weights.
FallenAngelRisk stores BBB weight, market value at risk, and holding count.
Its weight property returns bbb_weight.
RisingStarRisk stores BB weight, market value potential, and holding count.
Its weight property returns bb_weight.
MigrationRisk combines fallen-angel and rising-star risk. Its
crossover_weight property returns BBB weight plus BB weight.
Functions:
calculate_credit_quality: returnsCreditQualityMetrics.calculate_credit_metrics: alias forcalculate_credit_quality.calculate_migration_risk: returnsMigrationRisk.
from fuggers_py.portfolio import (
calculate_credit_quality,
calculate_risk_metrics,
calculate_spread_metrics,
calculate_yield_metrics,
weighted_best_duration,
weighted_oas,
)
risk = calculate_risk_metrics(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(risk.duration, risk.dv01)
yields = calculate_yield_metrics(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(yields.ytm, yields.best_yield)
spreads = calculate_spread_metrics(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(spreads.z_spread, spreads.cs01)
credit = calculate_credit_quality(portfolio)
print(credit.distribution)
print(credit.migration_risk.crossover_weight)
print(weighted_best_duration(portfolio, curve=curve, settlement_date=settlement_date))
print(weighted_oas(portfolio, curve=curve, settlement_date=settlement_date))
Liquidity¶
Liquidity scores are expected to be 0-to-1 decimals. Higher is more liquid.
If a holding has no liquidity score, portfolio analytics treat it as 1.
The bucket labels are fixed:
high: score >=0.75medium:0.50<= score <0.75limited:0.25<= score <0.50illiquid: score <0.25
estimate_days_to_liquidate uses a simple formula:
1 + (1 - liquidity_score) * 9, then multiplies by
liquidation_fraction. liquidation_fraction must be between 0 and 1.
Records:
LiquidityBucket: label, min score, max score, weight, dirty PV, and holding count.LiquidityDistribution: mapping from bucket label toLiquidityBucket. It supportskeys(),values(),items(),total_weight, andtotal_dirty_pv.DaysToLiquidate: days, liquidity score, and liquidation fraction. It also behaves like a mapping over its fields.LiquidityMetrics: liquidity score, bid-ask spread, days to liquidate, and distribution. It also behaves like a mapping over its fields.
Functions:
weighted_liquidity_score: weighted portfolio liquidity score.weighted_bid_ask_spread: dirty-value-weighted bid-ask spread. It readsbid_ask_spread,bid_ask, orbidask_spreadfrom holding custom fields when present.liquidity_distribution: fixed bucket distribution.estimate_days_to_liquidate: simple days estimate.calculate_liquidity_metrics: full liquidity record.
from decimal import Decimal
from fuggers_py.portfolio import (
calculate_liquidity_metrics,
estimate_days_to_liquidate,
liquidity_distribution,
)
liquidity = calculate_liquidity_metrics(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(liquidity["liquidity_score"])
print(liquidity.days_to_liquidate.days)
distribution = liquidity_distribution(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
for label, bucket in distribution.items():
print(label, bucket.weight, bucket.holding_count)
half_sale = estimate_days_to_liquidate(
portfolio,
curve=curve,
settlement_date=settlement_date,
liquidation_fraction=Decimal("0.50"),
)
print(half_sale.days)
Bucketing And Distributions¶
Bucketing helpers group holdings into named buckets. Cash is included only in
the maturity helper, where it is grouped under Cash.
Records:
MaturityDistribution: mapping from maturity bucket label to positions. It also stores the bucket definition.RatingDistribution: mapping from rating label to positions.SectorDistribution: mapping from sector label to positions.ClassifierDistribution: mapping from a named classifier to positions.CustomDistribution: mapping from a custom field to positions.BucketMetrics: alias forBucketResult.Bucketing: wrapper withbucket_dv01(curve, settlement_date, buckets=...).
Distribution objects support keys(), values(), items(), get(),
as_dict(), bucket_count, and holding_count.
Functions:
bucket_by_maturity: buckets by years to maturity usingDEFAULT_BUCKETS. Default buckets are0-2Y,2-5Y,5-10Y, and10Y+.bucket_by_rating: usesrating_info, thenclassification.rating, thenNR.bucket_by_sector: usessector_info, thenclassification.sector, thenOTHER.bucket_by_country,bucket_by_currency,bucket_by_issuer, andbucket_by_region: return plain dictionaries keyed by classification field.bucket_by_custom_field: usesholding.custom_fields, thenclassification.custom_fields, thenUNKNOWN.bucket_by_classifier: supportsrating,sector,seniority,country,region,issuer,currency, custom fields, and other classification fields. Missing values useUNKNOWN.
from fuggers_py.portfolio import (
Bucketing,
bucket_by_classifier,
bucket_by_custom_field,
bucket_by_maturity,
bucket_by_rating,
bucket_by_sector,
)
maturity = bucket_by_maturity(
portfolio,
settlement_date=settlement_date,
)
print(maturity.bucket_count)
print(maturity.holding_count)
rating = bucket_by_rating(portfolio)
for rating_label, positions in rating.items():
print(rating_label, len(positions))
sector = bucket_by_sector(portfolio)
print(sector.as_dict())
custom = bucket_by_custom_field(portfolio, "strategy")
print(custom.keys())
issuer = bucket_by_classifier(portfolio, "issuer")
print(issuer.items())
bucket_metrics = Bucketing(portfolio).bucket_dv01(
curve,
settlement_date,
)
for bucket in bucket_metrics:
print(bucket.label, bucket.dv01, bucket.average_duration)
Benchmark Comparison¶
Benchmark helpers compare two portfolios on active weights, duration, yield, spread, and risk. Active means portfolio minus benchmark.
Records:
ActiveWeight: one named active weight.valuereturnsactive_weight.as_dict()returns a simple dictionary.__getitem__supportsname,portfolio_weight,benchmark_weight,active_weight, andvalue.ActiveWeights: mapping from name to active weight. It supportskeys(),values(),items(),get(),by_name(),to_dict(),portfolio_weights,benchmark_weights, andnet_active_weight.DurationComparison: portfolio, benchmark, and active duration.RiskComparison: portfolio, benchmark, and active dirty PV and DV01.YieldComparison: portfolio, benchmark, and active current yield, YTM, and YTW.SpreadComparison: portfolio, benchmark, and active Z-spread and OAS.SectorComparison: portfolio, benchmark, and active sector weights.RatingComparison: portfolio, benchmark, and active rating weights.BenchmarkComparison: full comparison result. It exposes convenience properties for active dirty PV, duration, DV01, current yield, Z-spread, YTM, YTW, OAS, sector active weights, and rating active weights.BenchmarkMetrics: alias forBenchmarkComparison.PortfolioBenchmark: reusable pair of portfolio and benchmark.TrackingErrorEstimate: heuristic tracking-error result. It stores the total estimate and duration, spread, and dispersion components. It can be compared with decimals and hasas_decimal().
Functions:
active_weights: active holding weights.compare_portfolios: full comparison.benchmark_comparison: alias forcompare_portfolios.estimate_tracking_error: heuristic estimate from active duration, active spread, and active-weight dispersion. It is not a fitted statistical model.
Useful PortfolioBenchmark methods:
compare(curve, settlement_date)active_weights(curve, settlement_date)active_weights_by_holding(curve, settlement_date)active_weights_by_sector(curve, settlement_date)active_weights_by_rating(curve, settlement_date)aggregated_attribution(curve, settlement_date, assumptions=None)duration_difference_by_sector(curve, settlement_date)spread_difference_by_sector(curve, settlement_date)overweight_underweight_counts(curve, settlement_date)largest_active_positions(curve, settlement_date, limit=5)tracking_error_estimate(curve, settlement_date)
from fuggers_py.portfolio import (
PortfolioBenchmark,
active_weights,
compare_portfolios,
estimate_tracking_error,
)
comparison = compare_portfolios(
portfolio,
benchmark_portfolio,
curve,
settlement_date,
)
print(comparison.active_duration)
print(comparison.sector_active_weights.to_dict())
weights = active_weights(
portfolio,
benchmark_portfolio,
curve,
settlement_date,
)
for name, active_weight in weights.items():
print(name, active_weight)
pair = PortfolioBenchmark(portfolio, benchmark_portfolio)
print(pair.largest_active_positions(curve, settlement_date, limit=3))
print(pair.overweight_underweight_counts(curve, settlement_date))
tracking = estimate_tracking_error(pair, curve, settlement_date)
print(tracking.as_decimal())
print(tracking.duration_component)
Contribution And Attribution¶
Contribution helpers split portfolio values back to holdings or sectors. Attribution helpers estimate return pieces from income, rate moves, and spread moves.
The active convention is portfolio minus benchmark. Rate and spread return estimates use this first-order formula:
rate return:
-(portfolio DV01 * rate_change_bps) / dirty PVspread return:
-(portfolio CS01 * spread_change_bps) / dirty PV
Records:
Contribution: wrapper for portfolio contribution helpers.HoldingContribution: one holding contribution. Properties includecontribution,duration_contribution,dv01_contribution,spread_contribution, andcs01_contribution. It supportsas_dict()and key lookup.DurationContributions: sequence ofHoldingContributionrecords withtotal.Dv01Contributions: sequence ofHoldingContributionrecords withtotal.Cs01Contributions: sequence ofHoldingContributionrecords withtotal.SpreadContributions: alias forCs01Contributions.HoldingAttribution: holding-level PV percent, DV01 percent, and duration contribution. It supportsas_dict()and key lookup.PortfolioAttribution: sequence ofHoldingAttributionrecords. It stores total PV percent, total DV01 percent, total duration contribution, and supportsby_name(name).AttributionInput: income horizon in years, rate shock in basis points, and spread shock in basis points. It converts values toDecimaland raisesValueErrorwhenincome_horizon_yearsis negative. Itsaggregate()method calls aggregated attribution.BucketContribution: portfolio value, benchmark value, active value, and weights for one bucket.valuereturnsactive_value.SectorAttribution: mapping from sector name toBucketContribution. It supportskeys(),values(),items(),by_name(), andtotal_active.AggregatedAttribution: income, rate, spread, and total return estimates. When a benchmark is provided, benchmark and active fields are also populated.from_portfolios()is a constructor helper.
Functions:
duration_contributions: holding duration contributions weighted by dirty PV.dv01_contributions: holding DV01 contributions.spread_contributions: holding CS01 contributions.cs01_contributions: alias forspread_contributions.top_contributors: sorts contribution records or dictionaries by a selected value key.attribution_summary: holding-level PV and DV01 attribution.calculate_attribution: alias forattribution_summary.estimate_income_returns: current yield times horizon.estimate_rate_returns: first-order rate return estimate.estimate_spread_returns: first-order spread return estimate.duration_difference_by_sector: sector duration difference versus benchmark.spread_difference_by_sector: sector spread difference versus benchmark.aggregated_attribution: combined income, rate, and spread attribution.
Useful Contribution methods:
by_position(curve, settlement_date)aggregate(curve, settlement_date, assumptions=None)
from decimal import Decimal
from fuggers_py.portfolio import (
AttributionInput,
Contribution,
aggregated_attribution,
attribution_summary,
duration_contributions,
dv01_contributions,
estimate_rate_returns,
top_contributors,
)
duration = duration_contributions(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(duration.total)
print(duration.by_name("EXAMPLE 5.00 2030"))
dv01 = dv01_contributions(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
leaders = top_contributors(
dv01,
value_key="dv01_contribution",
limit=3,
absolute=True,
)
for item in leaders:
print(item.as_dict())
summary = attribution_summary(
portfolio,
curve=curve,
settlement_date=settlement_date,
)
print(summary.total_pv_pct)
print(summary.by_name("EXAMPLE 5.00 2030"))
assumptions = AttributionInput(
income_horizon_years=Decimal("1"),
rate_change_bps=Decimal("25"),
spread_change_bps=Decimal("50"),
)
aggregate = aggregated_attribution(
portfolio,
curve=curve,
settlement_date=settlement_date,
assumptions=assumptions,
benchmark=benchmark_portfolio,
)
print(aggregate.active_total_return)
wrapper = Contribution(portfolio)
print(wrapper.aggregate(curve, settlement_date, assumptions=assumptions).total_return)
rate_return = estimate_rate_returns(
portfolio,
curve=curve,
settlement_date=settlement_date,
rate_change_bps=Decimal("10"),
)
print(rate_return)
ETF Workflows¶
ETF helpers build basket summaries, NAV metrics, premium/discount metrics, SEC-yield records, and simple compliance checks.
Basket Records¶
BasketAnalysis: high-level basket summary with number of positions, sector counts, and total quantity.security_countreturnsnum_positions.BasketComponent: one security in a creation basket.BasketFlowSummary: security value, dirty value, accrued interest, cash, liabilities, total basket value, shares outstanding, and creation-unit shares.basket_per_sharereturns total basket value divided by creation-unit shares, or zero when creation-unit shares are zero.CreationBasket: ordered sequence ofBasketComponentrecords plus a flow summary. It supports iteration,len(), indexing,by_name(name),component_count, andbasket_per_share.
Functions:
analyze_etf_basket: counts portfolio positions, sector counts, and total quantity.build_creation_basket: importable fromfuggers_py.portfoliotoday, but not listed in__all__or the JSON public contract. It scales portfolio holdings to a requested creation-unit share count and requires positiveshares_outstandingandcreation_unit_shares.
from decimal import Decimal
from fuggers_py.portfolio import analyze_etf_basket, build_creation_basket
analysis = analyze_etf_basket(portfolio)
print(analysis.security_count)
print(analysis.sector_counts)
basket = build_creation_basket(
portfolio,
curve=curve,
settlement_date=settlement_date,
shares_outstanding=Decimal("1000000"),
creation_unit_shares=Decimal("50000"),
)
print(basket.component_count)
print(basket.basket_per_share)
component = basket.by_name("EXAMPLE 5.00 2030")
if component is not None:
print(component.quantity, component.weight)
SEC Yield, Distribution Yield, Expenses, And Compliance¶
Records:
SecYieldInput: inputs for standardized SEC-yield calculation.SecYield: standardized SEC-yield result.fee_waiver_impact()returns subsidized yield minus unsubsidized yield when both are available.DistributionYield: distribution yield as raw decimal, percentage points, and basis points.yield_pctreturnsdistribution_yield_pct. It also delegates numeric operations to the raw decimal value.ExpenseMetrics: gross yield, net yield, expense ratios, fee waiver ratio, annual income estimate, annual expense amount, and net assets. Propertiesexpense_drag,yield_before_expenses, andyield_after_expensesreturn the main yield pieces.ComplianceSeverity:INFO,WARNING, orCRITICAL.ComplianceCheck: one named compliance check.EtfComplianceReport: weight and issuer-limit checks.passedis true only when all checks pass.by_name(name)returns a check by name.
Functions:
calculate_sec_yield(SecYieldInput(...)): returns aSecYieldrecord.calculate_sec_yield(net_investment_income, net_assets): legacy call form. It returns a raw decimal and emits a deprecation warning.approximate_sec_yield: historical approximation as a raw decimal.calculate_distribution_yield: annual distribution divided by market price.estimate_yield_from_holdings: estimates gross and net yield from portfolio YTM and expense ratios.etf_compliance_checks: checks whether weights sum to one and whether the largest issuer weight is at or below the fixed 25% limit.
Validation:
SEC-yield average shares and maximum offering price must be positive.
Approximate SEC-yield net assets must be positive.
Distribution-yield market price must be positive.
Gross expense ratio and fee waiver ratio cannot be negative.
Issuer weight cannot be negative.
Weight sum passes when it is within
0.0001of one.
from decimal import Decimal
from fuggers_py.portfolio import (
SecYieldInput,
calculate_distribution_yield,
calculate_sec_yield,
estimate_yield_from_holdings,
etf_compliance_checks,
)
sec_input = SecYieldInput(
net_investment_income=Decimal("250000"),
average_shares_outstanding=Decimal("1000000"),
max_offering_price=Decimal("100"),
fee_waivers=Decimal("10000"),
)
sec_yield = calculate_sec_yield(sec_input)
print(sec_yield.sec_30_day_yield)
print(sec_yield.fee_waiver_impact())
distribution = calculate_distribution_yield(
annual_distribution=Decimal("4.80"),
market_price=Decimal("100"),
)
print(distribution.distribution_yield)
print(distribution.yield_pct)
expenses = estimate_yield_from_holdings(
portfolio,
curve=curve,
settlement_date=settlement_date,
gross_expense_ratio=Decimal("0.0040"),
fee_waiver_ratio=Decimal("0.0010"),
)
print(expenses.expense_drag)
print(expenses.yield_after_expenses)
report = etf_compliance_checks(
holdings_weight_sum=Decimal("1.0000"),
max_issuer_weight=Decimal("0.20"),
)
print(report.passed)
print(report.by_name("issuer_limit_ok").severity)
Quote-Output ETF Pricing¶
EtfPricer aggregates EtfHolding rows and BondQuoteOutput records into an
EtfAnalyticsOutput. It skips holdings without quotes, prices, or quantities.
It value-weights duration, convexity, and spreads by dirty value. price()
returns NAV, iNAV, per-share risk, counts, and weighted risk fields.
from decimal import Decimal
from fuggers_py.portfolio import EtfPricer
etf_output = EtfPricer().price(
etf_id="etf:demo",
holdings=etf_holdings,
quote_outputs=quote_outputs,
shares_outstanding=Decimal("1000000"),
)
print(etf_output.nav)
print(etf_output.fully_priced)
Stress¶
Stress helpers apply rate, spread, or tenor-specific shocks to portfolio analytics and return dirty-PV changes.
Records and aliases:
StressScenario: base named scenario.RateShockScenario: parallel rate shock in basis points.RateScenario: alias forRateShockScenario.SpreadShockScenario: parallel spread shock in basis points.SpreadScenario: alias forSpreadShockScenario.TenorShift: one tenor and one shock in basis points.KeyRateShiftScenario: name plus tenor-to-shock mapping.tenor_shiftsreturns typedTenorShiftrecords.from_tenor_shifts()builds a scenario from typed shifts.StressSummary: mapping from scenario name toStressResult. It supportsfrom_results(),scenario_count,aggregate_change,worst_loss,best_gain,best_case(), andworst_case().Stress: wrapper withparallel_shift(curve, settlement_date, bump_bps=...).
Functions:
rate_shock_impact: typed result for a parallel rate shock.parallel_shift_impact: alias forrate_shock_impact.spread_shock_impact: decimal dirty-PV change for a spread shock.spread_shock_result: typed result for a spread shock.key_rate_shift_impact: decimal dirty-PV change for tenor shocks.key_rate_shift_result: typed result for tenor shocks.run_stress_scenario: runs one scenario and raisesTypeErrorfor unsupported scenario types.run_stress_scenarios: runs supported scenarios and returnsStressSummary.stress_scenarios: alias forrun_stress_scenarios.standard_scenarios: returns the package standard scenarios.summarize_results: normalizes mappings or iterables intoStressSummary.best_case: best result from a result collection.worst_case: worst result from a result collection.
For rate and spread shocks, positive bump_bps usually produces a negative PV
change when the portfolio has positive DV01 or CS01.
from decimal import Decimal
from fuggers_py.portfolio import (
KeyRateShiftScenario,
RateShockScenario,
SpreadShockScenario,
Stress,
TenorShift,
run_stress_scenario,
run_stress_scenarios,
standard_scenarios,
)
rate_up = RateShockScenario(
name="+25 bps rates",
bump_bps=Decimal("25"),
)
result = run_stress_scenario(
portfolio,
curve=curve,
settlement_date=settlement_date,
scenario=rate_up,
)
print(result.actual_change)
print(result.pv_change)
key_rate = KeyRateShiftScenario.from_tenor_shifts(
name="curve twist",
shifts=[
TenorShift("2Y", Decimal("-10")),
TenorShift("10Y", Decimal("15")),
],
)
summary = run_stress_scenarios(
portfolio,
curve=curve,
settlement_date=settlement_date,
scenarios=[
rate_up,
SpreadShockScenario(name="+50 bps spreads", bump_bps=Decimal("50")),
key_rate,
],
)
print(summary.scenario_count)
print(summary.worst_loss)
print(summary.best_case())
wrapper_result = Stress(portfolio).parallel_shift(
curve,
settlement_date,
bump_bps=Decimal("10"),
)
print(wrapper_result.shocked_pv)
for scenario in standard_scenarios():
print(scenario.name)
Public Submodules¶
The package exports these module objects for users who prefer grouped imports:
analyticsbenchmarkbucketingcontributionetfliquidityriskstresstypes
User code should still prefer one-layer imports from fuggers_py.portfolio
unless it has a clear reason to import a submodule.
Boundaries¶
Bond instruments and bond analytics come from
fuggers_py.bonds.Curves come from
fuggers_py.curves.Credit instruments and CDS analytics come from
fuggers_py.credit.Rates instruments come from
fuggers_py.rates.Inflation data and inflation swaps come from
fuggers_py.inflation.Funding trades and financing analytics come from
fuggers_py.funding.
portfolio can depend on these packages because portfolio work combines many
domains. Those packages should not import from portfolio.
Fixed-income portfolio analytics and typed public result surfaces.
The package exposes the main portfolio container, typed holdings and classification helpers, and the analytics surfaces for risk, spreads, yield, liquidity, ETF, benchmark, contribution, bucketing, stress, and quote-output aggregation workflows.
The main public groups are:
analyticsfor totals, weighted metrics, NAV, and key-rate profilesbenchmarkfor active-weight and tracking-error style comparisonscontributionfor attribution and grouped risk splitsetffor basket, NAV, and compliance helpersstressfor parallel, spread, and key-rate scenario analysis
Values are expressed using the library’s fixed-income conventions: prices are
typically percent-of-par, spreads and rates are raw decimals unless a
*_bps or *_pct field states otherwise, and portfolio analytics are
settled on the valuation date passed to each helper.
- fuggers_py.portfolio.aggregate_key_rate_profile(portfolio, *, curve, settlement_date)¶
Return the portfolio key-rate DV01 profile.
- Parameters:
portfolio (
Portfolio) – Portfolio to aggregate.curve – Yield curve input used to price the holdings.
settlement_date – Valuation date used for the portfolio metrics.
- Returns:
Tenor-keyed DV01 entries in currency units per 1 bp.
- Return type:
- class fuggers_py.portfolio.AggregatedAttribution(assumptions, income_return, rate_return, spread_return, total_return, benchmark_income_return=None, benchmark_rate_return=None, benchmark_spread_return=None, benchmark_total_return=None, active_income_return=None, active_rate_return=None, active_spread_return=None, active_total_return=None, duration_by_sector=None, spread_by_sector=None)¶
Aggregated income, rate, and spread attribution outputs.
- Parameters:
assumptions (AttributionInput)
income_return (Decimal)
rate_return (Decimal)
spread_return (Decimal)
total_return (Decimal)
benchmark_income_return (Decimal | None)
benchmark_rate_return (Decimal | None)
benchmark_spread_return (Decimal | None)
benchmark_total_return (Decimal | None)
active_income_return (Decimal | None)
active_rate_return (Decimal | None)
active_spread_return (Decimal | None)
active_total_return (Decimal | None)
duration_by_sector (SectorAttribution | None)
spread_by_sector (SectorAttribution | None)
- classmethod from_portfolios(portfolio, *, curve, settlement_date, assumptions=None, benchmark=None)¶
Build aggregated attribution from one or two portfolios.
- Return type:
- Parameters:
portfolio (Portfolio)
assumptions (AttributionInput | None)
benchmark (Portfolio | None)
- class fuggers_py.portfolio.ActiveWeight(name, portfolio_weight, benchmark_weight, active_weight)¶
Active weight for a single holding or bucket.
- Parameters:
name (str)
portfolio_weight (Decimal)
benchmark_weight (Decimal)
active_weight (Decimal)
- property value: Decimal¶
Return the active weight.
- as_dict()¶
Return a mapping-style representation.
- Return type:
dict[str,Decimal|str]
- class fuggers_py.portfolio.ActiveWeights(entries, dimension='holding')¶
Collection of active weights keyed by name.
- Parameters:
entries (tuple[ActiveWeight, ...])
dimension (str)
- keys()¶
Return the active-weight names.
- Return type:
tuple[str,...]
- values()¶
Return the active-weight values.
- Return type:
tuple[Decimal,...]
- items()¶
Return
(name, active_weight)pairs.- Return type:
tuple[tuple[str,Decimal],...]
- get(key, default=None)¶
Return the active weight for
keyordefault.- Return type:
Decimal|None- Parameters:
key (str)
default (Decimal | None)
- by_name(name)¶
Return the matching entry if present.
- Return type:
ActiveWeight|None- Parameters:
name (str)
- property portfolio_weights: dict[str, Decimal]¶
Return portfolio weights by name.
- property benchmark_weights: dict[str, Decimal]¶
Return benchmark weights by name.
- property net_active_weight: Decimal¶
Return the signed sum of active weights.
- to_dict()¶
Return a plain dictionary of active weights.
- Return type:
dict[str,Decimal]
- fuggers_py.portfolio.analyze_etf_basket(portfolio)¶
Return a high-level basket analysis for the portfolio.
- Return type:
- Parameters:
portfolio (Portfolio)
- class fuggers_py.portfolio.AnalyticsConfig(settlement_date=None, weighting_method=WeightingMethod.DIRTY_VALUE, key_rate_tenors=(Tenor(length=3, unit=<TenorUnit.MONTHS: 'M'>), Tenor(length=6, unit=<TenorUnit.MONTHS: 'M'>), Tenor(length=1, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=2, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=3, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=5, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=7, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=10, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=20, unit=<TenorUnit.YEARS: 'Y'>), Tenor(length=30, unit=<TenorUnit.YEARS: 'Y'>)), default_currency=Currency.<bound method Currency.name of <Currency.USD: 'USD'>>)¶
Configuration for portfolio analytics aggregation.
The config controls the settlement date used for accrued interest, the weighting basis used for portfolio averages, and the key-rate tenors used when building tenor profiles.
- Parameters:
settlement_date (Date | None)
weighting_method (WeightingMethod)
key_rate_tenors (tuple[Tenor, ...])
default_currency (Currency)
- fuggers_py.portfolio.approximate_sec_yield(net_investment_income, net_assets)¶
Return the historical SEC-yield approximation as a raw decimal.
- Return type:
Decimal- Parameters:
net_investment_income (Decimal)
net_assets (Decimal)
- fuggers_py.portfolio.arbitrage_opportunity(portfolio, *, curve, settlement_date, shares_outstanding, market_price, liabilities=Decimal('0'), transaction_cost_bps=Decimal('0'))¶
Evaluate ETF creation or redemption arbitrage against NAV.
The result compares market price to NAV after estimated transaction costs and flags whether create or redeem is the better direction.
- Return type:
- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
market_price (Decimal)
liabilities (Decimal)
transaction_cost_bps (Decimal)
- class fuggers_py.portfolio.AttributionInput(income_horizon_years=Decimal('1'), rate_change_bps=Decimal('0'), spread_change_bps=Decimal('0'))¶
Assumptions used to scale attribution return estimates.
- Parameters:
income_horizon_years (Decimal)
rate_change_bps (Decimal)
spread_change_bps (Decimal)
- aggregate(portfolio, *, curve, settlement_date, benchmark=None)¶
Aggregate attribution using these assumptions.
- Return type:
- Parameters:
- fuggers_py.portfolio.attribution_summary(portfolio, *, curve, settlement_date)¶
Return holding-level PV and DV01 attribution.
The PV and DV01 percentages are normalized against the portfolio totals computed by the analytics layer. The duration contribution is adjusted so the holding totals reconcile to the portfolio-level duration.
- Return type:
- Parameters:
portfolio (Portfolio)
- class fuggers_py.portfolio.BasketAnalysis(num_positions, sector_counts, total_quantity)¶
High-level ETF basket summary.
- Parameters:
num_positions (int)
sector_counts (dict[str, int])
total_quantity (Decimal)
- property security_count: int¶
Return the number of securities in the basket.
- class fuggers_py.portfolio.BasketComponent(name, quantity, clean_price, dirty_price, market_value, dirty_value, accrued_interest, weight, sector=None)¶
One component in a creation basket.
- Parameters:
name (str)
quantity (Decimal)
clean_price (Decimal | None)
dirty_price (Decimal | None)
market_value (Decimal)
dirty_value (Decimal)
accrued_interest (Decimal)
weight (Decimal)
sector (str | None)
- class fuggers_py.portfolio.BasketFlowSummary(component_count, total_quantity, securities_market_value, securities_dirty_value, accrued_interest, cash_component, liabilities_component, total_basket_value, shares_outstanding, creation_unit_shares)¶
Creation-basket cash-flow summary in currency units.
- Parameters:
component_count (int)
total_quantity (Decimal)
securities_market_value (Decimal)
securities_dirty_value (Decimal)
accrued_interest (Decimal)
cash_component (Decimal)
liabilities_component (Decimal)
total_basket_value (Decimal)
shares_outstanding (Decimal)
creation_unit_shares (Decimal)
Return the basket value per ETF share.
- class fuggers_py.portfolio.BenchmarkComparison(risk, duration, yields, spread, active_weights, sector, rating)¶
Complete portfolio-versus-benchmark comparison output.
- Parameters:
risk (RiskComparison)
duration (DurationComparison)
yields (YieldComparison)
spread (SpreadComparison)
active_weights (ActiveWeights)
sector (SectorComparison)
rating (RatingComparison)
- property active_dirty_pv: Decimal¶
Return the active dirty PV.
- property active_duration: Decimal¶
Return the active duration.
- property active_dv01: Decimal¶
Return the active DV01.
- property active_current_yield: Decimal¶
Return the active current yield.
- property active_z_spread: Decimal¶
Return the active Z-spread.
- property active_ytm: Decimal¶
Return the active YTM.
- property active_ytw: Decimal¶
Return the active YTW.
- property active_oas: Decimal¶
Return the active OAS.
- property sector_active_weights: ActiveWeights¶
Return the sector active weights.
- property rating_active_weights: ActiveWeights¶
Return the rating active weights.
- fuggers_py.portfolio.BenchmarkMetrics¶
alias of
BenchmarkComparison
- fuggers_py.portfolio.best_case(results)¶
Return the best-case stress result, if any.
- Return type:
StressResult|None- Parameters:
results (StressSummary | Mapping[str, StressResult] | Iterable[StressResult])
- class fuggers_py.portfolio.BucketContribution(name, portfolio_value, benchmark_value, active_value, portfolio_weight=Decimal('0'), benchmark_weight=Decimal('0'), active_weight=Decimal('0'))¶
Portfolio-versus-benchmark contribution for a bucket.
- Parameters:
name (str)
portfolio_value (Decimal)
benchmark_value (Decimal)
active_value (Decimal)
portfolio_weight (Decimal)
benchmark_weight (Decimal)
active_weight (Decimal)
- property value: Decimal¶
Return the active value.
- fuggers_py.portfolio.BucketMetrics¶
alias of
BucketResult
- class fuggers_py.portfolio.BucketResult(label, clean_pv, dirty_pv, dv01, weight=Decimal('0'), market_value=Decimal('0'), average_ytm=None, average_duration=None, average_spread=None, holding_count=0)¶
Aggregate metrics for a single portfolio bucket.
- Parameters:
label (str)
clean_pv (Decimal)
dirty_pv (Decimal)
dv01 (Decimal)
weight (Decimal)
market_value (Decimal)
average_ytm (Decimal | None)
average_duration (Decimal | None)
average_spread (Decimal | None)
holding_count (int)
- label¶
Bucket name.
- clean_pv, dirty_pv
Aggregated clean and dirty present values in currency units.
- dv01¶
Bucket DV01 in currency units per 1 bp.
- weight¶
Bucket weight relative to the portfolio total, as a raw decimal.
- market_value¶
Clean market value proxy used by the bucketing helpers.
- average_ytm, average_duration, average_spread
Dirty-value-weighted averages, or
Nonewhen no metric is available.
- holding_count¶
Number of holdings assigned to the bucket.
- class fuggers_py.portfolio.Bucketing(portfolio)¶
Convenience wrapper for portfolio bucketing helpers.
- Parameters:
portfolio (Portfolio)
- bucket_dv01(curve, settlement_date, buckets=(('0-2Y', 0.0, 2.0), ('2-5Y', 2.0, 5.0), ('5-10Y', 5.0, 10.0), ('10Y+', 10.0, None)))¶
Return maturity buckets with PV-weighted averages.
Each bucket is keyed by the supplied maturity definition and includes clean PV, dirty PV, DV01, and dirty-value-weighted averages.
- Return type:
list[BucketResult]- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- fuggers_py.portfolio.bucket_by_classifier(portfolio, classifier_name)¶
Bucket holdings by a named classifier or custom field.
- Return type:
- Parameters:
portfolio (Portfolio)
classifier_name (str)
- fuggers_py.portfolio.bucket_by_country(portfolio)¶
Bucket holdings by country.
- fuggers_py.portfolio.bucket_by_currency(portfolio)¶
Bucket holdings by currency.
- fuggers_py.portfolio.bucket_by_custom_field(portfolio, field_name)¶
Bucket holdings by a custom field name.
- Return type:
- Parameters:
portfolio (Portfolio)
field_name (str)
- fuggers_py.portfolio.bucket_by_issuer(portfolio)¶
Bucket holdings by issuer.
- fuggers_py.portfolio.bucket_by_maturity(portfolio, *, settlement_date, buckets=(('0-2Y', 0.0, 2.0), ('2-5Y', 2.0, 5.0), ('5-10Y', 5.0, 10.0), ('10Y+', 10.0, None)))¶
Bucket holdings by time to maturity in years.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.bucket_by_rating(portfolio)¶
Bucket holdings by credit rating.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.bucket_by_region(portfolio)¶
Bucket holdings by region.
- fuggers_py.portfolio.bucket_by_sector(portfolio)¶
Bucket holdings by sector.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.calculate_attribution(portfolio, *, curve, settlement_date)¶
Compatibility alias for
attribution_summary().- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.calculate_credit_metrics(portfolio)¶
Compatibility alias for
calculate_credit_quality().- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.calculate_credit_quality(portfolio)¶
Return portfolio credit-quality metrics with typed risk fields.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.calculate_distribution_yield(annual_distribution, market_price)¶
Return distribution yield as decimal, percent, and basis points.
- Return type:
- Parameters:
annual_distribution (Decimal)
market_price (Decimal)
Return ETF NAV per share.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
liabilities (Decimal)
Return the full ETF NAV and per-share risk summary.
The output includes total NAV, NAV per share, indicative NAV, per-share DV01 and CS01, and optional premium/discount data when a market price is supplied.
- Return type:
- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
liabilities (Decimal)
market_price (Decimal | None)
Return ETF indicative NAV per share.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
- fuggers_py.portfolio.calculate_liquidity_metrics(portfolio, *, curve, settlement_date)¶
Return the standard liquidity metrics.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.calculate_migration_risk(portfolio)¶
Return the BBB and BB crossover risk for the portfolio.
- Return type:
- Parameters:
portfolio (Portfolio)
Return the portfolio NAV split into clean, dirty, and cash components.
- Parameters:
portfolio (
Portfolio) – Portfolio to aggregate.curve – Yield curve input used to price the holdings.
settlement_date – Valuation date used for the portfolio metrics.
- Returns:
Currency-unit split of clean PV, dirty PV, accrued interest, market value, dirty market value, and cash value.
- Return type:
- fuggers_py.portfolio.calculate_portfolio_analytics(portfolio, *, curve, settlement_date, config=None)¶
Return the full portfolio analytics summary.
The returned object includes the portfolio-level metrics computed by
PortfolioAnalytics.- Parameters:
portfolio (Portfolio)
config (AnalyticsConfig | None)
- fuggers_py.portfolio.calculate_risk_metrics(portfolio, *, curve, settlement_date)¶
Return the standard portfolio rate-risk metrics.
- Return type:
- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.calculate_sec_yield(input_data, net_assets=None)¶
Return either standardized SEC yield or the legacy approximation.
- Return type:
SecYield|Decimal- Parameters:
input_data (SecYieldInput | Decimal)
net_assets (Decimal | None)
- fuggers_py.portfolio.calculate_spread_metrics(portfolio, *, curve, settlement_date)¶
Return the standard portfolio spread metrics.
- Return type:
- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.calculate_yield_metrics(portfolio, *, curve, settlement_date)¶
Return the standard portfolio yield metrics.
- Return type:
- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- class fuggers_py.portfolio.CashPosition(amount, currency, label='cash', fx_rate=Decimal('1'))¶
A cash holding denominated in a portfolio currency.
The amount is treated as the position’s market value. The optional FX rate is only used when translating the cash amount into the portfolio’s base currency.
- Parameters:
amount (Decimal)
currency (Currency)
label (str)
fx_rate (Decimal)
- market_value()¶
Return the cash amount as market value.
- Return type:
Decimal
- property base_currency_value: Decimal¶
Return the cash amount translated by
fx_rate.
- class fuggers_py.portfolio.Classification(sector=None, rating=None, seniority=None, country=None, currency=None, issuer=None, region=None, custom_fields=<factory>)¶
Optional cross-sectional classification data for a holding.
The fields are used for bucketing, active-weight analysis, and custom portfolio aggregation. A field may be left unset when the information is not available at holding creation time.
- Parameters:
sector (Sector | None)
rating (CreditRating | None)
seniority (Seniority | None)
country (str | None)
currency (Currency | None)
issuer (str | None)
region (str | None)
custom_fields (dict[str, str])
- class fuggers_py.portfolio.ClassifierDistribution(classifier_name, entries)¶
Distribution keyed by a named classification dimension.
- Parameters:
classifier_name (str)
entries (dict[str, list[object]])
- fuggers_py.portfolio.compare_portfolios(portfolio, benchmark, curve, settlement_date)¶
Compare a portfolio with a benchmark on risk, yield, and spread.
- Return type:
- Parameters:
- class fuggers_py.portfolio.ComplianceCheck(name, passed, value, limit, description, severity)¶
Single ETF compliance check result.
- Parameters:
name (str)
passed (bool)
value (Decimal)
limit (Decimal)
description (str)
severity (ComplianceSeverity)
- class fuggers_py.portfolio.ComplianceSeverity(value)¶
Severity of an ETF compliance check.
- class fuggers_py.portfolio.Contribution(portfolio)¶
Convenience wrapper for portfolio contribution helpers.
- Parameters:
portfolio (Portfolio)
- by_position(curve, settlement_date)¶
Return holding-level attribution for the portfolio.
- aggregate(curve, settlement_date, *, assumptions=None)¶
Return aggregated contribution and return decomposition.
- Parameters:
assumptions (AttributionInput | None)
- class fuggers_py.portfolio.CreationBasket(components, flow_summary)¶
Ordered ETF creation basket and its flow summary.
- Parameters:
components (tuple[BasketComponent, ...])
flow_summary (BasketFlowSummary)
- by_name(name)¶
Return the basket component with
nameif present.- Return type:
BasketComponent|None- Parameters:
name (str)
- property component_count: int¶
Return the number of basket components.
Return the basket value per ETF share.
- fuggers_py.portfolio.CreditMetrics¶
alias of
CreditQualityMetrics
- class fuggers_py.portfolio.CreditQualityMetrics(distribution, sector_distribution, average_score, average_rating, investment_grade_weight, high_yield_weight, default_weight, unrated_weight, bbb_weight, bb_weight, crossover_weight, quality_tiers, migration_risk)¶
Portfolio credit-quality distribution and migration risk.
- Parameters:
distribution (dict[str, Decimal])
sector_distribution (dict[str, Decimal])
average_score (Decimal)
average_rating (object)
investment_grade_weight (Decimal)
high_yield_weight (Decimal)
default_weight (Decimal)
unrated_weight (Decimal)
bbb_weight (Decimal)
bb_weight (Decimal)
crossover_weight (Decimal)
quality_tiers (QualityTiers)
migration_risk (MigrationRisk)
- class fuggers_py.portfolio.CreditRating(value)¶
Issuer credit rating buckets.
- score()¶
Return an ordinal score where lower numbers indicate stronger credit.
- Return type:
int
- class fuggers_py.portfolio.Cs01Contributions(entries, total=Decimal('0'))¶
Holding CS01 contributions.
- Parameters:
entries (tuple[HoldingContribution, ...])
total (Decimal)
- fuggers_py.portfolio.cs01_contributions(portfolio, *, curve, settlement_date)¶
Compatibility alias for
spread_contributions().- Return type:
- Parameters:
portfolio (Portfolio)
Return ETF CS01 per share in currency units per 1 bp.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
- class fuggers_py.portfolio.CustomDistribution(field_name, entries)¶
Distribution keyed by a user-defined field name.
- Parameters:
field_name (str)
entries (dict[str, list[object]])
- class fuggers_py.portfolio.DaysToLiquidate(days, liquidity_score, liquidation_fraction=Decimal('1'))¶
Estimated days to liquidate at a given liquidation fraction.
- Parameters:
days (Decimal)
liquidity_score (Decimal)
liquidation_fraction (Decimal)
- class fuggers_py.portfolio.DistributionYield(distribution_yield, annual_distribution, market_price, distribution_yield_pct, distribution_yield_bps)¶
Distribution yield expressed as raw decimal, percent, and bps.
- Parameters:
distribution_yield (Decimal)
annual_distribution (Decimal)
market_price (Decimal)
distribution_yield_pct (Decimal)
distribution_yield_bps (Decimal)
- property yield_pct: Decimal¶
Return the distribution yield in percentage points.
- as_decimal()¶
Return the raw decimal distribution yield.
- Return type:
Decimal
- fuggers_py.portfolio.duration_contributions(portfolio, *, curve, settlement_date)¶
Return duration contributions weighted by dirty PV.
Each holding contribution is its duration multiplied by its dirty-value weight in the portfolio.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.duration_difference_by_sector(portfolio, benchmark, *, curve, settlement_date)¶
Return sector-level duration differences versus benchmark.
- Return type:
- Parameters:
- class fuggers_py.portfolio.DurationComparison(portfolio_duration, benchmark_duration, active_duration)¶
Portfolio, benchmark, and active duration values.
- Parameters:
portfolio_duration (Decimal)
benchmark_duration (Decimal)
active_duration (Decimal)
- class fuggers_py.portfolio.DurationContributions(entries, total=Decimal('0'))¶
Holding duration contributions.
- Parameters:
entries (tuple[HoldingContribution, ...])
total (Decimal)
- fuggers_py.portfolio.dv01_contributions(portfolio, *, curve, settlement_date)¶
Return holding DV01 contributions.
The contribution amount is the holding-level DV01 returned by the analytics layer.
- Return type:
- Parameters:
portfolio (Portfolio)
Return ETF DV01 per share in currency units per 1 bp.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
shares_outstanding (Decimal)
- class fuggers_py.portfolio.Dv01Contributions(entries, total=Decimal('0'))¶
Holding DV01 contributions.
- Parameters:
entries (tuple[HoldingContribution, ...])
total (Decimal)
- class fuggers_py.portfolio.EtfPricer¶
Aggregate bond quote outputs into ETF-style analytics.
- price(etf_id, holdings, quote_outputs, *, shares_outstanding)¶
Aggregate holding-level outputs into an ETF analytics record.
The pricer sums value-weighted risk outputs across holdings and returns an ETF-style analytics record with NAV, per-share metrics, and aggregation counts.
- Return type:
EtfAnalyticsOutput- Parameters:
etf_id (EtfId | str | None)
holdings (list[EtfHolding] | tuple[EtfHolding, ...])
quote_outputs (dict[InstrumentId, BondQuoteOutput])
shares_outstanding (Decimal)
- fuggers_py.portfolio.estimate_days_to_liquidate(portfolio, *, curve, settlement_date, liquidation_fraction=Decimal('1'))¶
Estimate days to liquidate for the portfolio.
- Return type:
- Parameters:
portfolio (Portfolio)
liquidation_fraction (Decimal)
- fuggers_py.portfolio.estimate_income_returns(portfolio, *, curve, settlement_date, horizon_years=None, assumptions=None)¶
Estimate income return over the provided horizon as a raw decimal.
The estimate is the portfolio current yield multiplied by the horizon in years.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
horizon_years (Decimal | None)
assumptions (AttributionInput | None)
- fuggers_py.portfolio.estimate_rate_returns(portfolio, *, curve, settlement_date, rate_change_bps=None, assumptions=None)¶
Estimate rate return from a parallel move in raw decimal terms.
The result is a first-order estimate based on portfolio DV01 and the requested rate shock.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
rate_change_bps (Decimal | None)
assumptions (AttributionInput | None)
- fuggers_py.portfolio.estimate_spread_returns(portfolio, *, curve, settlement_date, spread_change_bps=None, assumptions=None)¶
Estimate spread return from a spread move in raw decimal terms.
The result is a first-order estimate based on portfolio CS01 and the requested spread shock.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
spread_change_bps (Decimal | None)
assumptions (AttributionInput | None)
- fuggers_py.portfolio.estimate_tracking_error(benchmark, curve, settlement_date)¶
Estimate tracking error from active risk and holding dispersion.
The result combines active duration, active spread, and a simple dispersion term derived from active weights.
- Return type:
- Parameters:
benchmark (PortfolioBenchmark)
curve (DiscountingCurve)
settlement_date (Date)
- fuggers_py.portfolio.estimate_yield_from_holdings(portfolio, *, curve, settlement_date, gross_expense_ratio=Decimal('0'), fee_waiver_ratio=Decimal('0'))¶
Estimate gross and net yield after expenses from holdings.
The gross yield is based on the portfolio YTM, then adjusted by the input expense and fee-waiver ratios to produce a net-yield estimate.
- Return type:
- Parameters:
portfolio (Portfolio)
gross_expense_ratio (Decimal)
fee_waiver_ratio (Decimal)
- class fuggers_py.portfolio.EtfComplianceReport(weights_sum_to_one, issuer_limit_ok, checks)¶
Summary of ETF compliance checks.
- Parameters:
weights_sum_to_one (bool)
issuer_limit_ok (bool)
checks (tuple[ComplianceCheck, ...])
- property passed: bool¶
Return
Truewhen all checks pass.
- by_name(name)¶
Return the named compliance check if present.
- Return type:
ComplianceCheck|None- Parameters:
name (str)
ETF NAV, iNAV, and per-share risk metrics.
- Parameters:
total_nav (Decimal)
shares_outstanding (Decimal)
nav_per_share (Decimal)
dv01_per_share (Decimal)
cs01_per_share (Decimal)
securities_value (Decimal)
cash_value (Decimal)
accrued_interest (Decimal)
liabilities (Decimal)
inav (Decimal | None)
market_price (Decimal | None)
premium_discount (PremiumDiscountStats | None)
premium_discount_dollars (Decimal | None)
Return the premium or discount in percent.
Return the premium or discount in basis points.
Return
Truewhen a premium/discount value is available and positive.- Return type:
bool
Return
Truewhen a premium/discount value is available and negative.- Return type:
bool
Return the absolute premium or discount in percent.
- Return type:
Decimal|None
- fuggers_py.portfolio.etf_compliance_checks(*, holdings_weight_sum, max_issuer_weight=None)¶
Evaluate a small set of ETF compliance checks.
The checks are intentionally simple: holdings weights should sum to one, and the issuer limit must stay within the provided bound when supplied.
- Return type:
- Parameters:
holdings_weight_sum (Decimal)
max_issuer_weight (Decimal | None)
- class fuggers_py.portfolio.ExpenseMetrics(gross_yield, net_yield, gross_expense_ratio, net_expense_ratio, fee_waiver_ratio, annual_income_estimate, annual_expense_amount, net_assets)¶
Yield and expense metrics estimated from holdings.
- Parameters:
gross_yield (Decimal)
net_yield (Decimal)
gross_expense_ratio (Decimal)
net_expense_ratio (Decimal)
fee_waiver_ratio (Decimal)
annual_income_estimate (Decimal)
annual_expense_amount (Decimal)
net_assets (Decimal)
- property expense_drag: Decimal¶
Return the yield drag from expenses.
- property yield_before_expenses: Decimal¶
Return the gross yield.
- property yield_after_expenses: Decimal¶
Return the net yield.
- class fuggers_py.portfolio.FallenAngelRisk(bbb_weight, market_value_at_risk, holdings_count)¶
Weight and market value at risk from BBB holdings.
- Parameters:
bbb_weight (Decimal)
market_value_at_risk (Decimal)
holdings_count (int)
- property weight: Decimal¶
Return the BBB weight.
- class fuggers_py.portfolio.Holding(instrument, quantity=Decimal('1'), clean_price=None, market_value=None, accrued_interest=None, analytics=None, label=None, id=None, classification=None, rating_info=None, sector_info=None, seniority_info=None, liquidity_score=None, custom_fields=<factory>, fx_rate=Decimal('1'))¶
A bond holding with optional valuation and classification metadata.
The holding stores the instrument, position size, optional pricing inputs, and optional classification metadata used for portfolio aggregation. When a clean price is present, market value is derived from the price and quantity unless an explicit market value is provided.
- Parameters:
instrument (Bond)
quantity (Decimal)
clean_price (Price | Decimal | None)
market_value (Decimal | None)
accrued_interest (Decimal | None)
analytics (HoldingAnalytics | None)
label (str | None)
id (str | None)
classification (Classification | None)
rating_info (RatingInfo | None)
sector_info (SectorInfo | None)
seniority_info (SeniorityInfo | None)
liquidity_score (Decimal | None)
custom_fields (dict[str, str])
fx_rate (Decimal)
- property par_amount: Decimal¶
Return the par amount carried by the holding.
- property market_price: Decimal | None¶
Return the clean market price as a percent-of-par value.
- property currency: Currency¶
Return the holding currency, preferring explicit classification.
- name()¶
Return a stable display name for the holding.
- Return type:
str
- property market_value_amount: Decimal¶
Return the clean market value in currency units.
If an explicit market value is present it is used directly; otherwise the clean price is multiplied by the par amount.
- property dirty_market_value: Decimal¶
Return the dirty market value in currency units.
Accrued interest is added on a par-amount basis so the result is a dirty value consistent with dirty-PV aggregation.
- property base_currency_value: Decimal¶
Return the clean market value translated by
fx_rate.
- weight_in_portfolio(total_market_value)¶
Return the clean-value weight of the holding within a portfolio.
- Return type:
Decimal- Parameters:
total_market_value (Decimal)
- class fuggers_py.portfolio.HoldingAnalytics(name, market_value, dirty_value, clean_value, accrued_value, duration, convexity, dv01, ytm=None, ytw=None, ytc=None, current_yield=None, best_yield=None, z_spread=None, oas=None, g_spread=None, i_spread=None, asw=None, best_spread=None, spread_duration=None, cs01=None, modified_duration=None, effective_duration=None, macaulay_duration=None, effective_convexity=None, key_rate_profile=<factory>, liquidity_score=None, weighted_average_life=None, coupon=None)¶
Per-holding analytics expressed in currency and raw-decimal units.
The currency fields are value terms for the individual holding. Yield, spread, duration, convexity, and key-rate fields use the library’s raw decimal convention unless the field name explicitly says otherwise.
- Parameters:
name (str)
market_value (Decimal)
dirty_value (Decimal)
clean_value (Decimal)
accrued_value (Decimal)
duration (Decimal)
convexity (Decimal)
dv01 (Decimal)
ytm (Decimal | None)
ytw (Decimal | None)
ytc (Decimal | None)
current_yield (Decimal | None)
best_yield (Decimal | None)
z_spread (Decimal | None)
oas (Decimal | None)
g_spread (Decimal | None)
i_spread (Decimal | None)
asw (Decimal | None)
best_spread (Decimal | None)
spread_duration (Decimal | None)
cs01 (Decimal | None)
modified_duration (Decimal | None)
effective_duration (Decimal | None)
macaulay_duration (Decimal | None)
effective_convexity (Decimal | None)
key_rate_profile (dict[str, Decimal])
liquidity_score (Decimal | None)
weighted_average_life (Decimal | None)
coupon (Decimal | None)
- class fuggers_py.portfolio.HoldingAttribution(name, pv_pct, dv01_pct, duration_contribution)¶
Holding-level PV and DV01 attribution.
- Parameters:
name (str)
pv_pct (Decimal)
dv01_pct (Decimal)
duration_contribution (Decimal)
- as_dict()¶
Return a mapping-style representation.
- Return type:
dict[str,Decimal|str]
- class fuggers_py.portfolio.HoldingBuilder(instrument=None, quantity=Decimal('1'), clean_price=None, market_value=None, accrued_interest=None, analytics=None, label=None, id=None, classification=None, rating_info=None, sector_info=None, seniority_info=None, liquidity_score=None, custom_fields=<factory>, fx_rate=Decimal('1'))¶
Mutable builder for
Holdinginstances.- Parameters:
instrument (Bond | None)
quantity (Decimal)
clean_price (Price | Decimal | None)
market_value (Decimal | None)
accrued_interest (Decimal | None)
analytics (HoldingAnalytics | None)
label (str | None)
id (str | None)
classification (Classification | None)
rating_info (RatingInfo | None)
sector_info (SectorInfo | None)
seniority_info (SeniorityInfo | None)
liquidity_score (Decimal | None)
custom_fields (dict[str, str])
fx_rate (Decimal)
- with_instrument(instrument)¶
Set the underlying instrument.
- Return type:
- Parameters:
instrument (Bond)
- with_quantity(quantity)¶
Set the par amount or share quantity.
- Return type:
- Parameters:
quantity (object)
- with_par_amount(par_amount)¶
Compatibility alias for
with_quantity().- Return type:
- Parameters:
par_amount (object)
- with_clean_price(clean_price)¶
Set the clean price as a percent-of-par value.
- Return type:
- Parameters:
clean_price (Price | Decimal)
- with_market_price(market_price)¶
Compatibility alias for
with_clean_price().- Return type:
- Parameters:
market_price (Price | Decimal)
- with_market_value(market_value)¶
Set the clean market value in currency units.
- Return type:
- Parameters:
market_value (object)
- with_accrued_interest(accrued_interest)¶
Set accrued interest in currency units.
- Return type:
- Parameters:
accrued_interest (object)
- with_analytics(analytics)¶
Attach precomputed analytics.
- Return type:
- Parameters:
analytics (HoldingAnalytics)
- with_label(label)¶
Set the display label.
- Return type:
- Parameters:
label (str)
- with_id(value)¶
Set the stable identifier used as a fallback name.
- Return type:
- Parameters:
value (str)
- with_classification(classification)¶
Attach classification metadata.
- Return type:
- Parameters:
classification (Classification)
- with_rating_info(rating_info)¶
Attach rating metadata.
- Return type:
- Parameters:
rating_info (RatingInfo)
- with_sector_info(sector_info)¶
Attach sector metadata.
- Return type:
- Parameters:
sector_info (SectorInfo)
- with_seniority_info(seniority_info)¶
Attach seniority metadata.
- Return type:
- Parameters:
seniority_info (SeniorityInfo)
- with_liquidity_score(liquidity_score)¶
Set the liquidity score as a raw decimal.
- Return type:
- Parameters:
liquidity_score (object)
- with_fx_rate(fx_rate)¶
Set the base-currency FX conversion rate.
- Return type:
- Parameters:
fx_rate (object)
- class fuggers_py.portfolio.HoldingContribution(name, amount, metric, value_key, weight=Decimal('0'))¶
Contribution for a single holding.
- Parameters:
name (str)
amount (Decimal)
metric (str)
value_key (str)
weight (Decimal)
- property contribution: Decimal¶
Return the raw contribution amount.
- property duration_contribution: Decimal¶
Return the duration contribution when this metric is duration.
- property dv01_contribution: Decimal¶
Return the DV01 contribution when this metric is DV01.
- property spread_contribution: Decimal¶
Return the spread contribution when this metric is CS01.
- property cs01_contribution: Decimal¶
Return the CS01 contribution alias.
- as_dict()¶
Return a mapping-style representation.
- Return type:
dict[str,Decimal|str]
- class fuggers_py.portfolio.KeyRateProfile(entries)¶
Key-rate DV01 profile keyed by tenor string.
- Parameters:
entries (dict[str, Decimal])
- property total_dv01: Decimal¶
Return the sum of all tenor contributions.
- by_tenor(tenor)¶
Return the contribution for
tenorif present.- Return type:
Decimal|None- Parameters:
tenor (str)
- fuggers_py.portfolio.key_rate_shift_impact(portfolio, *, curve, settlement_date, tenor_shocks_bps)¶
Return the dirty-PV change for tenor-specific key-rate shocks.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
tenor_shocks_bps (dict[str, Decimal])
- fuggers_py.portfolio.key_rate_shift_result(portfolio, *, curve, settlement_date, tenor_shocks_bps, scenario_name=None)¶
Return a typed result for a key-rate shift scenario.
- Return type:
- Parameters:
portfolio (Portfolio)
tenor_shocks_bps (dict[str, Decimal])
scenario_name (str | None)
- class fuggers_py.portfolio.KeyRateShiftScenario(name, tenor_shocks_bps)¶
Collection of tenor-specific basis-point shocks.
- Parameters:
name (str)
tenor_shocks_bps (dict[str, Decimal])
- property tenor_shifts: tuple[TenorShift, ...]¶
Return the tenor shocks as typed objects.
- classmethod from_tenor_shifts(name, shifts)¶
Build a scenario from typed tenor shifts.
- Return type:
- Parameters:
name (str)
shifts (tuple[TenorShift, ...] | list[TenorShift])
- fuggers_py.portfolio.liquidity_distribution(portfolio, *, curve, settlement_date)¶
Return the liquidity bucket distribution.
- Return type:
- Parameters:
portfolio (Portfolio)
- class fuggers_py.portfolio.LiquidityBucket(label, min_score, max_score, weight, dirty_pv, holding_count)¶
A liquidity-score bucket with dirty-PV weight.
- Parameters:
label (str)
min_score (Decimal)
max_score (Decimal | None)
weight (Decimal)
dirty_pv (Decimal)
holding_count (int)
- class fuggers_py.portfolio.LiquidityDistribution(entries)¶
Ordered liquidity buckets keyed by label.
- Parameters:
entries (tuple[LiquidityBucket, ...])
- keys()¶
- Return type:
tuple[str,...]
- values()¶
- Return type:
tuple[LiquidityBucket,...]
- items()¶
- Return type:
tuple[tuple[str,LiquidityBucket],...]
- property total_weight: Decimal¶
Return the sum of bucket weights.
- property total_dirty_pv: Decimal¶
Return the sum of bucket dirty PV.
- class fuggers_py.portfolio.LiquidityMetrics(liquidity_score, bid_ask_spread, days_to_liquidate, distribution)¶
Portfolio liquidity summary and bucket distribution.
- Parameters:
liquidity_score (Decimal)
bid_ask_spread (Decimal)
days_to_liquidate (DaysToLiquidate)
distribution (LiquidityDistribution)
- class fuggers_py.portfolio.MaturityBucket(label, start_years, end_years)¶
A half-open maturity bucket measured in years.
- Parameters:
label (str)
start_years (float)
end_years (float | None)
- contains(years_to_maturity)¶
Return
Truewhenyears_to_maturityfalls inside the bucket.- Return type:
bool- Parameters:
years_to_maturity (float)
- class fuggers_py.portfolio.MaturityDistribution(entries, bucket_definition)¶
Distribution keyed by maturity bucket labels.
- Parameters:
entries (dict[str, list[object]])
bucket_definition (tuple[tuple[str, float, float | None], ...])
- class fuggers_py.portfolio.MigrationRisk(fallen_angel_risk, rising_star_risk, fallen_angel, rising_star)¶
Combined fallen-angel and rising-star migration risk.
- Parameters:
fallen_angel_risk (Decimal)
rising_star_risk (Decimal)
fallen_angel (FallenAngelRisk)
rising_star (RisingStarRisk)
- property crossover_weight: Decimal¶
Return the combined BBB and BB crossover weight.
Portfolio NAV components in currency units.
- Parameters:
clean_pv (Decimal)
dirty_pv (Decimal)
accrued (Decimal)
market_value (Decimal)
dirty_market_value (Decimal)
cash_value (Decimal)
- fuggers_py.portfolio.parallel_shift_impact(portfolio, *, curve, settlement_date, bump_bps, scenario_name=None)¶
Compatibility alias for
rate_shock_impact().- Return type:
- Parameters:
portfolio (Portfolio)
bump_bps (Decimal)
scenario_name (str | None)
- fuggers_py.portfolio.partial_dv01s(portfolio, *, curve, settlement_date)¶
Return the portfolio key-rate DV01 profile.
This is a compatibility alias for
aggregate_key_rate_profile().- Return type:
- Parameters:
portfolio (Portfolio)
- class fuggers_py.portfolio.Portfolio(positions, currency)¶
A currency-denominated collection of positions and cash.
- Parameters:
positions (tuple[Holding | CashPosition, ...])
currency (Currency)
- positions¶
The portfolio holdings, stored in input order.
- currency¶
Base reporting currency for portfolio-level analytics.
- classmethod new(positions, currency)¶
Build a portfolio from a mutable position list.
The input list is converted to an immutable tuple so later analytics see a stable position order.
- Return type:
- Parameters:
positions (list[Holding | CashPosition])
currency (Currency)
- total_quantity()¶
Return the sum of quantity-bearing position quantities.
Cash positions are ignored because they do not carry a par quantity.
- Return type:
Decimal
- holdings()¶
Return the raw holdings tuple, including cash positions.
- Return type:
tuple[Holding|CashPosition,...]
- investable_holdings()¶
Return the bond holdings, excluding cash positions.
- Return type:
tuple[Holding,...]
- cash_positions()¶
Return the cash positions in the portfolio.
- Return type:
tuple[CashPosition,...]
- total_market_value()¶
Return total market value in the portfolio’s base currency units.
Bond holdings contribute clean market value while cash contributes its face amount. The result is therefore a clean, portfolio-level value proxy rather than a dirty PV.
- Return type:
Decimal
- class fuggers_py.portfolio.PortfolioAnalytics(portfolio)¶
Evaluate portfolio holdings into typed analytics outputs.
The object is a thin wrapper around the portfolio plus the analytics helpers that derive per-position and portfolio-level metrics.
- Parameters:
portfolio (Portfolio)
- position_metrics(curve, settlement_date, *, config=None, spread_curve=None, oas_calculator=None)¶
Return per-position analytics for the portfolio.
- Parameters:
curve (
DiscountingCurve|None) – Valuation curve used for discounting and risk calculations.settlement_date (
Date) – Settlement or valuation date that anchors accrued interest and year-fraction conventions.config (
AnalyticsConfig|None) – Optional analytics configuration. When omitted, the portfolio currency and settlement date are used to build a default config.spread_curve (
DiscountingCurve|None) – Optional curve used for spread calculations when it differs from the valuation curve.oas_calculator (
OASCalculator|None) – Optional spread calculator override.
- Returns:
One analytics record per position in portfolio order.
- Return type:
list[PositionAnalytics]
- metrics(curve, settlement_date, *, config=None, spread_curve=None, oas_calculator=None)¶
Return portfolio-level aggregated analytics.
The totals and weighted averages are reported in the portfolio’s base currency and raw-decimal risk units. The weighting basis follows the active analytics configuration.
- Return type:
- Parameters:
curve (DiscountingCurve | None)
settlement_date (Date)
config (AnalyticsConfig | None)
spread_curve (DiscountingCurve | None)
oas_calculator (OASCalculator | None)
- class fuggers_py.portfolio.PortfolioAnalyzer¶
Aggregate bond quote outputs into portfolio analytics.
- analyze(portfolio_id, positions, quote_outputs, *, reference_data=None)¶
Aggregate positions into portfolio-level market value and risk.
Holdings without a quote are skipped. Risk metrics are value weighted by dirty value, and the output includes sector and rating breakdowns when reference data is supplied.
- Return type:
PortfolioAnalyticsOutput- Parameters:
portfolio_id (PortfolioId | str | None)
positions (list[PortfolioPosition | EtfHolding] | tuple[PortfolioPosition | EtfHolding, ...])
quote_outputs (dict[InstrumentId, BondQuoteOutput])
reference_data (dict[InstrumentId, _ReferenceDataLike] | None)
- class fuggers_py.portfolio.PortfolioAttribution(entries, total_pv_pct=Decimal('0'), total_dv01_pct=Decimal('0'), total_duration_contribution=Decimal('0'))¶
Sequence of holding-level attribution records.
- Parameters:
entries (tuple[HoldingAttribution, ...])
total_pv_pct (Decimal)
total_dv01_pct (Decimal)
total_duration_contribution (Decimal)
- by_name(name)¶
Return the named holding attribution if present.
- Return type:
HoldingAttribution|None- Parameters:
name (str)
- class fuggers_py.portfolio.PortfolioBenchmark(portfolio, benchmark)¶
Pair a portfolio with its benchmark for repeated comparisons.
- compare(curve, settlement_date)¶
Return the portfolio-versus-benchmark comparison.
- Return type:
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- active_weights(curve, settlement_date)¶
Return active holding weights.
- Return type:
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- active_weights_by_holding(curve, settlement_date)¶
Return active holding weights with holding dimension metadata.
- Return type:
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- active_weights_by_sector(curve, settlement_date)¶
Return active sector weights.
- Return type:
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- active_weights_by_rating(curve, settlement_date)¶
Return active rating weights.
- Return type:
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- aggregated_attribution(curve, settlement_date, *, assumptions=None)¶
Return aggregated attribution for the paired portfolio and benchmark.
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- duration_difference_by_sector(curve, settlement_date)¶
Return sector duration differences.
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- spread_difference_by_sector(curve, settlement_date)¶
Return sector spread differences.
- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- overweight_underweight_counts(curve, settlement_date)¶
Return overweight and underweight active-weight counts.
- Return type:
dict[str,int]- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- largest_active_positions(curve, settlement_date, *, limit=5)¶
Return the largest active positions by absolute active weight.
- Return type:
list[tuple[str,Decimal]]- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
limit (int)
- tracking_error_estimate(curve, settlement_date)¶
Return the heuristic tracking error estimate.
- Return type:
Decimal- Parameters:
curve (DiscountingCurve)
settlement_date (Date)
- class fuggers_py.portfolio.PortfolioBuilder(currency=None, _positions=<factory>)¶
Incrementally assemble a
Portfolio.- Parameters:
currency (Currency | None)
_positions (list[Holding | CashPosition])
- with_currency(currency)¶
Set the portfolio reporting currency.
- Return type:
- Parameters:
currency (Currency)
- add_position(position)¶
Append a position and infer currency from it if needed.
If the builder does not yet have a currency, it adopts the position’s currency on the first appended item.
- Return type:
- Parameters:
position (Holding | CashPosition)
- add_holding(holding)¶
Compatibility alias for
add_position().- Return type:
- Parameters:
holding (Holding | CashPosition)
- add_positions(positions)¶
Append multiple positions to the builder.
- Return type:
- Parameters:
positions (list[Holding | CashPosition])
- class fuggers_py.portfolio.PortfolioMetrics(clean_pv, dirty_pv, accrued, duration, convexity, dv01, weights, currency, current_yield=Decimal('0'), ytm=Decimal('0'), ytw=Decimal('0'), ytc=Decimal('0'), best_yield=Decimal('0'), z_spread=Decimal('0'), oas=Decimal('0'), g_spread=None, i_spread=None, asw=None, best_spread=Decimal('0'), spread_duration=Decimal('0'), cs01=Decimal('0'), liquidity_score=Decimal('0'), key_rate_profile=<factory>, total_market_value=Decimal('0'), total_dirty_market_value=Decimal('0'), total_accrued_interest=Decimal('0'), cash_value=Decimal('0'), holding_count=0, priced_count=0, coverage_count=0, modified_duration=Decimal('0'), effective_duration=Decimal('0'), macaulay_duration=Decimal('0'), effective_convexity=Decimal('0'), weighted_average_maturity=Decimal('0'), weighted_average_coupon=Decimal('0'))¶
Portfolio-level weighted metrics and totals.
All spread and rate values are raw decimals unless a name explicitly says
bpsorpctelsewhere in the API. PV and cash fields are currency amounts, while theweightsand bucket shares are raw decimals.- Parameters:
clean_pv (Decimal)
dirty_pv (Decimal)
accrued (Decimal)
duration (Decimal)
convexity (Decimal)
dv01 (Decimal)
weights (dict[str, Decimal])
currency (Currency)
current_yield (Decimal)
ytm (Decimal)
ytw (Decimal)
ytc (Decimal)
best_yield (Decimal)
z_spread (Decimal)
oas (Decimal)
g_spread (Decimal | None)
i_spread (Decimal | None)
asw (Decimal | None)
best_spread (Decimal)
spread_duration (Decimal)
cs01 (Decimal)
liquidity_score (Decimal)
key_rate_profile (dict[str, Decimal])
total_market_value (Decimal)
total_dirty_market_value (Decimal)
total_accrued_interest (Decimal)
cash_value (Decimal)
holding_count (int)
priced_count (int)
coverage_count (int)
modified_duration (Decimal)
effective_duration (Decimal)
macaulay_duration (Decimal)
effective_convexity (Decimal)
weighted_average_maturity (Decimal)
weighted_average_coupon (Decimal)
- class fuggers_py.portfolio.PortfolioPosition(instrument_id, quantity)¶
Quantity held in a single instrument.
- Parameters:
instrument_id (InstrumentId)
quantity (Decimal)
- fuggers_py.portfolio.PositionAnalytics¶
alias of
HoldingAnalytics
- class fuggers_py.portfolio.PremiumDiscountPoint(nav_per_share, market_price, shares_outstanding, premium_discount, premium_discount_dollars, estimated_edge_per_share, estimated_edge_bps, direction, is_actionable)¶
Premium/discount evaluation point with actionable edge data.
- Parameters:
nav_per_share (Decimal)
market_price (Decimal)
shares_outstanding (Decimal)
premium_discount (PremiumDiscountStats)
premium_discount_dollars (Decimal)
estimated_edge_per_share (Decimal)
estimated_edge_bps (Decimal)
direction (str)
is_actionable (bool)
Return the premium or discount in percent.
Return the premium or discount in basis points.
- class fuggers_py.portfolio.PremiumDiscountStats(premium_discount, premium_discount_bps, premium_discount_pct)¶
Portfolio premium or discount relative to NAV.
- Parameters:
premium_discount (Decimal)
premium_discount_bps (Decimal)
premium_discount_pct (Decimal)
Return the per-share premium or discount in currency units.
Return
Truewhen the market price is above NAV.
- property is_discount: bool¶
Return
Truewhen the market price is below NAV.
Compatibility alias for
premium_discount_stats().- Return type:
- Parameters:
nav (Decimal)
market_price (Decimal)
Return ETF premium or discount statistics.
- Return type:
- Parameters:
nav (Decimal)
market_price (Decimal)
- class fuggers_py.portfolio.QualityTiers(investment_grade, high_yield, distressed, defaulted, unrated)¶
Normalized credit-quality tier weights.
- Parameters:
investment_grade (Decimal)
high_yield (Decimal)
distressed (Decimal)
defaulted (Decimal)
unrated (Decimal)
- fuggers_py.portfolio.RateScenario¶
alias of
RateShockScenario
- fuggers_py.portfolio.rate_shock_impact(portfolio, *, curve, settlement_date, bump_bps, scenario_name=None)¶
Return the dirty-PV change for a parallel rate shock in bps.
- Return type:
- Parameters:
portfolio (Portfolio)
bump_bps (Decimal)
scenario_name (str | None)
- class fuggers_py.portfolio.RateShockScenario(name, bump_bps)¶
Parallel rate shock measured in basis points.
- Parameters:
name (str)
bump_bps (Decimal)
- class fuggers_py.portfolio.RatingBucket(label, ratings)¶
A named set of credit ratings used for bucketing.
- Parameters:
label (str)
ratings (tuple[CreditRating, ...])
- class fuggers_py.portfolio.RatingComparison(portfolio_weights, benchmark_weights, active_weights)¶
Portfolio, benchmark, and active rating weights.
- Parameters:
portfolio_weights (dict[str, Decimal])
benchmark_weights (dict[str, Decimal])
active_weights (ActiveWeights)
- class fuggers_py.portfolio.RatingDistribution(entries)¶
Distribution keyed by credit rating label.
- Parameters:
entries (dict[str, list[object]])
- class fuggers_py.portfolio.RatingInfo(rating, agency=None, outlook=None)¶
Rating metadata from an agency or internal source.
- Parameters:
rating (CreditRating)
agency (str | None)
outlook (str | None)
- class fuggers_py.portfolio.RiskComparison(portfolio_dirty_pv, benchmark_dirty_pv, active_dirty_pv, portfolio_dv01, benchmark_dv01, active_dv01)¶
Portfolio, benchmark, and active dirty PV and DV01 values.
- Parameters:
portfolio_dirty_pv (Decimal)
benchmark_dirty_pv (Decimal)
active_dirty_pv (Decimal)
portfolio_dv01 (Decimal)
benchmark_dv01 (Decimal)
active_dv01 (Decimal)
- class fuggers_py.portfolio.RiskMetrics(duration, modified_duration, effective_duration, macaulay_duration, best_duration, convexity, effective_convexity, dv01, cs01)¶
Portfolio rate-risk metrics expressed in raw-decimal units.
- Parameters:
duration (Decimal)
modified_duration (Decimal)
effective_duration (Decimal)
macaulay_duration (Decimal)
best_duration (Decimal)
convexity (Decimal)
effective_convexity (Decimal)
dv01 (Decimal)
cs01 (Decimal)
- class fuggers_py.portfolio.RisingStarRisk(bb_weight, market_value_potential, holdings_count)¶
Weight and market value potential from BB holdings.
- Parameters:
bb_weight (Decimal)
market_value_potential (Decimal)
holdings_count (int)
- property weight: Decimal¶
Return the BB weight.
- fuggers_py.portfolio.run_stress_scenario(portfolio, *, curve, settlement_date, scenario)¶
Run a single stress scenario and return its result.
- Return type:
- Parameters:
portfolio (Portfolio)
scenario (object)
- fuggers_py.portfolio.run_stress_scenarios(portfolio, *, curve, settlement_date, scenarios)¶
Run a list of stress scenarios and return a summary.
- Return type:
- Parameters:
portfolio (Portfolio)
scenarios (list[object])
- class fuggers_py.portfolio.Sector(value)¶
High-level issuer sector classification.
- class fuggers_py.portfolio.SectorAttribution(entries, metric, portfolio_total, benchmark_total, active_total)¶
Bucketed attribution results keyed by sector.
- Parameters:
entries (tuple[BucketContribution, ...])
metric (str)
portfolio_total (Decimal)
benchmark_total (Decimal)
active_total (Decimal)
- keys()¶
- Return type:
tuple[str,...]
- values()¶
- Return type:
tuple[BucketContribution,...]
- items()¶
- Return type:
tuple[tuple[str,BucketContribution],...]
- property total_active: Decimal¶
Return the total active contribution.
- class fuggers_py.portfolio.SectorComparison(portfolio_weights, benchmark_weights, active_weights)¶
Portfolio, benchmark, and active sector weights.
- Parameters:
portfolio_weights (dict[str, Decimal])
benchmark_weights (dict[str, Decimal])
active_weights (ActiveWeights)
- class fuggers_py.portfolio.SectorDistribution(entries)¶
Distribution keyed by sector label.
- Parameters:
entries (dict[str, list[object]])
- class fuggers_py.portfolio.SectorInfo(sector, issuer=None, country=None, region=None, subsector=None)¶
Sector metadata attached to a portfolio holding or issuer.
- Parameters:
sector (Sector)
issuer (str | None)
country (str | None)
region (str | None)
subsector (str | None)
- class fuggers_py.portfolio.SecYield(sec_30_day_yield, unsubsidized_yield, net_investment_income, average_shares_outstanding, max_offering_price, gross_expenses=None, fee_waivers=None, as_of_date=None)¶
Standardized SEC yield output and related inputs.
- Parameters:
sec_30_day_yield (Decimal)
unsubsidized_yield (Decimal | None)
net_investment_income (Decimal)
average_shares_outstanding (Decimal)
max_offering_price (Decimal)
gross_expenses (Decimal | None)
fee_waivers (Decimal | None)
as_of_date (Date | None)
- fee_waiver_impact()¶
Return the yield impact of fee waivers when available.
- Return type:
Decimal|None
- class fuggers_py.portfolio.SecYieldInput(net_investment_income, average_shares_outstanding, max_offering_price, gross_expenses=None, fee_waivers=None, as_of_date=None)¶
Inputs for the standardized SEC-yield calculation.
- Parameters:
net_investment_income (Decimal)
average_shares_outstanding (Decimal)
max_offering_price (Decimal)
gross_expenses (Decimal | None)
fee_waivers (Decimal | None)
as_of_date (Date | None)
- class fuggers_py.portfolio.Seniority(value)¶
Issuer seniority classification.
- class fuggers_py.portfolio.SeniorityInfo(seniority, secured=False)¶
Seniority metadata attached to a portfolio holding or issuer.
- Parameters:
seniority (Seniority)
secured (bool)
- class fuggers_py.portfolio.SpreadComparison(portfolio_z_spread, benchmark_z_spread, active_z_spread, portfolio_oas, benchmark_oas, active_oas)¶
Portfolio, benchmark, and active spread metrics.
- Parameters:
portfolio_z_spread (Decimal)
benchmark_z_spread (Decimal)
active_z_spread (Decimal)
portfolio_oas (Decimal)
benchmark_oas (Decimal)
active_oas (Decimal)
- fuggers_py.portfolio.spread_contributions(portfolio, *, curve, settlement_date)¶
Return holding CS01 contributions.
The contribution amount is the holding-level CS01 returned by the analytics layer.
- Return type:
- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.spread_difference_by_sector(portfolio, benchmark, *, curve, settlement_date)¶
Return sector-level spread differences versus benchmark.
- Return type:
- Parameters:
- fuggers_py.portfolio.spread_shock_impact(portfolio, *, curve, settlement_date, bump_bps)¶
Return the dirty-PV change for a parallel spread shock in bps.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
bump_bps (Decimal)
- fuggers_py.portfolio.spread_shock_result(portfolio, *, curve, settlement_date, bump_bps, scenario_name=None)¶
Return a typed result for a parallel spread shock.
- Return type:
- Parameters:
portfolio (Portfolio)
bump_bps (Decimal)
scenario_name (str | None)
- fuggers_py.portfolio.SpreadContributions¶
alias of
Cs01Contributions
- class fuggers_py.portfolio.SpreadMetrics(z_spread, oas, g_spread, i_spread, asw, best_spread, spread_duration, cs01)¶
Portfolio spread metrics expressed as raw decimals.
- Parameters:
z_spread (Decimal)
oas (Decimal)
g_spread (Decimal | None)
i_spread (Decimal | None)
asw (Decimal | None)
best_spread (Decimal)
spread_duration (Decimal)
cs01 (Decimal)
- fuggers_py.portfolio.SpreadScenario¶
alias of
SpreadShockScenario
- class fuggers_py.portfolio.SpreadShockScenario(name, bump_bps)¶
Parallel spread shock measured in basis points.
- Parameters:
name (str)
bump_bps (Decimal)
- fuggers_py.portfolio.standard_scenarios()¶
Return the standard set of illustrative stress scenarios.
- Return type:
list[StressScenario]
- class fuggers_py.portfolio.Stress(portfolio)¶
Convenience wrapper around portfolio stress helpers.
- Parameters:
portfolio (Portfolio)
- parallel_shift(curve, settlement_date, *, bump_bps)¶
Return the dirty-PV change for a parallel rate shift in bps.
- fuggers_py.portfolio.stress_scenarios(portfolio, *, curve, settlement_date, scenarios)¶
Compatibility alias for
run_stress_scenarios().- Return type:
- Parameters:
portfolio (Portfolio)
scenarios (list[object])
- class fuggers_py.portfolio.StressResult(base_dirty_pv, stressed_dirty_pv, actual_change, dv01_approximation, scenario_name=None, breakdown=<factory>)¶
Result of a stress scenario against portfolio dirty PV.
- Parameters:
base_dirty_pv (Decimal)
stressed_dirty_pv (Decimal)
actual_change (Decimal)
dv01_approximation (Decimal)
scenario_name (str | None)
breakdown (dict[str, Decimal])
- base_dirty_pv¶
Unstressed dirty present value.
- stressed_dirty_pv¶
Dirty present value after applying the scenario.
- actual_change¶
Signed PV change, where negative values indicate a loss.
- dv01_approximation¶
First-order approximation of the change, in the same currency units.
- scenario_name¶
Optional label for the scenario.
- breakdown¶
Optional per-position or per-tenor change breakdown.
- class fuggers_py.portfolio.StressScenario(name)¶
Base class for a named stress scenario.
- Parameters:
name (str)
- class fuggers_py.portfolio.StressSummary(results)¶
Mapping of scenario names to stress results.
- Parameters:
results (dict[str, StressResult])
- classmethod from_results(results)¶
Normalize a collection of stress results into a summary.
- Return type:
- Parameters:
results (StressSummary | Mapping[str, StressResult] | Iterable[StressResult])
- property scenario_count: int¶
Return the number of scenarios in the summary.
- property aggregate_change: Decimal¶
Return the sum of all scenario PV changes.
- property worst_loss: Decimal¶
Return the most negative PV change.
- property best_gain: Decimal¶
Return the most positive PV change.
- best_case()¶
Return the scenario with the largest PV change.
- Return type:
StressResult|None
- worst_case()¶
Return the scenario with the smallest PV change.
- Return type:
StressResult|None
- fuggers_py.portfolio.summarize_results(results)¶
Normalize stress results into a
StressSummary.- Return type:
- Parameters:
results (StressSummary | Mapping[str, StressResult] | Iterable[StressResult])
- class fuggers_py.portfolio.TenorShift(tenor, bump_bps)¶
A single key-rate tenor shock in basis points.
- Parameters:
tenor (str)
bump_bps (Decimal)
- fuggers_py.portfolio.total_cs01(portfolio, *, curve, settlement_date)¶
Return portfolio CS01 in currency units per 1 bp.
The value is the sum of holding-level CS01 contributions across the portfolio.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.total_dv01(portfolio, *, curve, settlement_date)¶
Return portfolio DV01 in currency units per 1 bp.
The value is the sum of holding-level DV01 contributions across the portfolio.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- class fuggers_py.portfolio.TrackingErrorEstimate(estimate, duration_component=Decimal('0'), spread_component=Decimal('0'), dispersion_component=Decimal('0'))¶
Heuristic tracking-error estimate and its components.
The estimate is a heuristic decimal value, not a statistically fitted tracking-error model.
- Parameters:
estimate (Decimal)
duration_component (Decimal)
spread_component (Decimal)
dispersion_component (Decimal)
- as_decimal()¶
Return the tracking-error estimate as a decimal.
- Return type:
Decimal
- fuggers_py.portfolio.active_weights(portfolio, benchmark, curve, settlement_date)¶
Return active holding weights for portfolio minus benchmark.
- Return type:
- Parameters:
- fuggers_py.portfolio.aggregated_attribution(portfolio, *, curve, settlement_date, assumptions=None, benchmark=None)¶
Return aggregated income, rate, and spread attribution.
When a benchmark is supplied, active attribution fields are populated as portfolio minus benchmark.
- Return type:
- Parameters:
portfolio (Portfolio)
assumptions (AttributionInput | None)
benchmark (Portfolio | None)
- fuggers_py.portfolio.benchmark_comparison(portfolio, benchmark, curve, settlement_date)¶
Compatibility alias for
compare_portfolios().- Return type:
- Parameters:
- fuggers_py.portfolio.top_contributors(contributions, *, value_key, limit=5, absolute=False)¶
Return the largest contributors ordered by the requested value key.
- Return type:
list[HoldingContribution|Mapping[str,Decimal|str]]- Parameters:
contributions (Sequence[HoldingContribution] | Sequence[Mapping[str, Decimal | str]])
value_key (str)
limit (int)
absolute (bool)
- fuggers_py.portfolio.weighted_asw(portfolio, *, curve, settlement_date)¶
Return the portfolio asset-swap spread as a raw decimal.
- Return type:
Decimal|None- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_best_duration(portfolio, *, curve, settlement_date)¶
Return the dirty-value-weighted best duration.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_best_spread(portfolio, *, curve, settlement_date)¶
Return the portfolio best spread as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_best_yield(portfolio, *, curve, settlement_date)¶
Return the portfolio best yield as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_bid_ask_spread(portfolio, *, curve, settlement_date)¶
Return the dirty-value-weighted bid/ask spread as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_convexity(portfolio, *, curve, settlement_date)¶
Return portfolio convexity as a raw decimal.
The result is the portfolio-level convexity from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_current_yield(portfolio, *, curve, settlement_date)¶
Return the portfolio current yield as a raw decimal.
The result is the portfolio-level current yield from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_duration(portfolio, *, curve, settlement_date)¶
Return portfolio duration as a raw decimal.
The result is the portfolio-level duration from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_effective_convexity(portfolio, *, curve, settlement_date)¶
Return the portfolio effective convexity as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_effective_duration(portfolio, *, curve, settlement_date)¶
Return the portfolio effective duration as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_g_spread(portfolio, *, curve, settlement_date)¶
Return the portfolio G-spread as a raw decimal.
- Return type:
Decimal|None- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_i_spread(portfolio, *, curve, settlement_date)¶
Return the portfolio I-spread as a raw decimal.
- Return type:
Decimal|None- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_liquidity_score(portfolio, *, curve, settlement_date)¶
Return the portfolio liquidity score as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_macaulay_duration(portfolio, *, curve, settlement_date)¶
Return the portfolio Macaulay duration as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_modified_duration(portfolio, *, curve, settlement_date)¶
Return the portfolio modified duration as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_oas(portfolio, *, curve, settlement_date)¶
Return the portfolio OAS as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_spread_duration(portfolio, *, curve, settlement_date)¶
Return the portfolio spread duration as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- fuggers_py.portfolio.weighted_spreads(portfolio, *, curve, settlement_date)¶
Return the portfolio Z-spread as a raw decimal.
The result is the portfolio-level Z-spread from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_ytc(portfolio, *, curve, settlement_date)¶
Return the portfolio yield to call as a raw decimal.
The result is the portfolio-level yield to call from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_ytm(portfolio, *, curve, settlement_date)¶
Return the portfolio yield to maturity as a raw decimal.
The result is the portfolio-level yield to maturity from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_ytw(portfolio, *, curve, settlement_date)¶
Return the portfolio yield to worst as a raw decimal.
The result is the portfolio-level yield to worst from the aggregated metrics.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
- fuggers_py.portfolio.weighted_z_spread(portfolio, *, curve, settlement_date)¶
Return the portfolio Z-spread as a raw decimal.
- Return type:
Decimal- Parameters:
portfolio (Portfolio)
curve (DiscountingCurve | None)
settlement_date (Date)
- class fuggers_py.portfolio.WeightingMethod(value)¶
Weighting basis used for portfolio-level aggregation.
- fuggers_py.portfolio.worst_case(results)¶
Return the worst-case stress result, if any.
- Return type:
StressResult|None- Parameters:
results (StressSummary | Mapping[str, StressResult] | Iterable[StressResult])
- class fuggers_py.portfolio.YieldComparison(portfolio_current_yield, benchmark_current_yield, active_current_yield, portfolio_ytm, benchmark_ytm, active_ytm, portfolio_ytw, benchmark_ytw, active_ytw)¶
Portfolio, benchmark, and active yield metrics.
- Parameters:
portfolio_current_yield (Decimal)
benchmark_current_yield (Decimal)
active_current_yield (Decimal)
portfolio_ytm (Decimal)
benchmark_ytm (Decimal)
active_ytm (Decimal)
portfolio_ytw (Decimal)
benchmark_ytw (Decimal)
active_ytw (Decimal)
- class fuggers_py.portfolio.YieldMetrics(ytm, ytw, ytc, current_yield, best_yield)¶
Portfolio yield metrics expressed as raw decimals.
- Parameters:
ytm (Decimal)
ytw (Decimal)
ytc (Decimal)
current_yield (Decimal)
best_yield (Decimal)