Skip to main content

sbic-tracker

PyPI version Python 3.9+ License: MIT

SBIC investment portfolio analyzer for Python.

Model and analyze Small Business Investment Company (SBIC) portfolios: fund-level IRR, TVPI, DPI, RVPI, vintage-year cohort analysis, peer benchmarking, and sector/state concentration — all built on pure Python with no external dependencies.


⚠️ Unmaintained — and it has no live data source

Read this before installing.

  • This package is not currently maintained. No live SBA data source is planned. It is published with the PyPI classifier Development Status :: 7 - Inactive.
  • Live SBA data loading is not implemented. load_from_sba_url() raises SBADownloadError. There is no SBA data in this package and never was.
  • The package returns sample data only when you explicitly ask for it, via load_sample_licensees() / load_sample_investments().

What 0.1.0 did

load_from_sba_url() claimed in its own docstring to load live SBA data. It could not do so by any path: the CKAN resource_id in its URL was a hand-typed placeholder that returns 404, the request was wrapped in except Exception: pass, and the success branch was return [] # would parse live records here. Every caller silently received load_sample_licensees() — invented fund names, invented license dates, invented dollar amounts — labelled as SBA program data. Fund-level IRR, TVPI and DPI computed downstream were arithmetic on fiction.

A fabricated positive is worse than a fabricated negative: an empty result is visibly unhelpful, whereas a fully populated portfolio of plausible fake companies reads as a successful data load.

What 0.2.0 does

from sbictracker import load_from_sba_url, load_sample_licensees, SBADownloadError

load_from_sba_url()          # raises SBADownloadError, always. No request is made.

licensees = load_sample_licensees()          # demo data, explicitly
licensees[0].data_source                     # "sample"

Every SBICLicensee and Investment now carries a data_source marker — "sample" for records from the demo loaders, "user" for records you construct yourself. Check it before reporting any figure derived from these records.

The example notebook was removed in 0.2.0

examples/sbic_portfolio_demo.ipynb is deleted. It was written against an API this package never had — LICENSE_TYPES.keys() on a list, SBICPortfolio.count() / .total_invested / .filter_state() / .filter_sector() (the real names are len(), summary_stats(), filter_by_state(), filter_by_sector()), irr(investments) where irr takes a List[float], and vintage_year_analysis / sector_breakdown / state_breakdown treated as returning DataFrames when they return dict. 8 of its 10 code cells raised.

It was deleted rather than repaired: this package is unmaintained, so a demo notebook is an artifact that rots with nobody tending it, and the Quickstart below covers every working feature. Every line of that Quickstart — including the summary() output block — is executed and verified against the shipped code before release.

What still works

All of the financial machinery. irr, tvpi, dpi, rvpi, vintage_year_analysis, peer_quartile_ranking, sector_breakdown, SBICPortfolio — these are real, tested arithmetic that operate on whatever Investment records you supply. If you have your own SBIC data, this package will analyze it correctly. What it will not do is fetch that data for you.


Why sbic-tracker?

SBICs deploy over $6 billion annually into U.S. small businesses through SBA-leveraged funds. Portfolio managers, fund-of-funds analysts, and SBA examiners need consistent, auditable metrics across heterogeneous portfolios. sbic-tracker provides typed Python data structures and financial functions that match SBA and LP reporting standards.

Installation

pip install sbic-tracker

No external dependencies — pure Python 3.9+.

Quickstart

from datetime import date
from sbictracker import (
    SBICLicensee, Investment,
    SBICPortfolio,
    load_sample_investments, load_sample_licensees,
    irr, tvpi, dpi, rvpi,
    vintage_year_analysis, peer_quartile_ranking,
    sector_breakdown, state_breakdown, top_naics,
)

# Load sample data (or plug in your own).
# These are INVENTED companies with invented dollar amounts — every record is
# stamped data_source == "sample". There is no live SBA loader; see above.
licensees = load_sample_licensees()
investments = load_sample_investments()

# Build a portfolio
portfolio = SBICPortfolio("Apex Growth Fund I")
portfolio.add_many(investments)
print(portfolio.summary())
# === Apex Growth Fund I ===
#   Investments      : 20 (9 realized / 11 unrealized)
#   Called capital   : $83,150,000
#   Distributed      : $72,410,000
#   NAV (unrealized) : $34,550,000
#   TVPI             : 1.29x
#   DPI              : 0.87x
#   RVPI             : 0.42x
# (Real output of the shipped sample data, executed 2026-08-02. Every figure
#  above is arithmetic over INVENTED companies — correct arithmetic, fictional
#  inputs. Do not quote these as SBIC program statistics.)

# IRR from custom cash flows
fund_flows = [-10_000_000, 0, 500_000, 2_000_000, 8_000_000, 5_000_000]
print(f"Fund IRR: {irr(fund_flows):.2%}")

