equitable-capital-optimization-ai 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ """Public API for the Equitable Capital Optimization research package."""
2
+
3
+ from .allocation import allocate_capital, summarize_allocation
4
+ from .data import generate_synthetic_startups
5
+ from .explainability import explain_applicant
6
+ from .fairness import fairness_audit, opportunity_gap
7
+ from .modeling import (
8
+ ModelResult,
9
+ build_pipeline,
10
+ global_feature_importance,
11
+ train_model,
12
+ )
13
+
14
+ __all__ = [
15
+ "ModelResult",
16
+ "allocate_capital",
17
+ "build_pipeline",
18
+ "explain_applicant",
19
+ "fairness_audit",
20
+ "generate_synthetic_startups",
21
+ "global_feature_importance",
22
+ "opportunity_gap",
23
+ "summarize_allocation",
24
+ "train_model",
25
+ ]
@@ -0,0 +1,96 @@
1
+ """Capital-allocation scenario simulation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pandas as pd
6
+
7
+ from .config import DEFAULT_EQUITY_WEIGHT
8
+
9
+
10
+ def _greedy_allocate(
11
+ data: pd.DataFrame,
12
+ budget: float,
13
+ score_column: str,
14
+ ) -> pd.DataFrame:
15
+ ranked = data.sort_values(
16
+ [score_column, "predicted_success_probability"], ascending=False
17
+ ).copy()
18
+ remaining = float(budget)
19
+ allocations: list[dict] = []
20
+
21
+ for _, row in ranked.iterrows():
22
+ if remaining <= 0:
23
+ break
24
+ requested = float(row["requested_capital"])
25
+ allocated = min(requested, remaining)
26
+ if allocated <= 0:
27
+ continue
28
+ item = row.to_dict()
29
+ item["allocated_capital"] = allocated
30
+ allocations.append(item)
31
+ remaining -= allocated
32
+
33
+ return pd.DataFrame(allocations)
34
+
35
+
36
+ def allocate_capital(
37
+ scored: pd.DataFrame,
38
+ budget: float,
39
+ equity_weight: float = DEFAULT_EQUITY_WEIGHT,
40
+ ) -> tuple[pd.DataFrame, pd.DataFrame]:
41
+ """Compare efficiency-only and equity-aware research scenarios."""
42
+ if budget <= 0:
43
+ raise ValueError("budget must be greater than zero")
44
+ if not 0 <= equity_weight <= 1:
45
+ raise ValueError("equity_weight must be between 0 and 1")
46
+
47
+ data = scored.copy()
48
+ data["efficiency_priority"] = (
49
+ data["predicted_success_probability"] / data["requested_capital"].clip(lower=1)
50
+ )
51
+
52
+ request_norm = data["requested_capital"] / data["requested_capital"].max()
53
+ data["equity_priority"] = (
54
+ (1 - equity_weight) * data["predicted_success_probability"]
55
+ + equity_weight * data["underserved_context_index"]
56
+ - 0.05 * request_norm
57
+ )
58
+
59
+ baseline = _greedy_allocate(data, budget, "efficiency_priority")
60
+ equitable = _greedy_allocate(data, budget, "equity_priority")
61
+ return baseline, equitable
62
+
63
+
64
+ def summarize_allocation(
65
+ allocated: pd.DataFrame,
66
+ budget: float,
67
+ ) -> dict[str, float | int]:
68
+ """Summarize a simulated allocation result."""
69
+ if allocated.empty:
70
+ return {
71
+ "businesses_funded": 0,
72
+ "capital_allocated": 0.0,
73
+ "budget_utilization": 0.0,
74
+ "share_to_higher_barrier_contexts": 0.0,
75
+ "expected_successes": 0.0,
76
+ }
77
+
78
+ total = float(allocated["allocated_capital"].sum())
79
+ higher_barrier = allocated["underserved_context_index"] >= 0.5
80
+
81
+ return {
82
+ "businesses_funded": int(len(allocated)),
83
+ "capital_allocated": total,
84
+ "budget_utilization": total / budget if budget else 0.0,
85
+ "share_to_higher_barrier_contexts": float(
86
+ allocated.loc[higher_barrier, "allocated_capital"].sum() / total
87
+ if total
88
+ else 0.0
89
+ ),
90
+ "expected_successes": float(
91
+ (
92
+ allocated["predicted_success_probability"]
93
+ * (allocated["allocated_capital"] / allocated["requested_capital"])
94
+ ).sum()
95
+ ),
96
+ }
@@ -0,0 +1,23 @@
1
+ """Shared project configuration and feature definitions."""
2
+
3
+ RANDOM_SEED = 42
4
+ DEFAULT_SAMPLE_SIZE = 1500
5
+ DEFAULT_SELECTION_THRESHOLD = 0.50
6
+ DEFAULT_EQUITY_WEIGHT = 0.30
7
+
8
+ NUMERIC_FEATURES = [
9
+ "annual_revenue",
10
+ "revenue_growth_pct",
11
+ "cash_runway_months",
12
+ "employees",
13
+ "years_operating",
14
+ "debt_service_coverage",
15
+ "digital_adoption_score",
16
+ "market_demand_score",
17
+ "management_capacity_score",
18
+ "requested_capital",
19
+ ]
20
+
21
+ CATEGORICAL_FEATURES = ["state", "industry"]
22
+ MODEL_FEATURES = NUMERIC_FEATURES + CATEGORICAL_FEATURES
23
+ TARGET = "funding_success"
@@ -0,0 +1,81 @@
1
+ """Synthetic data generation for the research prototype."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+ from .config import DEFAULT_SAMPLE_SIZE, RANDOM_SEED, TARGET
9
+
10
+
11
+ def generate_synthetic_startups(
12
+ n: int = DEFAULT_SAMPLE_SIZE,
13
+ seed: int = RANDOM_SEED,
14
+ ) -> pd.DataFrame:
15
+ """Generate reproducible, privacy-safe synthetic small-business records."""
16
+ if n < 100:
17
+ raise ValueError("n must be at least 100 for a stable demonstration dataset")
18
+
19
+ rng = np.random.default_rng(seed)
20
+ states = np.array(["VA", "MD", "DC", "NC", "GA", "TX", "CA", "NY", "IL", "FL"])
21
+ industries = np.array(
22
+ [
23
+ "Technology",
24
+ "Retail",
25
+ "Professional Services",
26
+ "Food",
27
+ "Healthcare",
28
+ "Manufacturing",
29
+ "Education",
30
+ "Logistics",
31
+ ]
32
+ )
33
+
34
+ data = pd.DataFrame(
35
+ {
36
+ "startup_id": [f"BUS-{i:04d}" for i in range(1, n + 1)],
37
+ "state": rng.choice(states, n),
38
+ "industry": rng.choice(industries, n),
39
+ "annual_revenue": np.round(rng.lognormal(12.0, 0.9, n), 2),
40
+ "revenue_growth_pct": np.round(rng.normal(18, 18, n).clip(-40, 120), 2),
41
+ "cash_runway_months": np.round(rng.gamma(3.2, 2.0, n).clip(0.5, 24), 2),
42
+ "employees": rng.integers(1, 80, n),
43
+ "years_operating": np.round(rng.gamma(2.5, 1.8, n).clip(0.2, 20), 2),
44
+ "debt_service_coverage": np.round(
45
+ rng.normal(1.35, 0.45, n).clip(0.2, 3.5), 2
46
+ ),
47
+ "digital_adoption_score": np.round(rng.normal(62, 20, n).clip(0, 100), 1),
48
+ "market_demand_score": np.round(rng.normal(66, 18, n).clip(0, 100), 1),
49
+ "management_capacity_score": np.round(
50
+ rng.normal(64, 17, n).clip(0, 100), 1
51
+ ),
52
+ "requested_capital": np.round(rng.lognormal(11.3, 0.75, n), 2),
53
+ "rural_area": rng.binomial(1, 0.28, n),
54
+ "low_income_area": rng.binomial(1, 0.35, n),
55
+ "limited_finance_access": rng.binomial(1, 0.33, n),
56
+ }
57
+ )
58
+
59
+ data["underserved_context_index"] = np.round(
60
+ (
61
+ 0.35 * data["low_income_area"]
62
+ + 0.30 * data["limited_finance_access"]
63
+ + 0.20 * data["rural_area"]
64
+ + 0.15 * (1 - data["digital_adoption_score"] / 100)
65
+ ).clip(0, 1),
66
+ 3,
67
+ )
68
+
69
+ logit = (
70
+ -2.6
71
+ + 0.0000022 * data["annual_revenue"]
72
+ + 0.018 * data["revenue_growth_pct"]
73
+ + 0.075 * data["cash_runway_months"]
74
+ + 0.30 * data["debt_service_coverage"]
75
+ + 0.010 * data["market_demand_score"]
76
+ + 0.008 * data["management_capacity_score"]
77
+ - 0.0000013 * data["requested_capital"]
78
+ )
79
+ probability = 1 / (1 + np.exp(-logit))
80
+ data[TARGET] = rng.binomial(1, probability.clip(0.03, 0.97))
81
+ return data
@@ -0,0 +1,38 @@
1
+ """Lightweight, transparent local explanation utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pandas as pd
6
+ from sklearn.pipeline import Pipeline
7
+
8
+ from .config import MODEL_FEATURES, NUMERIC_FEATURES
9
+
10
+
11
+ def explain_applicant(
12
+ pipeline: Pipeline,
13
+ applicant: pd.Series,
14
+ reference: pd.DataFrame,
15
+ ) -> pd.DataFrame:
16
+ """Estimate local directional sensitivity for numeric model features."""
17
+ base = applicant[MODEL_FEATURES].to_frame().T.copy()
18
+ base_probability = float(pipeline.predict_proba(base)[:, 1][0])
19
+ rows: list[dict[str, float | str]] = []
20
+
21
+ for feature in NUMERIC_FEATURES:
22
+ perturbed = base.copy()
23
+ perturbed[feature] = reference[feature].median()
24
+ probability = float(pipeline.predict_proba(perturbed)[:, 1][0])
25
+ rows.append(
26
+ {
27
+ "feature": feature,
28
+ "applicant_value": float(base.iloc[0][feature]),
29
+ "reference_median": float(reference[feature].median()),
30
+ "contribution_proxy": base_probability - probability,
31
+ }
32
+ )
33
+
34
+ return pd.DataFrame(rows).sort_values(
35
+ "contribution_proxy",
36
+ key=lambda series: series.abs(),
37
+ ascending=False,
38
+ )
@@ -0,0 +1,68 @@
1
+ """Fairness and structural-opportunity diagnostic utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pandas as pd
6
+
7
+ from .config import DEFAULT_SELECTION_THRESHOLD
8
+
9
+
10
+ def fairness_audit(
11
+ scored: pd.DataFrame,
12
+ threshold: float = DEFAULT_SELECTION_THRESHOLD,
13
+ underserved_cutoff: float = 0.50,
14
+ ) -> pd.DataFrame:
15
+ """Compare model outcomes across higher- and lower-barrier contexts."""
16
+ if not 0 <= threshold <= 1:
17
+ raise ValueError("threshold must be between 0 and 1")
18
+
19
+ data = scored.copy()
20
+ data["context_group"] = data["underserved_context_index"].ge(underserved_cutoff).map(
21
+ {
22
+ True: "Higher structural barriers",
23
+ False: "Lower structural barriers",
24
+ }
25
+ )
26
+ data["selected"] = data["predicted_success_probability"].ge(threshold).astype(int)
27
+
28
+ rows: list[dict[str, float | int | str]] = []
29
+ for group, frame in data.groupby("context_group", observed=True):
30
+ rows.append(
31
+ {
32
+ "context_group": group,
33
+ "n": int(len(frame)),
34
+ "selection_rate": float(frame["selected"].mean()),
35
+ "avg_predicted_success": float(
36
+ frame["predicted_success_probability"].mean()
37
+ ),
38
+ "avg_requested_capital": float(frame["requested_capital"].mean()),
39
+ "avg_readiness_score": float(frame["capital_readiness_score"].mean()),
40
+ }
41
+ )
42
+
43
+ audit = pd.DataFrame(rows)
44
+ if len(audit) == 2:
45
+ maximum = float(audit["selection_rate"].max())
46
+ minimum = float(audit["selection_rate"].min())
47
+ ratio = minimum / maximum if maximum > 0 else 1.0
48
+ else:
49
+ ratio = 1.0
50
+
51
+ audit["selection_rate_ratio"] = ratio
52
+ return audit
53
+
54
+
55
+ def opportunity_gap(scored: pd.DataFrame, cutoff: float = 0.50) -> dict[str, float]:
56
+ """Summarize readiness and requested-capital gaps across contexts."""
57
+ higher = scored[scored["underserved_context_index"] >= cutoff]
58
+ lower = scored[scored["underserved_context_index"] < cutoff]
59
+
60
+ return {
61
+ "readiness_gap_points": float(
62
+ lower["capital_readiness_score"].mean()
63
+ - higher["capital_readiness_score"].mean()
64
+ ),
65
+ "requested_capital_gap": float(
66
+ higher["requested_capital"].mean() - lower["requested_capital"].mean()
67
+ ),
68
+ }
@@ -0,0 +1,122 @@
1
+ """Predictive modeling and model-evaluation utilities."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+ import pandas as pd
8
+ from sklearn.compose import ColumnTransformer
9
+ from sklearn.ensemble import RandomForestClassifier
10
+ from sklearn.metrics import (
11
+ accuracy_score,
12
+ brier_score_loss,
13
+ f1_score,
14
+ precision_score,
15
+ recall_score,
16
+ roc_auc_score,
17
+ )
18
+ from sklearn.model_selection import train_test_split
19
+ from sklearn.pipeline import Pipeline
20
+ from sklearn.preprocessing import OneHotEncoder, StandardScaler
21
+
22
+ from .config import (
23
+ CATEGORICAL_FEATURES,
24
+ MODEL_FEATURES,
25
+ NUMERIC_FEATURES,
26
+ RANDOM_SEED,
27
+ TARGET,
28
+ )
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class ModelResult:
33
+ """Container for the trained pipeline, evaluation metrics, and scored data."""
34
+
35
+ pipeline: Pipeline
36
+ metrics: dict[str, float]
37
+ scored_data: pd.DataFrame
38
+
39
+ @property
40
+ def auc(self) -> float:
41
+ return self.metrics["roc_auc"]
42
+
43
+ @property
44
+ def accuracy(self) -> float:
45
+ return self.metrics["accuracy"]
46
+
47
+
48
+ def build_pipeline(random_state: int = RANDOM_SEED) -> Pipeline:
49
+ """Build the preprocessing and Random Forest classification pipeline."""
50
+ preprocess = ColumnTransformer(
51
+ [
52
+ ("num", StandardScaler(), NUMERIC_FEATURES),
53
+ ("cat", OneHotEncoder(handle_unknown="ignore"), CATEGORICAL_FEATURES),
54
+ ]
55
+ )
56
+ model = RandomForestClassifier(
57
+ n_estimators=300,
58
+ max_depth=9,
59
+ min_samples_leaf=5,
60
+ class_weight="balanced",
61
+ random_state=random_state,
62
+ n_jobs=-1,
63
+ )
64
+ return Pipeline([("preprocess", preprocess), ("model", model)])
65
+
66
+
67
+ def train_model(data: pd.DataFrame, random_state: int = RANDOM_SEED) -> ModelResult:
68
+ """Train the model and score the complete synthetic dataset."""
69
+ missing = sorted(set(MODEL_FEATURES + [TARGET]) - set(data.columns))
70
+ if missing:
71
+ raise ValueError(f"Missing required columns: {missing}")
72
+
73
+ features = data[MODEL_FEATURES].copy()
74
+ target = data[TARGET].astype(int)
75
+
76
+ x_train, x_test, y_train, y_test = train_test_split(
77
+ features,
78
+ target,
79
+ test_size=0.25,
80
+ stratify=target,
81
+ random_state=random_state,
82
+ )
83
+
84
+ pipeline = build_pipeline(random_state=random_state)
85
+ pipeline.fit(x_train, y_train)
86
+
87
+ predictions = pipeline.predict(x_test)
88
+ probabilities = pipeline.predict_proba(x_test)[:, 1]
89
+
90
+ metrics = {
91
+ "roc_auc": float(roc_auc_score(y_test, probabilities)),
92
+ "accuracy": float(accuracy_score(y_test, predictions)),
93
+ "precision": float(precision_score(y_test, predictions, zero_division=0)),
94
+ "recall": float(recall_score(y_test, predictions, zero_division=0)),
95
+ "f1": float(f1_score(y_test, predictions, zero_division=0)),
96
+ "brier": float(brier_score_loss(y_test, probabilities)),
97
+ }
98
+
99
+ scored = data.copy()
100
+ scored["predicted_success_probability"] = pipeline.predict_proba(features)[:, 1]
101
+ scored["capital_readiness_score"] = (
102
+ 100 * scored["predicted_success_probability"]
103
+ ).round(1)
104
+
105
+ return ModelResult(pipeline=pipeline, metrics=metrics, scored_data=scored)
106
+
107
+
108
+ def global_feature_importance(result: ModelResult) -> pd.DataFrame:
109
+ """Return transformed-model feature importances in descending order."""
110
+ preprocess = result.pipeline.named_steps["preprocess"]
111
+ model = result.pipeline.named_steps["model"]
112
+ feature_names = preprocess.get_feature_names_out()
113
+
114
+ importance = pd.DataFrame(
115
+ {"feature": feature_names, "importance": model.feature_importances_}
116
+ )
117
+ importance["feature"] = (
118
+ importance["feature"]
119
+ .str.replace("num__", "", regex=False)
120
+ .str.replace("cat__", "", regex=False)
121
+ )
122
+ return importance.sort_values("importance", ascending=False).reset_index(drop=True)
@@ -0,0 +1,267 @@
1
+ Metadata-Version: 2.4
2
+ Name: equitable-capital-optimization-ai
3
+ Version: 0.2.0
4
+ Summary: Research package for predictive capital-readiness analysis, fairness auditing, explainable AI, and equity-aware capital allocation.
5
+ Author: Sakera Begum
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sakera023/equitable-capital-optimization-ai
8
+ Project-URL: Repository, https://github.com/sakera023/equitable-capital-optimization-ai
9
+ Project-URL: Issues, https://github.com/sakera023/equitable-capital-optimization-ai/issues
10
+ Project-URL: Documentation, https://github.com/sakera023/equitable-capital-optimization-ai/tree/main/docs
11
+ Project-URL: Publication, https://www.researchgate.net/publication/410866072_An_AI-Powered_Framework_for_Equitable_Capital_Optimization_Leveraging_Predictive_Intelligence_to_Empower_Underserved_Entrepreneurial_Ecosystems_in_the_US
12
+ Keywords: artificial-intelligence,machine-learning,predictive-analytics,entrepreneurship,small-business,capital-allocation,fairness,responsible-ai,explainable-ai,streamlit
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy<3,>=1.26
27
+ Requires-Dist: pandas<4,>=2.1
28
+ Requires-Dist: plotly<8,>=5.20
29
+ Requires-Dist: scikit-learn<2,>=1.4
30
+ Requires-Dist: streamlit<2,>=1.40
31
+ Provides-Extra: dev
32
+ Requires-Dist: build<2,>=1.2; extra == "dev"
33
+ Requires-Dist: pytest<10,>=8; extra == "dev"
34
+ Requires-Dist: ruff<1,>=0.8; extra == "dev"
35
+ Requires-Dist: twine<7,>=5; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # Equitable Capital Optimization AI
39
+
40
+ [![CI](https://github.com/sakera023/equitable-capital-optimization-ai/actions/workflows/ci.yml/badge.svg)](https://github.com/sakera023/equitable-capital-optimization-ai/actions/workflows/ci.yml)
41
+ ![Python](https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python&logoColor=white)
42
+ ![Streamlit](https://img.shields.io/badge/Streamlit-App-FF4B4B?logo=streamlit&logoColor=white)
43
+ ![License](https://img.shields.io/badge/License-MIT-green)
44
+
45
+ A reproducible research prototype for **predictive capital-readiness analysis, model
46
+ explainability, fairness auditing, and equity-aware capital-allocation simulation** for
47
+ underserved U.S. entrepreneurial ecosystems.
48
+
49
+ The project is inspired by:
50
+
51
+ > **An AI-Powered Framework for Equitable Capital Optimization: Leveraging Predictive
52
+ > Intelligence to Empower Underserved Entrepreneurial Ecosystems in the U.S.**
53
+
54
+ Related publication:
55
+ [ResearchGate](https://www.researchgate.net/publication/410866072_An_AI-Powered_Framework_for_Equitable_Capital_Optimization_Leveraging_Predictive_Intelligence_to_Empower_Underserved_Entrepreneurial_Ecosystems_in_the_US)
56
+
57
+ ## Why this project exists
58
+
59
+ Access to capital is not only a prediction problem. It is also an allocation,
60
+ transparency, and measurement problem. This repository separates those concerns into
61
+ four independently testable components:
62
+
63
+ | Component | Purpose |
64
+ | --- | --- |
65
+ | Predictive modeling | Estimate funding-success probability from business and market features |
66
+ | Explainability | Show how applicant-level features influence the model locally |
67
+ | Fairness auditing | Compare outcomes across structural-access contexts |
68
+ | Capital allocation | Compare efficiency-only and equity-aware funding scenarios |
69
+
70
+ ## Responsible-use boundary
71
+
72
+ > **Research and educational use only.**
73
+ >
74
+ > This project must not be used to make real lending, credit, investment, employment,
75
+ > housing, insurance, benefits, or eligibility decisions.
76
+
77
+ The predictive model intentionally excludes protected personal characteristics.
78
+ Structural context indicators are used for research auditing and allocation simulation,
79
+ not as protected-trait proxies for real-world underwriting.
80
+
81
+ ## Architecture
82
+
83
+ ```mermaid
84
+ flowchart LR
85
+ A[Synthetic Business Data] --> B[Feature Pipeline]
86
+ B --> C[Random Forest Model]
87
+ C --> D[Capital Readiness Score]
88
+ C --> E[Local Explanation]
89
+ D --> F[Fairness Audit]
90
+ D --> G[Allocation Simulator]
91
+ F --> H[Research Dashboard]
92
+ G --> H
93
+ E --> H
94
+ ```
95
+
96
+ See [Architecture](docs/ARCHITECTURE.md) and [Methodology](docs/METHODOLOGY.md).
97
+
98
+ ## Key capabilities
99
+
100
+ - Reproducible synthetic U.S. small-business/startup data generation
101
+ - Scikit-learn preprocessing and Random Forest classification pipeline
102
+ - Holdout evaluation with ROC-AUC, accuracy, precision, recall, F1, and Brier score
103
+ - Capital Readiness Score derived from predicted funding-success probability
104
+ - Global feature-importance reporting
105
+ - Applicant-level local sensitivity explanations
106
+ - Structural-context fairness audit and selection-rate comparison
107
+ - Efficiency-only and equity-aware capital-allocation simulation
108
+ - Interactive Streamlit research dashboard
109
+ - Automated tests and linting in GitHub Actions
110
+ - Model card, citation metadata, contribution guide, and security policy
111
+
112
+ ## Python package
113
+
114
+ The reusable research code lives in the `equitable_capital` Python package.
115
+
116
+ After a release is published to PyPI, install it with:
117
+
118
+ ```bash
119
+ pip install equitable-capital-optimization-ai
120
+ ```
121
+
122
+ Example:
123
+
124
+ ```python
125
+ from equitable_capital import (
126
+ allocate_capital,
127
+ fairness_audit,
128
+ generate_synthetic_startups,
129
+ train_model,
130
+ )
131
+
132
+ data = generate_synthetic_startups()
133
+ result = train_model(data)
134
+ audit = fairness_audit(result.scored_data)
135
+ ```
136
+
137
+ For local development, install the repository in editable mode:
138
+
139
+ ```bash
140
+ pip install -e ".[dev]"
141
+ ```
142
+
143
+ ## Quick start
144
+
145
+ ```bash
146
+ git clone https://github.com/sakera023/equitable-capital-optimization-ai.git
147
+ cd equitable-capital-optimization-ai
148
+ python -m venv .venv
149
+ ```
150
+
151
+ Activate the environment.
152
+
153
+ **Windows**
154
+
155
+ ```bash
156
+ .venv\Scripts\activate
157
+ ```
158
+
159
+ **macOS/Linux**
160
+
161
+ ```bash
162
+ source .venv/bin/activate
163
+ ```
164
+
165
+ Install and run:
166
+
167
+ ```bash
168
+ pip install -r requirements.txt
169
+ streamlit run app.py
170
+ ```
171
+
172
+ Development checks:
173
+
174
+ ```bash
175
+ pip install -r requirements-dev.txt
176
+ ruff check src tests app.py
177
+ python -m pytest -q
178
+ ```
179
+
180
+ ## Repository structure
181
+
182
+ ```text
183
+ .
184
+ ├── app.py
185
+ ├── pyproject.toml
186
+ ├── requirements.txt
187
+ ├── requirements-dev.txt
188
+ ├── Makefile
189
+ ├── src/
190
+ │ └── equitable_capital/
191
+ │ ├── __init__.py
192
+ │ ├── allocation.py
193
+ │ ├── config.py
194
+ │ ├── data.py
195
+ │ ├── explainability.py
196
+ │ ├── fairness.py
197
+ │ └── modeling.py
198
+ ├── tests/
199
+ ├── docs/
200
+ ├── .github/
201
+ ├── CITATION.cff
202
+ ├── CONTRIBUTING.md
203
+ ├── SECURITY.md
204
+ ├── CHANGELOG.md
205
+ └── LICENSE
206
+ ```
207
+
208
+ ## Data design
209
+
210
+ The repository uses **synthetic data by default**. This avoids exposing private
211
+ financial records, makes the project reproducible, and prevents the demonstration from
212
+ implying real-world predictive validity.
213
+
214
+ Predictive features include revenue, growth, cash runway, employees, operating history,
215
+ debt-service coverage, digital adoption, market demand, management capacity, requested
216
+ capital, industry, and state.
217
+
218
+ ## Model evaluation
219
+
220
+ The application reports ROC-AUC, accuracy, precision, recall, F1 score, and Brier score.
221
+ These metrics evaluate the synthetic demonstration only.
222
+
223
+ ## Fairness and equity analysis
224
+
225
+ A **structural barrier index** is built from contextual variables such as low-income
226
+ area, rural area, limited finance access, and digital adoption.
227
+
228
+ The index is reserved for post-model fairness diagnostics and research simulation of
229
+ equity-aware allocation policies. It is not included in the predictive training
230
+ features.
231
+
232
+ ## Reproducibility
233
+
234
+ The synthetic data generator and model pipeline use explicit random seeds. Tests verify
235
+ data ranges, prediction bounds, allocation-budget constraints, and fairness-audit
236
+ outputs. CI runs on every push and pull request.
237
+
238
+ ## Research roadmap
239
+
240
+ Planned extensions include gradient-boosted model benchmarks, probability calibration,
241
+ SHAP, temporal/geographic validation, county-level opportunity maps, Census/SBA/CDFI
242
+ public-data integrations, constrained optimization, and uncertainty analysis.
243
+
244
+ See [Research Roadmap](docs/RESEARCH_ROADMAP.md).
245
+
246
+ ## Citation
247
+
248
+ If you use the software, cite the repository metadata in [CITATION.cff](CITATION.cff).
249
+ If you use the associated research concept, cite the publication separately and clearly
250
+ distinguish research findings from this software prototype.
251
+
252
+ ## Contributing
253
+
254
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
255
+
256
+ ## Security
257
+
258
+ Do not publish secrets, private financial information, or real applicant records in
259
+ issues or pull requests. See [SECURITY.md](SECURITY.md).
260
+
261
+ ## License
262
+
263
+ MIT License. See [LICENSE](LICENSE).
264
+
265
+ ## Maintainer
266
+
267
+ **Sakera Begum**
@@ -0,0 +1,12 @@
1
+ equitable_capital/__init__.py,sha256=ipacOoxOMfhIpfEaczJ5Wlli-qf6v49SGtWjdODvjwU,660
2
+ equitable_capital/allocation.py,sha256=Ll2ka3NiX1Dk2fY6L3LOXXiBWveua4JDFyG8DEXGQ0U,2966
3
+ equitable_capital/config.py,sha256=rN5yJXbv5YExFO5ggTt74zdQ_Ru0R2PbyQkwtveVFl4,581
4
+ equitable_capital/data.py,sha256=5Msi58Kwai3Yd-lNXcc5BWTbupORxzA3X7BmjIv2L3Q,2919
5
+ equitable_capital/explainability.py,sha256=vNx8uRVUYbPH0P-9g372CEmdryc6iLMgIJSzPPE2BPo,1225
6
+ equitable_capital/fairness.py,sha256=qwqagtGV1ip58jst5VBqnNb2GVt9XyW68zo9R8GtmHE,2368
7
+ equitable_capital/modeling.py,sha256=omZmIqxrjhwUyNML12eFXGUM9Ea-kJT19ULEUmT1HD8,3857
8
+ equitable_capital_optimization_ai-0.2.0.dist-info/licenses/LICENSE,sha256=34lseBbMlsAHo4x1C5pPRwAqE9pXcsI-ALlU3aqLguA,1069
9
+ equitable_capital_optimization_ai-0.2.0.dist-info/METADATA,sha256=-fkDfKdSbZwA2zH6aA2TgYQP26YFvZvGfUZLuF41iqA,9055
10
+ equitable_capital_optimization_ai-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
11
+ equitable_capital_optimization_ai-0.2.0.dist-info/top_level.txt,sha256=j69pW2IqsDHlt81XaFj4eHXKoOzF6eBYKcdg4buSMi0,18
12
+ equitable_capital_optimization_ai-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sakera Begum
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ equitable_capital