|
11 | 11 | runs-on: ubuntu-latest |
12 | 12 | strategy: |
13 | 13 | matrix: |
14 | | - python-version: [3.9, 3.10, 3.11, 3.12] |
| 14 | + python-version: ["3.9", "3.10", "3.11", "3.12"] |
15 | 15 |
|
16 | 16 | steps: |
17 | 17 | - uses: actions/checkout@v4 |
@@ -40,105 +40,3 @@ jobs: |
40 | 40 | with: |
41 | 41 | files: coverage.xml |
42 | 42 | fail_ci_if_error: true |
43 | | -# Below is a **surgical to-do list** you can tackle one file at a time. I’ve ordered the fixes roughly by ROI: finish everything in **Step 0** first, then march down the file list. |
44 | | - |
45 | | -# --- |
46 | | - |
47 | | -# ## Step 0 – Repo-level hygiene (do once) |
48 | | - |
49 | | -# | Action | Why it matters | |
50 | | -# | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | |
51 | | -# | **Create `pyproject.toml`** with-in `[project]` dependencies (`numpy`, `pandas`, `numpy-financial`, `pydantic`, `typer`, `streamlit`, `plotly`, `markdown2`, `weasyprint`) and an editable `src` layout. | Removes “works-on-my-machine” smell. | |
52 | | -# | **Add `pre-commit`** (black, isort, flake8, mypy). | Static lint stops style drift. | |
53 | | -# | **GitHub Actions**: matrix on 3.9 → 3.12 running `pytest -q`. | Shows green badge to recruiters. | |
54 | | -# | **Codecov badge** (>90 % lines) | Signals test discipline. | |
55 | | - |
56 | | -# --- |
57 | | - |
58 | | -# ## File-by-file fixes |
59 | | - |
60 | | -# ### 1. `src/modules/lbo_model.py` |
61 | | - |
62 | | -# | 🔧 Fix | Detail | |
63 | | -# | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | |
64 | | -# | **Parameterise hard-coded 70 / 30 split** of bullet vs amort debt; pass as kwargs with defaults. Right now they’re literals . | Makes model flexible for mezz / unitranche cases. | |
65 | | -# | **Move `amort_schedule = [amort_amt/5]*5` to a helper** and allow custom schedules. | Models seven-year deals without code edits. | |
66 | | -# | **Sweep hierarchy**: instead of paying only the first non-revolver tranche , iterate senior → subordinated until cash exhausted. | Reflects typical cash-waterfall. | |
67 | | -# | **Implement LTV covenant** (`enterprise_value * exit_multiple`) vs total debt each year; raise `CovenantBreachError` like ICR. | Completes promised feature set. | |
68 | | -# | **Exit cash & WC unwind**: add cash balance build-up and working-capital release in exit IRR calc. | Removes rosy bias in IRR. | |
69 | | -# | **Docstrings & type hints** for every public method. | Reviewer readability. | |
70 | | - |
71 | | -# ### 2. `src/modules/fund_waterfall.py` |
72 | | - |
73 | | -# | 🔧 Fix | Detail | |
74 | | -# | ------------------------------------------------------------------------------------------------------------------------------------------ | ------ | |
75 | | -# | **Finish `reset_hurdle` logic** – after a tier is met, reduce base capital and recompute IRR; remove the stub comment . | | |
76 | | -# | **True catch-up math**: calculate GP catch-up until GP gets X % of all distributed profit before moving to next tier. | | |
77 | | -# | **Tier-by-tier carry** instead of “highest tier only”: loop through tiers and allocate incremental carry on the tranche above each hurdle. | | |
78 | | -# | **Management-fee base**: make it choice of *committed* vs *drawn* capital; right now it’s always committed . | | |
79 | | -# | **Annual fee offset**: subtract fees from distributions before hurdle tests; this is market practice. | | |
80 | | -# | **Clawback polish**: compare *net* GP carry (paid – taxes) to final entitlement; accrue interest on excess. | | |
81 | | -# | **Return vs paid-in capital test**: ensure LP gets 100 % of paid-in + pref before any carry. | | |
82 | | - |
83 | | -# ### 3. `src/modules/sensitivity.py` |
84 | | - |
85 | | -# | 🔧 Fix | Detail | |
86 | | -# | ------------------------------------------------------------------------------------ | ------ | |
87 | | -# | **Add confidence intervals** via bootstrap on IRR distribution. | | |
88 | | -# | **Vectorise `run_2d_sensitivity`** with `itertools.product` + list-comp for speed. | | |
89 | | -# | **Optional heat-map export** (`plotly.express.imshow`). | | |
90 | | -# | **Test coverage**: assert runtime < 1 s for a 100×100 grid to flag perf regressions. | | |
91 | | - |
92 | | -# ### 4. `cli.py` |
93 | | - |
94 | | -# | 🔧 Fix | Detail | |
95 | | -# | -------------------------------------------------------------------------------------------------- | ------ | |
96 | | -# | **Typo in `Field(. gt=0)`** – the leading space breaks parsing; use `Field(gt=0, …)` | | |
97 | | -# | . | | |
98 | | -# | **`--years` global option** so users don’t edit JSON for horizon tweaks. | | |
99 | | -# | **`typer.Option(Path(...), exists=True)`** is deprecated; switch to `FileText` or manual check. | | |
100 | | -# | **Surfacing error codes**: exit 2 for covenant breach, 3 for insolvency; CI can grep return codes. | | |
101 | | - |
102 | | -# ### 5. `streamlit_app.py` |
103 | | - |
104 | | -# | 🔧 Fix | Detail | |
105 | | -# | -------------------------------------------------------------------------------------------------------------------------- | ------ | |
106 | | -# | **Sanitise user JSON** from `tiers_json` with `jsonschema.validate`; right now `eval()` risk is latent when you refactor . | | |
107 | | -# | **Cache `convert_md_to_pdf`** with `@st.cache_data(ttl=3600)` to avoid heavy WeasyPrint re-runs. | | |
108 | | -# | **Guard against large uploads** – max file size sidebar setting. | | |
109 | | -# | **Accessibility**: add alt-text for Plotly traces via `hovertext`. | | |
110 | | - |
111 | | -# ### 6. `cashflow.py` |
112 | | - |
113 | | -# | 🔧 Fix | Detail | |
114 | | -# | ------------------------------------------------------------------------------------- | ------ | |
115 | | -# | **Remove duplicate logic with `lbo_model`** – keep in one place, import in the other. | | |
116 | | -# | **Return `pd.DataFrame` directly** instead of dict-of-dicts for usability. | | |
117 | | - |
118 | | -# ### 7. `exit.py` |
119 | | - |
120 | | -# | 🔧 Fix | Detail | |
121 | | -# | --------------------------------------------------------------------------------------------- | ------ | |
122 | | -# | **Use `numpy_financial.irr`** instead of custom CAGR when cash flows aren’t annual lump sums. | | |
123 | | -# | **Handle negative equity value** by returning `None` IRR, not −1 sentinel . | | |
124 | | -# | **Add option for sale costs (%) and leverage recap**. | | |
125 | | - |
126 | | -# ### 8. Tests (`tests/*.py`) |
127 | | - |
128 | | -# | 🔧 Fix | Detail | |
129 | | -# | ------------------------------------------------------------------------------------------------ | ------ | |
130 | | -# | **Parametrise** pytest cases with `@pytest.mark.parametrize` instead of copy-paste blocks. | | |
131 | | -# | **Add property-based tests** (`hypothesis`) to fuzz weird tiers, fee rates, and amort schedules. | | |
132 | | -# | **Contract tests vs Excel**: load a simple spreadsheet waterfall, assert parity. | | |
133 | | - |
134 | | -# --- |
135 | | - |
136 | | -# ## Suggested implementation sequence |
137 | | - |
138 | | -# 1. **Fund waterfall core fixes** (carry tiers, reset hurdle). |
139 | | -# 2. **LBO model debt & covenant realism**. |
140 | | -# 3. **Repo packaging + CI** (do once features stabilise). |
141 | | -# 4. **Streamlit security & performance tweaks**. |
142 | | -# 5. **Sensitivity visual extras & hypothesis tests**. |
143 | | - |
144 | | -# Finishing items 1-3 gets you to the “minimum publishable model”; items 4-8 are polish that will impress reviewers but aren’t blocking the paper. |
0 commit comments