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:
Build three credit-proxy assessments (varying leverage)
Build the portfolio backtest and assemble the dashboard
Dashboard summary outputs
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']
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.