Integrated Risk Dashboard

RiskDashboard combines a portfolio backtest, volatility risk contribution, drawdown, asset correlation, and one or more credit-proxy assessments into a single review surface — with its own .summary(), .visualize(), and .report().

Sections:

  1. Build three credit-proxy assessments (varying leverage)

  2. Build the portfolio backtest and assemble the dashboard

  3. Dashboard summary outputs

  4. Visualizations

Setup

import abaquant
print(f"AbaQuant version: {abaquant.__version__}")
AbaQuant version: 1.0.0rc1
import numpy as np
import pandas as pd

from abaquant import RiskDashboard
from abaquant.credit import (
    BalanceSheetInputs,
    CashFlowInputs,
    CreditAnalysisInputs,
    CreditHistoricalSeries,
    IncomeStatementInputs,
    MarketEquityObservation,
    PriorPeriodInputs,
    calculate_credit_proxy_metrics,
)
from abaquant.portfolio import PortfolioAllocator
from abaquant.visualization import VisualizationError

def sample_returns() -> pd.DataFrame:
    dates = pd.date_range("2025-01-02", periods=36, freq="B")
    trend = np.linspace(0.0, 1.0, len(dates))
    seasonal = np.sin(np.linspace(0.0, 4.0 * np.pi, len(dates)))
    prices = pd.DataFrame(
        {
            "ALPHA": 100.0 + 9.0 * trend + 1.8 * seasonal,
            "BETA": 82.0 + 6.0 * trend - 1.2 * seasonal,
            "GAMMA": 54.0 + 3.0 * trend + 0.7 * np.cos(np.linspace(0.0, 3.0 * np.pi, len(dates))),
        },
        index=dates,
    )
    return prices.pct_change().dropna()

1. Build three credit-proxy assessments

The same accounting inputs, scaled by a debt_multiplier, so we can put three issuers of varying leverage side by side in the dashboard.

def build_credit_assessment(debt_multiplier: float = 1.0):
    return calculate_credit_proxy_metrics(
        CreditAnalysisInputs(
            balance_sheet=BalanceSheetInputs(
                total_debt=120.0 * debt_multiplier,
                total_equity=300.0,
                current_assets=250.0,
                inventory=40.0,
                current_liabilities=100.0,
                cash_and_cash_equivalents=50.0,
                total_assets=500.0,
                total_liabilities=200.0,
                retained_earnings=110.0,
                long_term_debt=80.0 * debt_multiplier,
            ),
            income_statement=IncomeStatementInputs(
                revenue=450.0, gross_profit=200.0, ebit=75.0, ebitda=90.0,
                interest_expense=10.0, net_income=60.0,
            ),
            cash_flow_statement=CashFlowInputs(operating_cash_flow=70.0),
            prior_period=PriorPeriodInputs(
                total_assets=470.0, net_income=55.0, long_term_debt=90.0, current_assets=220.0,
                current_liabilities=105.0, shares_outstanding=100.0, gross_profit=180.0, revenue=420.0,
            ),
            market_equity=MarketEquityObservation(market_value_equity=650.0),
            historical_series=CreditHistoricalSeries(
                earnings_history=(42.0, 47.0, 53.0, 60.0),
                leverage_history=(0.60, 0.54, 0.48, 0.42),
            ),
            reporting_currency="USD",
            reporting_period="FY2025",
        )
    )

2. Build the portfolio backtest and assemble the dashboard

allocator = PortfolioAllocator(sample_returns(), annual_risk_free_rate=0.02)
backtest = allocator.backtest(
    weights="inverse_volatility",
    rebalance="monthly",
    transaction_cost_bps=5.0,
    slippage_bps=1.0,
    benchmark="equal_weight",
    lookback=10,
)

dashboard = RiskDashboard(
    allocator,
    credit_assessments={
        "ALPHA": build_credit_assessment(0.85),
        "BETA": build_credit_assessment(1.00),
        "GAMMA": build_credit_assessment(1.20),
    },
    weights=backtest.weights_history.iloc[-1],
    backtest=backtest,
)

3. Dashboard summary outputs

summary = dashboard.summary()
risk_table = dashboard.risk_contribution()
credit_table = dashboard.credit_scores()

outputs = {
    "portfolio_source": summary["portfolio"].get("source"),
    "portfolio_sharpe_ratio": summary["portfolio"].get("sharpe_ratio"),
    "largest_risk_contributor": summary["risk_contribution"].get("largest_risk_contributor"),
    "average_credit_score": summary["credit"].get("average_score"),
    "average_pairwise_correlation": summary["correlation"].get("average_pairwise_correlation"),
    "risk_contribution_rows": len(risk_table),
    "credit_score_rows": len(credit_table),
}
for key, value in outputs.items():
    print(f"{key:30s}: {value}")
portfolio_source              : backtest
portfolio_sharpe_ratio        : 27.114294107210487
largest_risk_contributor      : GAMMA
average_credit_score          : 95.34666666666668
average_pairwise_correlation  : -0.33326212181390363
risk_contribution_rows        : 3
credit_score_rows             : 3
credit_table
synthetic_credit_proxy_score synthetic_credit_proxy_band available_score_weight debt_to_equity current_ratio interest_coverage net_debt_to_ebitda altman_z_score piotroski_f_score
symbol
ALPHA 96.51 strong_balance_sheet_proxy 86.0 0.34 2.5 7.5 0.577778 4.013 None
BETA 96.51 strong_balance_sheet_proxy 86.0 0.40 2.5 7.5 0.777778 4.013 None
GAMMA 93.02 strong_balance_sheet_proxy 86.0 0.48 2.5 7.5 1.044444 4.013 None

4. Visualizations

Risk contribution, drawdown, credit scores, and asset correlation — the four panels of the dashboard.

try:
    figures = {
        "risk_contribution": dashboard.visualize(chart="risk_contribution"),
        "drawdown": dashboard.visualize(chart="drawdown"),
        "credit_scores": dashboard.visualize(chart="credit_scores"),
        "correlation": dashboard.visualize(chart="correlation"),
    }
    print(f"Created {len(figures)} figures: {list(figures)}")
except VisualizationError as exc:
    print(f"Visualization skipped (optional dependency missing): {exc}")
Created 4 figures: ['risk_contribution', 'drawdown', 'credit_scores', 'correlation']
../../_images/1f1fc162166b8cb0b099389869fab9a3ac602f4efcceec2861a09da1efbf2be0.png ../../_images/4a2740d963e71d48980f4b2c45e8beb6f4208a3905d22b0da737ccc035a3e34e.png ../../_images/12697642aedda0d44b8ca01d3add85b4aca48f0f5cc5c470184f940558f19c01.png ../../_images/43760528783a7ef4de9c3e5b23f94fac6f35271ca67292963132a5e698337a10.png

Takeaway

RiskDashboard is the formal version of the ad-hoc dashboard built in notebook 13 — Portfolio–Credit Visual Dashboard. It also exposes .report() for a one-call Markdown/HTML/PDF export — see notebook 21 — Exportable Reports.