lyndonkl/claude/cost-of-capital-toolkit

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Estimates discount rates and the optimal financing mix — riskfree rate in any currency, equity risk premium including country risk, bottom-up and total betas, synthetic credit ratings from interest coverage, cost of debt, market value of debt, WACC, the implied equity risk premium solved from current index levels, and the cost-of-capital schedule across debt ratios that locates the optimal debt ratio, with an APV cross-check and a stress test under rating constraints. Bundles Damodaran's rating and spread tables, Altman default probabilities, industry-average betas and multiples, and country risk premiums, each tagged with its vintage. Use when estimating a discount rate, WACC, hurdle rate, cost of equity or cost of debt, unlevering or relevering a beta, when a company has no credit rating, when estimating the equity risk premium priced into the market, when looking up a sector beta or country risk premium, when converting a rate between currencies, or when finding or stressing an optimal capital structure.

Install

npx vskill@latest install lyndonkl/claude/cost-of-capital-toolkit

SKILL.md

Cost of capital toolkit

Every discounted valuation needs a rate. Most valuation errors that survive review are rate errors. A rate built in one currency gets applied to cash flows in another. A regression beta describes a period that no longer matches the business. Book weights sit where market weights belong.

The arithmetic is fully scripted. Your job is choosing the inputs — which comparables, which premium estimator, gross or net debt — and defending those choices.

The scripts

Two of them, both pure standard library with nothing to install. Every subcommand takes JSON on stdin (or --in FILE) and prints JSON.

resources/costofcapital.py does the arithmetic.

bash
python3 resources/costofcapital.py <subcommand> --example # show input shape
python3 resources/costofcapital.py <subcommand> --in payload.json
python3 resources/costofcapital.py selftest # verify the engine
SubcommandTurns thisInto this
ratingEBIT and interest expensesynthetic rating, default spread, pre-tax and after-tax cost of debt
betacomparable betas, or one levered betaunlevered, relevered, bottom-up, or total beta
mv-debtbook debt, interest expense, maturitymarket value of debt
wacccomponent costs and valuesWACC with weights
debt-scheduleunlevered beta, EBIT, firm valuecost of capital at every debt ratio, the optimum, and the value of moving there
implied-erpindex level and expected cash flowsthe expected return and equity risk premium the market is pricing in
apvequity, debt, tax rate, bankruptcy costunlevered value, tax shield and expected distress cost at every debt ratio
stressa debt-schedule payload plus haircuts or a rating floorhow far the optimum moves under weaker EBIT, and what a rating floor costs
convert-ratea rate and two inflation ratesthe same rate in another currency

resources/reference_data.py serves the bundled tables. Every other engine reads its industry and country numbers through here, so a valuation cannot quietly mix a beta from one year with a country premium from another.

bash
python3 resources/reference_data.py <subcommand> --example
python3 resources/reference_data.py <subcommand> --in payload.json
python3 resources/reference_data.py selftest
SubcommandTurns thisInto this
lookupan industry, country or region namethe full reference row, tagged with its vintage
erp-for-operationsrevenue shares by countrythe revenue-weighted equity risk premium, and the cost of equity if you add a beta
vintagea valuation datethe as_of of every bundled table, and a warning for each one the date has outrun

Run selftest on both after editing anything. Between them they check the engines against worked examples from the source models, including a full cost-of-capital build that reproduces its sheet to eight decimals.

Build the rate in this order

Each step feeds the next. Do not skip ahead: a beta is meaningless until you know the currency, and weights are meaningless until debt is at market value.

Cost of capital progress:
- [ ] 1. Fix the currency, and the riskfree rate in it
- [ ] 2. Build the equity risk premium, including country risk
- [ ] 3. Estimate the beta bottom-up
- [ ] 4. Estimate the cost of debt
- [ ] 5. Weight at market values and assemble
- [ ] 6. Check consistency
1. Currency and riskfree rate

The currency of the rate must match the currency of the cash flows. That is a hard constraint, not a preference — mismatching them builds an inflation differential into the answer that has nothing to do with the business.

Take the long-term government bond yield when the government is default-free. When it is not, strip the sovereign default spread out of the local bond yield:

riskfree rate = local government bond yield − sovereign default spread

Get the sovereign spread from a rating-based table, a sovereign CDS, or the gap between the government's local and hard-currency bonds. If no local bond exists, build the rate from a mature-market rate and the inflation differential instead. Details and the negative-rate case: resources/methodology.md.

Resist the urge to "normalize" a low riskfree rate upward. Doing so while leaving the equity risk premium alone quietly raises every discount rate and understates every company. If the rate looks wrong, change the cash flows, not the anchor.

2. Equity risk premium

Two layers. Start with a mature-market premium, then add country risk for where the company actually operates, not where it is incorporated.

For the mature-market layer, compute the implied premium rather than reaching for a historical average. Take today's index level as the price, forecast the cash the index will return to its investors, and solve for the rate that makes the two agree. That rate is the expected return on stocks; subtract the riskfree rate and the rest is the premium:

bash
python3 resources/costofcapital.py implied-erp --in index.json

Supply the cash flows one of three ways: an explicit cash_flows list, an earnings path with payout_ratios, or a base_cash_flow (or dividend_yield) with a growth_rate. Whichever you use, the cash flow is dividends plus buybacks, not dividends alone. Buybacks were 68.89 of the S&P 500's 127.78 in 2020; leaving them out roughly halves the answer. Terminal growth defaults to the riskfree rate and is capped there, because no perpetual growth rate can outrun the economy it grows in.

