superkit-mcp-server 1.0.2 → 1.1.0
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.
- package/ARCHITECTURE.md +102 -102
- package/README.md +67 -63
- package/SUPERKIT.md +168 -168
- package/agents/code-archaeologist.md +106 -0
- package/agents/coder.md +90 -90
- package/agents/data-engineer.md +28 -28
- package/agents/devops-engineer.md +242 -0
- package/agents/git-manager.md +203 -203
- package/agents/orchestrator.md +4 -0
- package/agents/penetration-tester.md +188 -0
- package/agents/performance-optimizer.md +187 -0
- package/agents/planner.md +270 -270
- package/agents/qa-automation-engineer.md +103 -0
- package/agents/quant-developer.md +32 -28
- package/agents/reviewer.md +100 -100
- package/agents/scout.md +222 -222
- package/agents/tester.md +274 -274
- package/agents/ui-designer.md +208 -208
- package/build/index.js +53 -1
- package/build/tools/validators/__tests__/apiSchema.test.js +23 -23
- package/build/tools/validators/__tests__/convertRules.test.js +5 -5
- package/build/tools/validators/__tests__/frontendDesign.test.js +12 -12
- package/build/tools/validators/__tests__/geoChecker.test.js +19 -19
- package/build/tools/validators/__tests__/mobileAudit.test.js +12 -12
- package/build/tools/validators/__tests__/reactPerformanceChecker.test.js +17 -17
- package/build/tools/validators/__tests__/securityScan.test.js +6 -6
- package/build/tools/validators/__tests__/seoChecker.test.js +16 -16
- package/build/tools/validators/__tests__/typeCoverage.test.js +14 -14
- package/package.json +33 -33
- package/skills/meta/README.md +30 -30
- package/skills/meta/api-design/SKILL.md +134 -134
- package/skills/meta/code-review/SKILL.md +44 -37
- package/skills/meta/code-review/checklists/pre-merge.md +25 -25
- package/skills/meta/code-review/workflows/architecture-pass.md +26 -26
- package/skills/meta/code-review/workflows/performance-pass.md +27 -27
- package/skills/meta/code-review/workflows/security-pass.md +29 -29
- package/skills/meta/compound-docs/SKILL.md +133 -133
- package/skills/meta/debug/SKILL.md +40 -40
- package/skills/meta/debug/templates/bug-report.template.md +31 -31
- package/skills/meta/debug/workflows/reproduce-issue.md +20 -20
- package/skills/meta/docker/SKILL.md +126 -126
- package/skills/meta/examples/supabase/SKILL.md +46 -46
- package/skills/meta/examples/supabase/references/best-practices.md +319 -319
- package/skills/meta/examples/supabase/references/common-patterns.md +373 -373
- package/skills/meta/examples/supabase/templates/migration-template.sql +49 -49
- package/skills/meta/examples/supabase/templates/rls-policy-template.sql +77 -77
- package/skills/meta/examples/supabase/workflows/debugging.md +260 -260
- package/skills/meta/examples/supabase/workflows/migration-workflow.md +211 -211
- package/skills/meta/examples/supabase/workflows/rls-policies.md +244 -244
- package/skills/meta/examples/supabase/workflows/schema-design.md +321 -321
- package/skills/meta/file-todos/SKILL.md +88 -88
- package/skills/meta/mobile/SKILL.md +140 -140
- package/skills/meta/nextjs/SKILL.md +101 -101
- package/skills/meta/performance/SKILL.md +130 -130
- package/skills/meta/react-patterns/SKILL.md +83 -83
- package/skills/meta/security/SKILL.md +114 -114
- package/skills/meta/session-resume/SKILL.md +96 -96
- package/skills/meta/tailwind/SKILL.md +139 -139
- package/skills/meta/testing/SKILL.md +43 -43
- package/skills/meta/testing/references/vitest-patterns.md +45 -45
- package/skills/meta/testing/templates/component-test.template.tsx +37 -37
- package/skills/tech/alpha-vantage/SKILL.md +142 -0
- package/skills/tech/alpha-vantage/references/commodities.md +153 -0
- package/skills/tech/alpha-vantage/references/economic-indicators.md +158 -0
- package/skills/tech/alpha-vantage/references/forex-crypto.md +154 -0
- package/skills/tech/alpha-vantage/references/fundamentals.md +223 -0
- package/skills/tech/alpha-vantage/references/intelligence.md +138 -0
- package/skills/tech/alpha-vantage/references/options.md +93 -0
- package/skills/tech/alpha-vantage/references/technical-indicators.md +374 -0
- package/skills/tech/alpha-vantage/references/time-series.md +157 -0
- package/skills/tech/financial-modeling/SKILL.md +18 -0
- package/skills/tech/financial-modeling/skills/3-statements/SKILL.md +368 -0
- package/skills/tech/financial-modeling/skills/3-statements/references/formatting.md +118 -0
- package/skills/tech/financial-modeling/skills/3-statements/references/formulas.md +292 -0
- package/skills/tech/financial-modeling/skills/3-statements/references/sec-filings.md +125 -0
- package/skills/tech/financial-modeling/skills/dcf-model/SKILL.md +1211 -0
- package/skills/tech/financial-modeling/skills/dcf-model/TROUBLESHOOTING.md +40 -0
- package/skills/tech/financial-modeling/skills/dcf-model/requirements.txt +8 -0
- package/skills/tech/financial-modeling/skills/dcf-model/scripts/validate_dcf.py +292 -0
- package/skills/tech/financial-modeling/skills/lbo-model/SKILL.md +236 -0
- package/skills/tech/financial-modeling/skills/merger-model/SKILL.md +108 -0
- package/skills/tech/intelligent-routing/SKILL.md +5 -5
- package/workflows/README.md +191 -191
- package/workflows/adr.md +174 -174
- package/workflows/changelog.md +74 -74
- package/workflows/compound.md +323 -323
- package/workflows/compound_health.md +74 -74
- package/workflows/create-agent-skill.md +139 -139
- package/workflows/cycle.md +144 -144
- package/workflows/deploy-docs.md +84 -84
- package/workflows/development-rules.md +37 -37
- package/workflows/doc.md +95 -95
- package/workflows/documentation-management.md +29 -29
- package/workflows/explore.md +146 -146
- package/workflows/generate_command.md +106 -106
- package/workflows/heal-skill.md +97 -97
- package/workflows/housekeeping.md +229 -229
- package/workflows/kit-setup.md +102 -102
- package/workflows/map-codebase.md +78 -0
- package/workflows/orchestration-protocol.md +38 -38
- package/workflows/plan-compound.md +439 -433
- package/workflows/plan_review.md +269 -248
- package/workflows/primary-workflow.md +32 -32
- package/workflows/promote_pattern.md +86 -86
- package/workflows/release-docs.md +82 -82
- package/workflows/report-bug.md +135 -135
- package/workflows/reproduce-bug.md +118 -118
- package/workflows/resolve_pr.md +133 -133
- package/workflows/resolve_todo.md +128 -128
- package/workflows/review-compound.md +376 -359
- package/workflows/skill-review.md +127 -127
- package/workflows/specs.md +257 -257
- package/workflows/triage-sprint.md +102 -102
- package/workflows/triage.md +152 -152
- package/workflows/work.md +399 -399
- package/workflows/xcode-test.md +93 -93
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# DCF Model Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
**When to read this file:** If recalc.py shows errors OR valuation results seem unreasonable OR case selector not working properly.
|
|
4
|
+
|
|
5
|
+
## Model Returns Error Values
|
|
6
|
+
|
|
7
|
+
### #REF! Errors
|
|
8
|
+
- Usually caused by formulas referencing wrong rows after headers were inserted
|
|
9
|
+
- Solution: Rebuild with correct row references, or start over following layout planning
|
|
10
|
+
- Prevention: Define all row positions BEFORE writing formulas
|
|
11
|
+
|
|
12
|
+
### #DIV/0! Errors
|
|
13
|
+
- Division by zero or empty cells
|
|
14
|
+
- Solution: Add IF statements to handle zeros: `=IF([Divisor]=0,0,[Numerator]/[Divisor])`
|
|
15
|
+
|
|
16
|
+
### #VALUE! Errors
|
|
17
|
+
- Wrong data type in calculation (text instead of number)
|
|
18
|
+
- Solution: Verify all inputs are formatted as numbers
|
|
19
|
+
|
|
20
|
+
## Valuation Seems Unreasonable
|
|
21
|
+
|
|
22
|
+
### Implied price far too high
|
|
23
|
+
- Check terminal value isn't >80% of EV
|
|
24
|
+
- Verify terminal growth < WACC
|
|
25
|
+
- Review if growth assumptions are realistic
|
|
26
|
+
- Consider if margins are too optimistic
|
|
27
|
+
|
|
28
|
+
### Implied price far too low
|
|
29
|
+
- Verify net debt vs net cash is correct
|
|
30
|
+
- Check if WACC is too high
|
|
31
|
+
- Review if projections are too conservative
|
|
32
|
+
- Consider if terminal growth is too low
|
|
33
|
+
|
|
34
|
+
## Case Selector Not Working
|
|
35
|
+
|
|
36
|
+
### Consolidation column not updating when switching scenarios
|
|
37
|
+
- Verify case selector cell contains 1, 2, or 3
|
|
38
|
+
- Check INDEX/OFFSET formulas reference correct row range and selector cell
|
|
39
|
+
- Ensure absolute references ($B$6) are used for selector
|
|
40
|
+
- Test by manually changing the selector cell and verifying projection values update
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
DCF Model Validation Script
|
|
4
|
+
Validates Excel DCF models for formula errors and common DCF mistakes
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DCFModelValidator:
|
|
14
|
+
"""Validates DCF models for errors and quality issues"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, excel_path: str):
|
|
17
|
+
try:
|
|
18
|
+
import openpyxl
|
|
19
|
+
except ImportError:
|
|
20
|
+
raise ImportError("openpyxl not installed. Run: pip install openpyxl")
|
|
21
|
+
|
|
22
|
+
self.excel_path = excel_path
|
|
23
|
+
self.openpyxl = openpyxl
|
|
24
|
+
|
|
25
|
+
if not Path(excel_path).exists():
|
|
26
|
+
raise FileNotFoundError(f"File not found: {excel_path}")
|
|
27
|
+
|
|
28
|
+
self.workbook_formulas = openpyxl.load_workbook(excel_path, data_only=False)
|
|
29
|
+
self.workbook_values = openpyxl.load_workbook(excel_path, data_only=True)
|
|
30
|
+
self.errors = []
|
|
31
|
+
self.warnings = []
|
|
32
|
+
self.info = []
|
|
33
|
+
|
|
34
|
+
def validate_all(self) -> dict:
|
|
35
|
+
"""
|
|
36
|
+
Run all validation checks
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Dict with validation results
|
|
40
|
+
"""
|
|
41
|
+
from datetime import datetime
|
|
42
|
+
|
|
43
|
+
self.check_sheet_structure()
|
|
44
|
+
self.check_formula_errors()
|
|
45
|
+
self.check_dcf_logic()
|
|
46
|
+
|
|
47
|
+
results = {
|
|
48
|
+
'file': self.excel_path,
|
|
49
|
+
'validation_date': datetime.now().isoformat(),
|
|
50
|
+
'status': 'PASS' if len(self.errors) == 0 else 'FAIL',
|
|
51
|
+
'error_count': len(self.errors),
|
|
52
|
+
'warning_count': len(self.warnings),
|
|
53
|
+
'errors': self.errors,
|
|
54
|
+
'warnings': self.warnings,
|
|
55
|
+
'info': self.info
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return results
|
|
59
|
+
|
|
60
|
+
def check_sheet_structure(self):
|
|
61
|
+
"""Verify required sheets exist"""
|
|
62
|
+
required_sheets = ['DCF', 'WACC', 'Sensitivity']
|
|
63
|
+
sheet_names = self.workbook_values.sheetnames
|
|
64
|
+
|
|
65
|
+
for sheet in required_sheets:
|
|
66
|
+
if sheet not in sheet_names:
|
|
67
|
+
self.warnings.append(f"Recommended sheet missing: {sheet}")
|
|
68
|
+
else:
|
|
69
|
+
self.info.append(f"Found sheet: {sheet}")
|
|
70
|
+
|
|
71
|
+
def check_formula_errors(self):
|
|
72
|
+
"""Check for Excel formula errors in all sheets"""
|
|
73
|
+
excel_errors = ['#VALUE!', '#DIV/0!', '#REF!', '#NAME?', '#NULL!', '#NUM!', '#N/A']
|
|
74
|
+
error_details = {err: [] for err in excel_errors}
|
|
75
|
+
total_errors = 0
|
|
76
|
+
total_formulas = 0
|
|
77
|
+
|
|
78
|
+
for sheet_name in self.workbook_values.sheetnames:
|
|
79
|
+
ws_values = self.workbook_values[sheet_name]
|
|
80
|
+
ws_formulas = self.workbook_formulas[sheet_name]
|
|
81
|
+
|
|
82
|
+
for row in ws_values.iter_rows():
|
|
83
|
+
for cell in row:
|
|
84
|
+
formula_cell = ws_formulas[cell.coordinate]
|
|
85
|
+
|
|
86
|
+
# Count formulas
|
|
87
|
+
if formula_cell.value and isinstance(formula_cell.value, str) and formula_cell.value.startswith('='):
|
|
88
|
+
total_formulas += 1
|
|
89
|
+
|
|
90
|
+
# Check for errors
|
|
91
|
+
if cell.value is not None and isinstance(cell.value, str):
|
|
92
|
+
for err in excel_errors:
|
|
93
|
+
if err in cell.value:
|
|
94
|
+
location = f"{sheet_name}!{cell.coordinate}"
|
|
95
|
+
error_details[err].append(location)
|
|
96
|
+
total_errors += 1
|
|
97
|
+
self.errors.append(f"{err} at {location}")
|
|
98
|
+
break
|
|
99
|
+
|
|
100
|
+
# Add summary info
|
|
101
|
+
self.info.append(f"Total formulas: {total_formulas}")
|
|
102
|
+
if total_errors == 0:
|
|
103
|
+
self.info.append("✓ No formula errors found")
|
|
104
|
+
else:
|
|
105
|
+
self.errors.append(f"Total formula errors: {total_errors}")
|
|
106
|
+
|
|
107
|
+
return error_details, total_errors
|
|
108
|
+
|
|
109
|
+
def check_dcf_logic(self):
|
|
110
|
+
"""Validate DCF-specific logic and calculations"""
|
|
111
|
+
self._check_terminal_growth_vs_wacc()
|
|
112
|
+
self._check_wacc_range()
|
|
113
|
+
self._check_terminal_value_proportion()
|
|
114
|
+
|
|
115
|
+
def _check_terminal_growth_vs_wacc(self):
|
|
116
|
+
"""Critical check: Terminal growth must be less than WACC"""
|
|
117
|
+
try:
|
|
118
|
+
dcf_sheet = self.workbook_values['DCF']
|
|
119
|
+
|
|
120
|
+
terminal_growth = None
|
|
121
|
+
wacc = None
|
|
122
|
+
|
|
123
|
+
# Search for terminal growth and WACC values
|
|
124
|
+
for row in dcf_sheet.iter_rows(max_row=100, max_col=20):
|
|
125
|
+
for cell in row:
|
|
126
|
+
if cell.value and isinstance(cell.value, str):
|
|
127
|
+
cell_str = cell.value.lower()
|
|
128
|
+
if 'terminal' in cell_str and 'growth' in cell_str:
|
|
129
|
+
# Look for value in adjacent cells
|
|
130
|
+
for offset in range(1, 5):
|
|
131
|
+
adjacent = dcf_sheet.cell(cell.row, cell.column + offset).value
|
|
132
|
+
if isinstance(adjacent, (int, float)) and 0 < adjacent < 1:
|
|
133
|
+
terminal_growth = adjacent
|
|
134
|
+
break
|
|
135
|
+
if 'wacc' in cell_str and wacc is None:
|
|
136
|
+
for offset in range(1, 5):
|
|
137
|
+
adjacent = dcf_sheet.cell(cell.row, cell.column + offset).value
|
|
138
|
+
if isinstance(adjacent, (int, float)) and 0 < adjacent < 1:
|
|
139
|
+
wacc = adjacent
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
if terminal_growth is not None and wacc is not None:
|
|
143
|
+
if terminal_growth >= wacc:
|
|
144
|
+
self.errors.append(
|
|
145
|
+
f"CRITICAL: Terminal growth ({terminal_growth:.2%}) >= WACC ({wacc:.2%}). "
|
|
146
|
+
"This creates infinite value and is mathematically invalid."
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
self.info.append(
|
|
150
|
+
f"✓ Terminal growth ({terminal_growth:.2%}) < WACC ({wacc:.2%})"
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
self.warnings.append("Could not locate terminal growth and WACC values")
|
|
154
|
+
|
|
155
|
+
except KeyError:
|
|
156
|
+
self.warnings.append("DCF sheet not found")
|
|
157
|
+
except Exception as e:
|
|
158
|
+
self.warnings.append(f"Could not validate terminal growth vs WACC: {str(e)}")
|
|
159
|
+
|
|
160
|
+
def _check_wacc_range(self):
|
|
161
|
+
"""Check if WACC is in reasonable range"""
|
|
162
|
+
try:
|
|
163
|
+
wacc_sheet = self.workbook_values.get('WACC') or self.workbook_values['DCF']
|
|
164
|
+
wacc = None
|
|
165
|
+
|
|
166
|
+
for row in wacc_sheet.iter_rows(max_row=100, max_col=20):
|
|
167
|
+
for cell in row:
|
|
168
|
+
if cell.value and isinstance(cell.value, str):
|
|
169
|
+
if 'wacc' in cell.value.lower():
|
|
170
|
+
for offset in range(1, 5):
|
|
171
|
+
adjacent = wacc_sheet.cell(cell.row, cell.column + offset).value
|
|
172
|
+
if isinstance(adjacent, (int, float)) and 0 < adjacent < 1:
|
|
173
|
+
wacc = adjacent
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
if wacc is not None:
|
|
177
|
+
if wacc < 0.05 or wacc > 0.20:
|
|
178
|
+
self.warnings.append(
|
|
179
|
+
f"WACC ({wacc:.2%}) is outside typical range (5%-20%). Verify calculation."
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
self.info.append(f"✓ WACC ({wacc:.2%}) in reasonable range")
|
|
183
|
+
else:
|
|
184
|
+
self.warnings.append("Could not locate WACC value")
|
|
185
|
+
|
|
186
|
+
except Exception as e:
|
|
187
|
+
self.warnings.append(f"Could not validate WACC range: {str(e)}")
|
|
188
|
+
|
|
189
|
+
def _check_terminal_value_proportion(self):
|
|
190
|
+
"""Check if terminal value is reasonable proportion of enterprise value"""
|
|
191
|
+
try:
|
|
192
|
+
dcf_sheet = self.workbook_values['DCF']
|
|
193
|
+
|
|
194
|
+
terminal_value = None
|
|
195
|
+
enterprise_value = None
|
|
196
|
+
|
|
197
|
+
for row in dcf_sheet.iter_rows(max_row=200, max_col=20):
|
|
198
|
+
for cell in row:
|
|
199
|
+
if cell.value and isinstance(cell.value, str):
|
|
200
|
+
cell_str = cell.value.lower()
|
|
201
|
+
if 'terminal' in cell_str and 'value' in cell_str and 'pv' in cell_str:
|
|
202
|
+
for offset in range(1, 5):
|
|
203
|
+
adjacent = dcf_sheet.cell(cell.row, cell.column + offset).value
|
|
204
|
+
if isinstance(adjacent, (int, float)) and adjacent > 0:
|
|
205
|
+
terminal_value = adjacent
|
|
206
|
+
break
|
|
207
|
+
if 'enterprise' in cell_str and 'value' in cell_str:
|
|
208
|
+
for offset in range(1, 5):
|
|
209
|
+
adjacent = dcf_sheet.cell(cell.row, cell.column + offset).value
|
|
210
|
+
if isinstance(adjacent, (int, float)) and adjacent > 0:
|
|
211
|
+
enterprise_value = adjacent
|
|
212
|
+
break
|
|
213
|
+
|
|
214
|
+
if terminal_value is not None and enterprise_value is not None and enterprise_value > 0:
|
|
215
|
+
proportion = terminal_value / enterprise_value
|
|
216
|
+
if proportion > 0.80:
|
|
217
|
+
self.warnings.append(
|
|
218
|
+
f"Terminal value is {proportion:.1%} of EV (typically should be 50-70%). "
|
|
219
|
+
"Model may be over-reliant on terminal assumptions."
|
|
220
|
+
)
|
|
221
|
+
elif proportion < 0.40:
|
|
222
|
+
self.warnings.append(
|
|
223
|
+
f"Terminal value is {proportion:.1%} of EV (typically should be 50-70%). "
|
|
224
|
+
"Check if terminal assumptions are too conservative."
|
|
225
|
+
)
|
|
226
|
+
else:
|
|
227
|
+
self.info.append(f"✓ Terminal value is {proportion:.1%} of EV")
|
|
228
|
+
else:
|
|
229
|
+
self.warnings.append("Could not locate terminal value and enterprise value")
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
self.warnings.append(f"Could not validate terminal value proportion: {str(e)}")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def validate_dcf_model(excel_path: str) -> dict:
|
|
237
|
+
"""
|
|
238
|
+
Validate a DCF model Excel file
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
excel_path: Path to Excel DCF model
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Dict with validation results
|
|
245
|
+
"""
|
|
246
|
+
validator = DCFModelValidator(excel_path)
|
|
247
|
+
return validator.validate_all()
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def main():
|
|
251
|
+
"""Command-line interface"""
|
|
252
|
+
if len(sys.argv) < 2:
|
|
253
|
+
print("Usage: python validate_dcf.py <excel_file> [output.json]")
|
|
254
|
+
print("\nValidates DCF model for:")
|
|
255
|
+
print(" - Formula errors (#REF!, #DIV/0!, etc.)")
|
|
256
|
+
print(" - Terminal growth < WACC (critical)")
|
|
257
|
+
print(" - WACC in reasonable range (5-20%)")
|
|
258
|
+
print(" - Terminal value proportion of EV (40-80%)")
|
|
259
|
+
print("\nReturns JSON with errors, warnings, and info")
|
|
260
|
+
print("\nExample: python validate_dcf.py model.xlsx")
|
|
261
|
+
print("Example: python validate_dcf.py model.xlsx results.json")
|
|
262
|
+
sys.exit(1)
|
|
263
|
+
|
|
264
|
+
excel_file = sys.argv[1]
|
|
265
|
+
output_file = sys.argv[2] if len(sys.argv) > 2 else None
|
|
266
|
+
|
|
267
|
+
try:
|
|
268
|
+
results = validate_dcf_model(excel_file)
|
|
269
|
+
|
|
270
|
+
# Print results
|
|
271
|
+
print(json.dumps(results, indent=2))
|
|
272
|
+
|
|
273
|
+
# Save to file if requested
|
|
274
|
+
if output_file:
|
|
275
|
+
with open(output_file, 'w') as f:
|
|
276
|
+
json.dump(results, f, indent=2)
|
|
277
|
+
|
|
278
|
+
# Exit with error code if validation failed
|
|
279
|
+
sys.exit(0 if results['status'] == 'PASS' else 1)
|
|
280
|
+
|
|
281
|
+
except Exception as e:
|
|
282
|
+
error_result = {
|
|
283
|
+
'file': excel_file,
|
|
284
|
+
'status': 'ERROR',
|
|
285
|
+
'error': str(e)
|
|
286
|
+
}
|
|
287
|
+
print(json.dumps(error_result, indent=2))
|
|
288
|
+
sys.exit(1)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if __name__ == "__main__":
|
|
292
|
+
main()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lbo-model
|
|
3
|
+
description: This skill should be used when completing LBO (Leveraged Buyout) model templates in Excel for private equity transactions, deal materials, or investment committee presentations. The skill fills in formulas, validates calculations, and ensures professional formatting standards that adapt to any template structure.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## TEMPLATE REQUIREMENT
|
|
9
|
+
|
|
10
|
+
**This skill uses templates for LBO models. Always check for an attached template file first.**
|
|
11
|
+
|
|
12
|
+
Before starting any LBO model:
|
|
13
|
+
1. **If a template file is attached/provided**: Use that template's structure exactly - copy it and populate with the user's data
|
|
14
|
+
2. **If no template is attached**: Ask the user: *"Do you have a specific LBO template you'd like me to use? If not, I can use the standard template which includes Sources & Uses, Operating Model, Debt Schedule, and Returns Analysis."*
|
|
15
|
+
3. **If using the standard template**: Copy `examples/LBO_Model.xlsx` as your starting point and populate it with the user's assumptions
|
|
16
|
+
|
|
17
|
+
**IMPORTANT**: When a file like `LBO_Model.xlsx` is attached, you MUST use it as your template - do not build from scratch. Even if the template seems complex or has more features than needed, copy it and adapt it to the user's requirements. Never decide to "build from scratch" when a template is provided.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## CRITICAL INSTRUCTIONS FOR CLAUDE - READ FIRST
|
|
22
|
+
|
|
23
|
+
### Core Principles
|
|
24
|
+
* **Every calculation must be an Excel formula** - NEVER compute values in Python and hardcode results into cells. The model must be dynamic and update when inputs change.
|
|
25
|
+
* **Use the template structure** - Follow the organization in `examples/LBO_Model.xlsx` or the user's provided template. Do not invent your own layout.
|
|
26
|
+
* **Use proper cell references** - All formulas should reference the appropriate cells. Never type numbers that should come from other cells.
|
|
27
|
+
* **Maintain sign convention consistency** - Follow whatever sign convention the template uses (some use negative for outflows, some use positive). Be consistent throughout.
|
|
28
|
+
* **Work section by section** - Complete one section fully before moving to the next, as later sections often depend on earlier ones.
|
|
29
|
+
|
|
30
|
+
### Formula Color Conventions
|
|
31
|
+
* **Blue (0000FF)**: Hardcoded inputs - typed numbers that don't reference other cells
|
|
32
|
+
* **Black (000000)**: Formulas with calculations - any formula using operators or functions (`=B4*B5`, `=SUM()`, `=-MAX(0,B4)`)
|
|
33
|
+
* **Purple (800080)**: Links to cells on the **same tab** - direct references with no calculation (`=B9`, `=B45`)
|
|
34
|
+
* **Green (008000)**: Links to cells on **different tabs** - cross-sheet references (`=Assumptions!B5`, `='Operating Model'!C10`)
|
|
35
|
+
|
|
36
|
+
### Number Formatting Standards
|
|
37
|
+
* **Currency**: `$#,##0;($#,##0);"-"` or `$#,##0.0` depending on template
|
|
38
|
+
* **Percentages**: `0.0%` (one decimal)
|
|
39
|
+
* **Multiples**: `0.0"x"` (one decimal)
|
|
40
|
+
* **MOIC/Detailed Ratios**: `0.00"x"` (two decimals for precision)
|
|
41
|
+
* **All numeric cells**: Right-aligned
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### Clarify Requirements First
|
|
46
|
+
|
|
47
|
+
Before filling any formulas:
|
|
48
|
+
|
|
49
|
+
* **Examine the template structure** - Identify all sections, understand the timeline (which columns are which periods), note any existing formulas
|
|
50
|
+
* **Ask the user if anything is unclear** - If the template structure, calculation methods, or requirements are ambiguous, ask before proceeding
|
|
51
|
+
* **Confirm key assumptions** - Any key inputs, calculation preferences, or specific requirements
|
|
52
|
+
* **ONLY AFTER understanding the template**, proceed to fill in formulas
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## TEMPLATE ANALYSIS PHASE - DO THIS FIRST
|
|
57
|
+
|
|
58
|
+
Before filling any formulas, examine the template thoroughly:
|
|
59
|
+
|
|
60
|
+
1. **Map the structure** - Identify where each section lives and how they relate to each other. Note which sections feed into others.
|
|
61
|
+
|
|
62
|
+
2. **Understand the timeline** - Which columns represent which periods? Is there a "Closing" or "Pro Forma" column? Where does the projection period start?
|
|
63
|
+
|
|
64
|
+
3. **Identify input vs formula cells** - Templates often use color coding, borders, or shading to indicate which cells need inputs vs formulas. Respect these conventions.
|
|
65
|
+
|
|
66
|
+
4. **Read existing labels carefully** - The row labels tell you exactly what calculation is expected. Don't assume - read what the template is asking for.
|
|
67
|
+
|
|
68
|
+
5. **Check for existing formulas** - Some templates come partially filled. Don't overwrite working formulas unless specifically asked.
|
|
69
|
+
|
|
70
|
+
6. **Note template-specific conventions** - Sign conventions, subtotal structures, how sections are organized, whether there are separate tabs for different components, etc.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## FILLING FORMULAS - GENERAL APPROACH
|
|
75
|
+
|
|
76
|
+
For each cell that needs a formula, follow this hierarchy:
|
|
77
|
+
|
|
78
|
+
### Step 1: Check the Template
|
|
79
|
+
* Does the cell already have a formula? If yes, verify it's correct and move on.
|
|
80
|
+
* Is there a comment or note indicating the expected calculation?
|
|
81
|
+
* Does the row/column label make the calculation obvious?
|
|
82
|
+
* Do neighboring cells show a pattern you should follow?
|
|
83
|
+
|
|
84
|
+
### Step 2: Check the User's Instructions
|
|
85
|
+
* Did the user specify a particular calculation method?
|
|
86
|
+
* Are there stated assumptions that affect this formula?
|
|
87
|
+
* Any special requirements mentioned?
|
|
88
|
+
|
|
89
|
+
### Step 3: Apply Standard Practice
|
|
90
|
+
* If neither template nor user specifies, use standard LBO modeling conventions
|
|
91
|
+
* Document any assumptions you make
|
|
92
|
+
* If genuinely uncertain, ask the user
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## COMMON PROBLEM AREAS
|
|
97
|
+
|
|
98
|
+
The following calculation patterns frequently cause issues across LBO models. Pay special attention when you encounter these:
|
|
99
|
+
|
|
100
|
+
### Balancing Sections
|
|
101
|
+
* When two sections must equal (e.g., Sources = Uses), one item is typically the "plug" (balancing figure)
|
|
102
|
+
* Identify which item is the plug and calculate it as the difference
|
|
103
|
+
|
|
104
|
+
### Tax Calculations
|
|
105
|
+
* Tax formulas should only reference the relevant income line and tax rate
|
|
106
|
+
* Should NOT reference unrelated sections (e.g., debt schedules)
|
|
107
|
+
* Consider whether losses create tax shields or are simply ignored
|
|
108
|
+
|
|
109
|
+
### Interest and Circular References
|
|
110
|
+
* Interest calculations can create circularity if they reference balances affected by cash flows
|
|
111
|
+
* Use **Beginning Balance** (not average or ending) to break circular references
|
|
112
|
+
* Pattern: Interest → Cash Flow → Paydown → Ending Balance (if interest uses ending balance, this circles back)
|
|
113
|
+
|
|
114
|
+
### Debt Paydown / Cash Sweeps
|
|
115
|
+
* When multiple debt tranches exist, there's usually a priority order
|
|
116
|
+
* Cash sweep should respect the priority waterfall
|
|
117
|
+
* Balances cannot go negative - use MAX or MIN functions appropriately
|
|
118
|
+
|
|
119
|
+
### Returns Calculations (IRR/MOIC)
|
|
120
|
+
* Cash flows must have correct signs: Investment = negative, Proceeds = positive
|
|
121
|
+
* If using XIRR, need corresponding dates
|
|
122
|
+
* If using IRR, cash flows should be in consecutive periods
|
|
123
|
+
* MOIC = Total Proceeds / Total Investment
|
|
124
|
+
|
|
125
|
+
### Sensitivity Tables
|
|
126
|
+
* Excel's DATA TABLE function may not work with openpyxl
|
|
127
|
+
* May need explicit formulas that reference row/column headers
|
|
128
|
+
* Each cell should show a DIFFERENT value - if all same, formulas aren't varying correctly
|
|
129
|
+
* Use mixed references (e.g., $A5 for row input, B$4 for column input)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## VERIFICATION CHECKLIST - RUN AFTER COMPLETION
|
|
134
|
+
|
|
135
|
+
### Run Formula Validation
|
|
136
|
+
```bash
|
|
137
|
+
python /mnt/skills/public/xlsx/recalc.py model.xlsx
|
|
138
|
+
```
|
|
139
|
+
Must return success with zero errors.
|
|
140
|
+
|
|
141
|
+
### Section Balancing
|
|
142
|
+
- [ ] Any sections that must balance (Sources/Uses, Assets/Liabilities) balance exactly
|
|
143
|
+
- [ ] Plug items are calculated correctly as the balancing figure
|
|
144
|
+
- [ ] Amounts that should match across sections are consistent
|
|
145
|
+
|
|
146
|
+
### Income/Operating Projections
|
|
147
|
+
- [ ] Revenue/top-line builds correctly from drivers or growth rates
|
|
148
|
+
- [ ] All cost and expense items calculated appropriately
|
|
149
|
+
- [ ] Subtotals and totals sum correctly
|
|
150
|
+
- [ ] Margins and ratios are reasonable
|
|
151
|
+
- [ ] Links to assumptions are correct
|
|
152
|
+
|
|
153
|
+
### Balance Sheet (if applicable)
|
|
154
|
+
- [ ] Assets = Liabilities + Equity (must balance)
|
|
155
|
+
- [ ] All items link to appropriate schedules or roll-forwards
|
|
156
|
+
- [ ] Beginning balances = prior period ending balances
|
|
157
|
+
- [ ] Check row included and shows zero
|
|
158
|
+
|
|
159
|
+
### Cash Flow (if applicable)
|
|
160
|
+
- [ ] Starts with correct income figure
|
|
161
|
+
- [ ] Non-cash items added/subtracted appropriately
|
|
162
|
+
- [ ] Working capital changes have correct signs
|
|
163
|
+
- [ ] Ending Cash = Beginning Cash + Net Cash Flow
|
|
164
|
+
- [ ] Cash balances are consistent across statements
|
|
165
|
+
|
|
166
|
+
### Supporting Schedules
|
|
167
|
+
- [ ] Roll-forward schedules balance (Beginning + Changes = Ending)
|
|
168
|
+
- [ ] Schedules link correctly to main statements
|
|
169
|
+
- [ ] Calculated items use appropriate drivers
|
|
170
|
+
- [ ] All periods are calculated consistently
|
|
171
|
+
|
|
172
|
+
### Debt/Financing Schedules (if applicable)
|
|
173
|
+
- [ ] Beginning balances tie to sources or prior period
|
|
174
|
+
- [ ] Interest calculated on appropriate balance (typically beginning)
|
|
175
|
+
- [ ] Paydowns respect cash availability and priority
|
|
176
|
+
- [ ] Ending balances cannot be negative
|
|
177
|
+
- [ ] Totals sum tranches correctly
|
|
178
|
+
|
|
179
|
+
### Returns/Output Analysis
|
|
180
|
+
- [ ] Exit/terminal values calculated correctly
|
|
181
|
+
- [ ] All relevant adjustments included
|
|
182
|
+
- [ ] Cash flow signs are correct (negative for investment, positive for proceeds)
|
|
183
|
+
- [ ] IRR/MOIC formulas reference complete ranges
|
|
184
|
+
- [ ] Results are reasonable for the scenario
|
|
185
|
+
|
|
186
|
+
### Sensitivity Tables (if applicable)
|
|
187
|
+
- [ ] Row and column headers contain appropriate input values
|
|
188
|
+
- [ ] Each data cell contains a formula (not hardcoded)
|
|
189
|
+
- [ ] Each data cell shows a DIFFERENT value
|
|
190
|
+
- [ ] Values move in expected directions
|
|
191
|
+
- [ ] Base case appears where headers match base assumptions
|
|
192
|
+
|
|
193
|
+
### Formatting
|
|
194
|
+
- [ ] Hardcoded inputs are blue (0000FF)
|
|
195
|
+
- [ ] Calculated formulas are black (000000)
|
|
196
|
+
- [ ] Same-tab links are purple (800080)
|
|
197
|
+
- [ ] Cross-tab links are green (008000)
|
|
198
|
+
- [ ] All numbers are right-aligned
|
|
199
|
+
- [ ] Appropriate number formats applied throughout
|
|
200
|
+
- [ ] No cells show error values (#REF!, #DIV/0!, #VALUE!, #NAME?)
|
|
201
|
+
|
|
202
|
+
### Logical Sanity Checks
|
|
203
|
+
- [ ] Numbers are reasonable order of magnitude
|
|
204
|
+
- [ ] Trends make sense (growth, decline, stabilization as expected)
|
|
205
|
+
- [ ] No obviously wrong values (negative where should be positive, impossible percentages, etc.)
|
|
206
|
+
- [ ] Key outputs are within reasonable ranges for the type of analysis
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## COMMON ERRORS TO AVOID
|
|
211
|
+
|
|
212
|
+
| Error | What Goes Wrong | How to Fix |
|
|
213
|
+
|-------|-----------------|------------|
|
|
214
|
+
| Hardcoding calculated values | Model doesn't update when inputs change | Always use formulas that reference source cells |
|
|
215
|
+
| Wrong cell references after copying | Formulas point to wrong cells | Verify all links, use appropriate $ anchoring |
|
|
216
|
+
| Circular reference errors | Model can't calculate | Use beginning balances for interest-type calcs, break the circle |
|
|
217
|
+
| Sections don't balance | Totals that should match don't | Ensure one item is the plug (calculated as difference) |
|
|
218
|
+
| Negative balances where impossible | Paying/using more than available | Use MAX(0, ...) or MIN functions appropriately |
|
|
219
|
+
| IRR/return errors | Wrong signs or incomplete ranges | Check cash flow signs and ensure formula covers all periods |
|
|
220
|
+
| Sensitivity table shows same value | Formula not varying with inputs | Check cell references - need mixed references ($A5, B$4) |
|
|
221
|
+
| Roll-forwards don't tie | Beginning ≠ prior ending | Verify links between periods |
|
|
222
|
+
| Inconsistent sign conventions | Additions become subtractions or vice versa | Follow template's convention consistently throughout |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## WORKING WITH THE USER
|
|
227
|
+
|
|
228
|
+
* **If the template structure is unclear**, ask before proceeding
|
|
229
|
+
* **If the user's requirements conflict with the template**, confirm their preference
|
|
230
|
+
* **After completing each major section**, offer to show the work or run verification
|
|
231
|
+
* **If errors are found during verification**, fix them before moving to the next section
|
|
232
|
+
* **Show your work** - explain key formulas or assumptions when helpful
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
**This skill produces investment banking-quality LBO models by filling templates with correct formulas, proper formatting, and validated calculations. The skill adapts to any template structure while ensuring financial accuracy and professional presentation standards.**
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Merger Model
|
|
2
|
+
|
|
3
|
+
description: Build accretion/dilution analysis for M&A transactions. Models pro forma EPS impact, synergy sensitivities, and purchase price allocation. Use when evaluating a potential acquisition, preparing merger consequences analysis for a pitch, or advising on deal terms. Triggers on "merger model", "accretion dilution", "M&A model", "pro forma EPS", "merger consequences", or "deal impact analysis".
|
|
4
|
+
|
|
5
|
+
## Workflow
|
|
6
|
+
|
|
7
|
+
### Step 1: Gather Inputs
|
|
8
|
+
|
|
9
|
+
**Acquirer:**
|
|
10
|
+
- Company name, current share price, shares outstanding
|
|
11
|
+
- LTM and NTM EPS (GAAP and adjusted)
|
|
12
|
+
- P/E multiple
|
|
13
|
+
- Pre-tax cost of debt, tax rate
|
|
14
|
+
- Cash on balance sheet, existing debt
|
|
15
|
+
|
|
16
|
+
**Target:**
|
|
17
|
+
- Company name, current share price, shares outstanding (if public)
|
|
18
|
+
- LTM and NTM EPS or net income
|
|
19
|
+
- Enterprise value or equity value
|
|
20
|
+
|
|
21
|
+
**Deal Terms:**
|
|
22
|
+
- Offer price per share (or premium to current)
|
|
23
|
+
- Consideration mix: % cash vs. % stock
|
|
24
|
+
- New debt raised to fund cash portion
|
|
25
|
+
- Expected synergies (revenue and cost) and phase-in timeline
|
|
26
|
+
- Transaction fees and financing costs
|
|
27
|
+
- Expected close date
|
|
28
|
+
|
|
29
|
+
### Step 2: Purchase Price Analysis
|
|
30
|
+
|
|
31
|
+
| Item | Value |
|
|
32
|
+
|------|-------|
|
|
33
|
+
| Offer price per share | |
|
|
34
|
+
| Premium to current | |
|
|
35
|
+
| Equity value | |
|
|
36
|
+
| Plus: net debt assumed | |
|
|
37
|
+
| Enterprise value | |
|
|
38
|
+
| EV / EBITDA implied | |
|
|
39
|
+
| P/E implied | |
|
|
40
|
+
|
|
41
|
+
### Step 3: Sources & Uses
|
|
42
|
+
|
|
43
|
+
| Sources | $ | Uses | $ |
|
|
44
|
+
|---------|---|------|---|
|
|
45
|
+
| New debt | | Equity purchase price | |
|
|
46
|
+
| Cash on hand | | Refinance target debt | |
|
|
47
|
+
| New equity issued | | Transaction fees | |
|
|
48
|
+
| | | Financing fees | |
|
|
49
|
+
| **Total** | | **Total** | |
|
|
50
|
+
|
|
51
|
+
### Step 4: Pro Forma EPS (Accretion / Dilution)
|
|
52
|
+
|
|
53
|
+
Calculate year-by-year (Year 1-3):
|
|
54
|
+
|
|
55
|
+
| | Standalone | Pro Forma | Accretion/(Dilution) |
|
|
56
|
+
|---|-----------|-----------|---------------------|
|
|
57
|
+
| Acquirer net income | | | |
|
|
58
|
+
| Target net income | | | |
|
|
59
|
+
| Synergies (after tax) | | | |
|
|
60
|
+
| Foregone interest on cash (after tax) | | | |
|
|
61
|
+
| New debt interest (after tax) | | | |
|
|
62
|
+
| Intangible amortization (after tax) | | | |
|
|
63
|
+
| Pro forma net income | | | |
|
|
64
|
+
| Pro forma shares | | | |
|
|
65
|
+
| **Pro forma EPS** | | | |
|
|
66
|
+
| **Accretion / (Dilution) %** | | | |
|
|
67
|
+
|
|
68
|
+
### Step 5: Sensitivity Analysis
|
|
69
|
+
|
|
70
|
+
**Accretion/Dilution vs. Synergies and Offer Premium:**
|
|
71
|
+
|
|
72
|
+
| | $0M syn | $25M syn | $50M syn | $75M syn | $100M syn |
|
|
73
|
+
|---|---------|----------|----------|----------|-----------|
|
|
74
|
+
| 15% premium | | | | | |
|
|
75
|
+
| 20% premium | | | | | |
|
|
76
|
+
| 25% premium | | | | | |
|
|
77
|
+
| 30% premium | | | | | |
|
|
78
|
+
|
|
79
|
+
**Accretion/Dilution vs. Cash/Stock Mix:**
|
|
80
|
+
|
|
81
|
+
| | 100% cash | 75/25 | 50/50 | 25/75 | 100% stock |
|
|
82
|
+
|---|-----------|-------|-------|-------|------------|
|
|
83
|
+
| Year 1 | | | | | |
|
|
84
|
+
| Year 2 | | | | | |
|
|
85
|
+
|
|
86
|
+
### Step 6: Breakeven Synergies
|
|
87
|
+
|
|
88
|
+
Calculate the minimum synergies needed for the deal to be EPS-neutral in Year 1.
|
|
89
|
+
|
|
90
|
+
### Step 7: Output
|
|
91
|
+
|
|
92
|
+
- Excel workbook with:
|
|
93
|
+
- Assumptions tab
|
|
94
|
+
- Sources & uses
|
|
95
|
+
- Pro forma income statement
|
|
96
|
+
- Accretion/dilution summary
|
|
97
|
+
- Sensitivity tables
|
|
98
|
+
- Breakeven analysis
|
|
99
|
+
- One-page merger consequences summary for pitch book
|
|
100
|
+
|
|
101
|
+
## Important Notes
|
|
102
|
+
|
|
103
|
+
- Always show both GAAP and adjusted (cash) EPS where relevant
|
|
104
|
+
- Stock deals: use acquirer's current price for exchange ratio, note dilution from new shares
|
|
105
|
+
- Include purchase price allocation — goodwill and intangible amortization matter for GAAP EPS
|
|
106
|
+
- Synergy phase-in is critical — Year 1 is often only 25-50% of run-rate synergies
|
|
107
|
+
- Don't forget foregone interest income on cash used and new interest expense on debt raised
|
|
108
|
+
- Tax rate on synergies and interest adjustments should match the acquirer's marginal rate
|