# Vintage cohort analysis
cohorts = vintage_year_analysis(investments)
for yr, data in sorted(cohorts.items()):
    print(f"  {yr}: {data['count']} investments, TVPI {data['tvpi']:.2f}x")

# Peer quartile ranking
ranking = peer_quartile_ranking(fund_tvpi=1.8, peer_tvpis=[1.2, 1.4, 1.6, 1.9, 2.1])
print(f"Quartile: Q{ranking['quartile']}  ({ranking['percentile']}th percentile)")

# Sector concentration
top = top_naics(investments, n=3)
for code, name, invested in top:
    print(f"  NAICS {code} ({name}): ${invested:,.0f}")

Key Features

Feature Detail
IRR Newton-Raphson solver for arbitrary annual cash-flow vectors
TVPI / DPI / RVPI Industry-standard multiples from first principles
Write-off tracking Net cost basis automatically reflects partial/full write-offs
Vintage cohort analysis Group and compare by investment year
Peer quartile ranking Percentile and Q1–Q4 ranking vs a peer TVPI distribution
SBICPortfolio Add/remove investments; filter by sector, state, or instrument type
Sector/state breakdown NAICS 2-digit concentration with portfolio % weights
Sample data 10 licensees + 20 investments for prototyping — invented, stamped data_source == "sample"
Provenance markers Every record carries data_source ("sample" / "user")
SBA URL loader Not implemented. load_from_sba_url() raises SBADownloadError; there is no live SBA source

Use Cases

  • Fund managers — Track called/distributed capital and compute NAV-based multiples for LP reporting.
  • SBA examiners — Audit licensee leverage ratios and investment-level MOIC across the portfolio.
  • Fund-of-funds analysts — Compare SBIC fund vintage cohorts and rank against peer TVPIs.
  • Policy researchers — Analyze SBIC capital deployment by sector, state, and instrument type.
  • Limited partners — Build DPI/RVPI waterfalls and sensitivity models in Python.

API Reference

Data Classes

SBICLicensee(license_number, fund_name, fund_manager, license_date,
             license_status, license_type, total_capital, sba_leverage,
             private_capital, data_source="user")
  .leverage_ratio   # sba_leverage / private_capital
  .vintage_year
  .data_source      # "sample" | "user" — provenance, check before reporting

Investment(investee_company, investment_date, investment_amount, naics_code, state,
           exit_date, exit_proceeds, write_off_amount, instrument_type,
           data_source="user")
  .is_realized       # bool
  .data_source       # "sample" | "user"
  .realized_value    # exit_proceeds if realized, else 0
  .net_cost_basis    # amount - write_off_amount
  .moic              # exit_proceeds / amount (realized only)
  .naics_sector      # human-readable sector name
  .vintage_year

Fund Metrics

irr(cash_flows)                   # Newton-Raphson IRR
tvpi(investments)                 # (distributed + NAV) / called
dpi(investments)                  # distributed / called
rvpi(investments)                 # NAV / called
called_capital(investments)
distributed_capital(investments)
nav(investments)                  # unrealized positions at net cost
total_value(investments)

Portfolio & Analysis

SBICPortfolio(name)
  .add(investment)
  .add_many(investments)
  .remove(investee_company)
  .filter_by_sector(naics_prefix)
  .filter_by_state(state)
  .filter_realized() / .filter_unrealized()
  .summary_stats()
  .summary()

vintage_year_analysis(investments)          # → {year: {count, tvpi, dpi, ...}}
peer_quartile_ranking(fund_tvpi, peer_tvpis) # → {quartile, percentile, peer_median}

sector_breakdown(investments)               # → {naics_2: {sector_name, invested, pct}}
state_breakdown(investments)                # → {state: {count, invested, pct}}
top_naics(investments, n=5)                 # → [(code, name, invested), ...]

License

MIT © Jay Patel

Metadata

Release files for sbic-tracker 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sbic-tracker 0.2.0
File Size Uploaded
sbic_tracker-0.2.0.tar.gz 23.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sbic-tracker 0.2.0
File Interpreter ABI Platform
sbic_tracker-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 41.9 kB

Release files / sbic_tracker-0.2.0.tar.gz

Download URL sbic_tracker-0.2.0.tar.gz
Size 23.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c0b109dc23f6461dcfda7d27d0266d66ed13dd7fa995683388a8442472890969
BLAKE2b-256 checksum
How to use checksums
c80594ed0cb1814e5b0112233ae8881da093a07895fdff8aae8873fb1a6faaee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.

Transparency log

Release files / sbic_tracker-0.2.0-py3-none-any.whl

Download URL sbic_tracker-0.2.0-py3-none-any.whl
Size 18.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5ab21c60c5de733836d4ed9bb4476da361e76e851648c2243e815429e309c01
BLAKE2b-256 checksum
How to use checksums
1669d5e8f6f67e9e6827e51d61b32c2279f5817d7df30320a33670dc70d9bcae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page