Minimal Credit Proxy Examples¶
Two small, focused examples of the fundamentals-based credit-proxy layer:
Manual inputs — the absolute minimum accounting inputs needed for a handful of proxy metrics, entered by hand.
Cached, provider-fed inputs — the same pipeline, but starting from cached financial-statement snapshots retrieved through a
MarketTicker.
These are good starting points before the fuller workflow in notebook 04 — Credit Risk.
Setup¶
import abaquant
print(f"AbaQuant version: {abaquant.__version__}")
AbaQuant version: 1.0.0rc1
1. Manual credit-proxy inputs¶
Declare only the balance-sheet, income-statement, and cash-flow fields you
actually have, and let calculate_credit_proxy_metrics compute whatever
metrics those inputs support.
from abaquant.credit.fundamentals import (
BalanceSheetInputs,
CashFlowInputs,
CreditAnalysisInputs,
IncomeStatementInputs,
calculate_credit_proxy_metrics,
)
manual_inputs = CreditAnalysisInputs(
balance_sheet=BalanceSheetInputs(
total_debt=120.0,
total_equity=300.0,
current_assets=250.0,
current_liabilities=100.0,
cash_and_cash_equivalents=50.0,
),
income_statement=IncomeStatementInputs(
ebit=75.0,
ebitda=90.0,
interest_expense=10.0,
),
cash_flow_statement=CashFlowInputs(operating_cash_flow=70.0),
reporting_currency="USD",
reporting_period="FY2025",
)
manual_assessment = calculate_credit_proxy_metrics(manual_inputs)
manual_summary = {
"debt_to_equity": manual_assessment.metrics["debt_to_equity"],
"current_ratio": manual_assessment.metrics["current_ratio"],
"interest_coverage": manual_assessment.metrics["interest_coverage"],
"synthetic_score": manual_assessment.synthetic_credit_proxy_score,
"synthetic_band": manual_assessment.synthetic_credit_proxy_band,
}
for key, value in manual_summary.items():
print(f"{key:20s}: {value}")
debt_to_equity : 0.4
current_ratio : 2.5
interest_coverage : 7.5
synthetic_score : 94.92
synthetic_band : strong_balance_sheet_proxy
2. Cached, provider-fed credit-proxy inputs¶
Instead of typing numbers by hand, retrieve them from a MarketTicker
backed by an offline (or, in production, live) provider. The statement
snapshot is cached in memory so repeated accessor calls (total_debt(),
ebitda(), …) reuse one retrieval.
import pandas as pd
from abaquant.marketdata import get_ticker
class DeterministicMarketDataProvider:
"""Minimal offline provider supplying one cached financial snapshot."""
name = "deterministic-example"
def fast_info(self, symbol):
return {"lastPrice": 105.0}
def info(self, symbol):
return {"currency": "USD", "marketCap": 600.0, "symbol": symbol}
def history(self, symbol, **kwargs):
dates = pd.date_range("2025-01-02", periods=12, freq="B")
return pd.DataFrame({"Close": [100.0 + i for i in range(len(dates))]}, index=dates)
def history_many(self, symbols, **kwargs):
return self.history(None).reindex(columns=list(symbols), method="nearest")
def option_expirations(self, symbol):
return []
def option_chain(self, symbol, expiry):
empty = pd.DataFrame(columns=["strike", "lastPrice", "impliedVolatility"])
return empty, empty
def income_statement(self, symbol, *, period="annual"):
return pd.DataFrame({"2025-12-31": {
"Total Revenue": 450.0, "EBITDA": 90.0, "EBIT": 75.0,
"Interest Expense": 10.0, "Net Income": 60.0, "Gross Profit": 200.0,
}})
def balance_sheet(self, symbol, *, period="annual"):
return pd.DataFrame({"2025-12-31": {
"Total Debt": 120.0, "Stockholders 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,
}})
def cash_flow_statement(self, symbol, *, period="annual"):
return pd.DataFrame({"2025-12-31": {"Operating Cash Flow": 70.0}})
cached_ticker = get_ticker(
"DEMO", provider=DeterministicMarketDataProvider(), financial_cache="memory"
)
snapshot = cached_ticker.financials.snapshot(period="annual")
cached_assessment = cached_ticker.credit.assess_from_financials(period="annual")
cached_summary = {
"statement_provider": snapshot.provider_name,
"total_debt": cached_ticker.financials.total_debt(),
"ebitda": cached_ticker.financials.ebitda(),
"operating_cash_flow": cached_ticker.financials.operating_cash_flow(),
"credit_proxy_score": cached_assessment.synthetic_credit_proxy_score,
}
for key, value in cached_summary.items():
print(f"{key:20s}: {value}")
statement_provider : deterministic-example
total_debt : 120.0
ebitda : 90.0
operating_cash_flow : 70.0
credit_proxy_score : 96.34
Takeaway¶
Both paths converge on the same CreditAnalysisInputs /
calculate_credit_proxy_metrics pipeline — pick manual inputs for quick,
one-off calculations, and provider-fed inputs when you want the numbers
sourced (and cached) from a real statement pipeline.