Why bother: the historical average is a mean with a standard error of roughly two points on a five-point estimate, which is wide enough to swallow the number whole. The implied premium has no standard error at all, and it moves — 4.83% in February 2020, 7.75% at the March bottom, 5.35% by November. Re-run it whenever the market moves and record the date you used. The same procedure works on any index: feed it the local level, the local cash yield and the local riskfree rate.

Then the country layer:

company ERP = mature market ERP + Σ (revenue share by country × country risk premium)

A country risk premium is the sovereign default spread scaled up for equity's greater volatility. Weighting by operations matters: a Brazilian company earning most of its revenue in the United States does not carry Brazil's full risk, and a US-incorporated company earning most of its revenue in Brazil does.

bash
echo '{"operations": [{"country": "Brazil", "revenue": 130},
{"country": "Canada", "revenue": 23}]}' \
| python3 resources/reference_data.py erp-for-operations

Rows name a country or a region. Where a filer reports a bucket that maps to nothing clean — "rest of world", "Eurasia", "Pacific" — give that row its own erp and say in the writeup where the number came from. Weight by whatever measure locates the risk: revenue usually, production for a resource company, assets for a manufacturer. Add a riskfree_rate and a beta and the answer carries a cost of equity under both attachments, adding the country premium and scaling it by beta, which on real emerging market cases can differ by several points.

3. Beta

Use a bottom-up beta. Regression betas carry standard errors so large the point estimate is rarely usable, and they describe a past business mix rather than the current one.

bash
python3 resources/costofcapital.py beta --in businesses.json

Take the median unlevered beta of comparable firms in each business the company operates in, weight by each business's estimated value, then relever at the company's own debt-to-equity ratio:

levered beta = unlevered beta × (1 + (1 − tax rate) × debt/equity)

Weight by value, and when segment values are not disclosed, approximate them as segment revenue times a sector EV/Sales multiple. Both numbers come out of the same lookup:

bash
echo '{"industry": "Aerospace/Defense",
"fields": ["unlevered_beta", "ev_sales"]}' \
| python3 resources/reference_data.py lookup

Names must match the table, but case and stray whitespace do not matter, and a miss comes back with the near matches rather than nothing. Watch for labels the source sheet truncated mid-word — Insurance (Prop/Cas.) is the real key, not a typo.

Use a total beta — operation: total — when valuing a company for an owner who cannot diversify, typically a private business. It scales the market beta up by the inverse of the correlation with the market, charging the owner for the firm-specific risk a diversified investor would shed.

4. Cost of debt

What matters is what the company would pay to borrow today, not the coupon on debt it issued years ago and not the rate a parent guarantees.

Prefer, in order: the yield to maturity on the company's own traded long-term bonds; the spread implied by its agency rating; a synthetic rating from interest coverage.

bash
echo '{"ebit": 2000, "interest_expense": 250, "riskfree_rate": 0.04,
"marginal_tax_rate": 0.25, "table": "large_manufacturing"}' \
| python3 resources/costofcapital.py rating

Pick the table that matches the company: large_manufacturing for large non-financial firms, small_or_risky for smaller or more volatile ones (the same coverage buys a worse rating), financial_service for banks and insurers.

pre-tax cost of debt = riskfree rate + company default spread + country default spread

Only the marginal tax rate matters for the after-tax cost, and only to the extent there is income to shelter — the engine caps the benefit when interest exceeds EBIT.

Capitalized leases create a circularity. Discounting lease commitments needs a cost of debt; a synthetic rating needs interest coverage, which lease interest changes. Iterate: compute a rate, capitalize leases, recompute coverage, recompute the rate, until it stops moving. debt-schedule already does this internally.

5. Weights and assembly

Weight at market values. Book weights systematically understate equity for a profitable company. Convert book debt to market by treating all of it as one coupon bond:

bash
python3 resources/costofcapital.py mv-debt --in debt.json

Use the weighted-average maturity of outstanding debt; where it is not disclosed, three years is the working default. Add capitalized lease debt afterwards — it is already a present value.

WACC = cost of equity × E/(D+E+P)

  • pre-tax cost of debt × (1 − tax rate) × D/(D+E+P)
  • cost of preferred × P/(D+E+P)

Preferred stock is a third component when it is material; below about 5% of capital, fold it into debt rather than carrying a third term.

6. Consistency checks
  • Currency of the rate equals currency of the cash flows.
  • Weights sum to one and use market values.
  • The tax rate used to relever the beta is the same one used for the after-tax cost of debt.
  • Gross debt throughout, or net debt throughout — never mixed.
  • The levered beta reflects the company's current debt ratio, not the comparables'.

Finding the optimal debt ratio

The same machinery run in a loop. At each candidate debt ratio the engine relevers the beta, re-prices the debt through a fresh synthetic rating, caps the tax benefit at available income, and computes the cost of capital. The ratio with the lowest cost of capital is the optimum, because the same cash flows discounted at a lower rate are worth more.

bash
python3 resources/costofcapital.py debt-schedule --in firm.json

Read the result with judgment:

  • The curve is usually flat near the bottom. A move from 30% to 40% debt that saves

four basis points is not an argument for anything. Look at the shape, not just the minimum.

  • Banks are excluded. For a financial service firm, regulatory capital sets the

financing mix. This calculation does not apply.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
162
Repository forks
24
7-day trend score
25

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/lyndonkl/claude/cost-of-capital-toolkit/badge)](https://verified-skill.com/skills/lyndonkl/claude/cost-of-capital-toolkit)

Something wrong with this skill or its page? Tell us.