The user wants to understand how MetricDuck computes Caterpillar's (CAT) ROIC for fiscal year 2025, walking the derivation tree down to as-filed numbers. Let me start by getting the metric lineage for ROIC.
Question
How does MetricDuck compute Caterpillar's (CAT) return on invested capital (ROIC) for fiscal year 2025? Walk the derivation tree — each input and the figures it's built from — down to the as-filed numbers.
TL;DR
Auditing a computed ratio — analysts distrust black-box metrics, so MetricDuck exposes the full derivation tree (ROIC → NOPAT ÷ invested capital → … → as-filed XBRL), every input traceable to the 10-K.
Sources (7) — every cited figure below traces to one of these
- [1]Caterpillar FY2025 10-K · ROIC derivation inputs (SEC accession 0000018230-26-000008) sec.gov/…/0000018230-26-000008-index.htm
- [2]CAT · 10-K sec.gov/…/0000018230-25-000008-index.htm
- [3]CAT · 10-K sec.gov/…/0000018230-24-000009-index.htm
- [4]CAT · 10-K sec.gov/…/0000018230-23-000011-index.htm
- [5]CAT · 10-K sec.gov/…/0000018230-22-000050-index.htm
- [6]OperatingIncomeLoss · 0000018230-26-000008 viewer.metricduck.com/…
- [7]LongTermDebtAndCapitalLeaseObligations · 0000018230-26-000021 viewer.metricduck.com/…
The full run
Every step the agent took — reasoning, tool calls, raw results. Click any cited figure to open it in the source filing.
I'll walk the ROIC derivation tree for CAT FY2025, starting at the top and drilling each input level.
No computed lineage for metric "roic" on CAT (FY2025 FY).
This usually means the metric_id isn't a MetricDuck computed metric for this company/period — not that the ticker is wrong. To find valid metrics:
• `get_company_overview("CAT")` — what's available for this company
• `get_financials("CAT")` — the standard computed metrics (margins, ROIC, FCF, leverage…)
• lineage is for COMPUTED metrics only; an as-filed line is in `get_xbrl_facts`.
Then drill a known computed metric, following the exact child ids it returns.Let me try the TTM period type or check what's available via get_company_overview and get_metric_history to understand if FY2025 data is available.
Let me check what's available and try alternate period types.
# CATERPILLAR INC (CAT) Sector: Industrials | Industry: Capital Goods **Leadership:** **CEO:** Joseph E. Creed · **CFO:** Kyle J. Epley _(per 2026-05-06 filing)_ **Investor Relations:** investors.caterpillar.com/… — earnings decks / IR materials (operational KPIs and forward schedules often live in the deck, not SEC filings) **TTM Data as of:** 2026-03-31 (10-Q) **MRQ Data as of:** 2026-03-31 **Current Price:** $1022.28 (as of 2026-06-22) · 1d 3.70% · 1w 12.27% · 1m 15.08% · YTD 70.83% · 1y 190.59% **52w Range:** $344.67 – $1022.28 · 0.00% from high · 196.60% from low ## Key Signals - Revenue (TTM): $70.75B (11.85% YoY) - Gross Margin: 33.44% (sector P53) - ROIC: 26.56% (sector P100) **Latest earnings:** Q1 2026 FY2026 (filed 2026-04-30) ## Data Availability - **Metrics through:** 2026-03-31 (10-Q) - **Latest earnings (8-K):** Q1 2026 (filed 2026-04-30) - **Deep analysis:** metricduck.com/…
Next Steps
get_filing_index("CAT", lens="earnings_quality")Drill earnings concernsget_company_overview("CAT", depth="core")Expanded overview (valuation, cash flow, segments, earnings)get_filing_index("CAT")Signal map of latest filingcompare_earnings_calls("CAT")Cross-quarter earnings trajectory (themes, guidance, tone)compare_companies("CAT")Peer benchmarks
---
*Source — figures are latest-period/TTM values derived from CAT's most recent SEC filings (USD, as of 2026-03-31). Primary source — SEC EDGAR: sec.gov/…# CAT — Return on Invested Capital (ROIC) (annual, last 5)
| FY | FP | Period End | Value | Source |
|---|---|---|---|---|
| 2025 | — | 2025-12-31 | 13.83% | [1] |
| 2024 | — | 2024-12-31 | 18.21% | [2] |
| 2023 | — | 2023-12-31 | 18.51% | [3] |
| 2022 | — | 2022-12-31 | 11.26% | [4] |
| 2021 | — | 2021-12-31 | 10.14% | [5] |
Sources
▸ Raw data▾ Raw data — exact filed values
{
"metric_id": "roic",
"display_name": "Return on Invested Capital (ROIC)",
"unit": null,
"period_type": "FY",
"points": [
{
"fiscal_year": 2025,
"fiscal_period": null,
"period_end": "2025-12-31",
"value": 0.13828295670659527,
"accession_number": "0000018230-26-000008",
"dimension": {
"scale": "actual",
"period": {
"calendar": "2025-12-31",
"type": "FY"
}
}
},
{
"fiscal_year": 2024,
"fiscal_period": null,
"period_end": "2024-12-31",
"value": 0.18212388161693424,
"accession_number": "0000018230-25-000008",
"dimension": {
"scale": "actual",
"period": {
"calendar": "2024-12-31",
"type": "FY"
}
}
},
{
"fiscal_year": 2023,
"fiscal_period": null,
"period_end": "2023-12-31",
"value": 0.1850614553966385,
"accession_number": "0000018230-24-000009",
"dimension": {
"scale": "actual",
"period": {
"calendar": "2023-12-31",
"type": "FY"
}
}
},
{
"fiscal_year": 2022,
"fiscal_period": null,
"period_end": "2022-12-31",
"value": 0.11264730618231907,
"accession_number": "0000018230-23-000011",
"dimension": {
"scale": "actual",
"period": {
"calendar": "2022-12-31",
"type": "FY"
}
}
},
{
"fiscal_year": 2021,
"fiscal_period": null,
"period_end": "2021-12-31",
"value": 0.10140869665799776,
"accession_number": "0000018230-22-000050",
"dimension": {
"scale": "actual",
"period": {
"calendar": "2021-12-31",
"type": "FY"
}
}
}
]
}Next Steps
get_company_overview("CAT")Single-period snapshot across many metricsget_financials("CAT")Full statements across multiple periods
Good, so FY2025 ROIC = 13.83% and it's from the 10-K filed in 2026. The accession number is 0000018230-26-000008. Now I need to drill into the lineage. The `get_metric_lineage` returned no data, but let me try with the TTM period type or just the default. Let me also try without fiscal_period parameter.
FY2025 ROIC = 13.83% confirmed from the 10-K (accession 0000018230-26-000008). Now drilling the lineage.
# CAT — Return on Invested Capital (ROIC) lineage (FY2025) **0.1383** = `if(is_financial(), null, if((max(0, (0 - invested_cap_base)) + max(0, (abs(((nopat / invested_cap_base) * (1 + (3 * is_quarterly())))) - 5))), null, (nopat / invested_cap_base)))`
| Input | Value | Source |
|---|---|---|
| Invested Cap Base | 61.30B | derived — `get_metric_lineage("CAT", "invested_cap_base")` |
| NOPAT | 8.48B | derived — `get_metric_lineage("CAT", "nopat")` |
> Return on Invested Capital (ROIC) = if(is_financial(), null, if((max(0, (0 - invested_cap_base)) + max(0, (abs(((nopat / invested_cap_base) * (1 + (3 * is_quarterly())))) - 5))), null, (nopat / invested_cap_base))) = 0.1383 (where invested_cap_base=61.30B, nopat=8.48B)
if(is_financial(), null, if((max(0, (0 - invested_cap_base)) + max(0, (abs(((nopat / invested_cap_base) * (1 + (3 * is_quarterly())))) - 5))), null, (nopat / invested_cap_base)))Return on Invested Capital (ROIC) = if(is_financial(), null, if((max(0, (0 - invested_cap_base)) + max(0, (abs(((nopat / invested_cap_base) * (1 + (3 * is_quarterly())))) - 5))), null, (nopat / invested_cap_base))) = 0.1383 (where invested_cap_base=61.30B, nopat=8.48B)
- Invested Cap Base61,298,500,000derived
- Nopat8,476,537,821.679231derived
Next Steps
get_metric_history("CAT", "roic")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I need to drill into both `invested_cap_base` and `nopat`.
Now drilling both inputs in parallel.
# CAT — NOPAT lineage (FY2025) **8.48B** = `if(is_financial(), null, (ebit * (1 - max(-0.25, min(0.45, eff_tax_rate)))))`
| Input | Value | Source |
|---|---|---|
| EBIT | 11.15B | derived — `get_metric_lineage("CAT", "ebit")` |
| Effective Tax Rate | 0.2398 | derived — `get_metric_lineage("CAT", "eff_tax_rate")` |
> NOPAT = if(is_financial(), null, (ebit * (1 - max(-0.25, min(0.45, eff_tax_rate))))) = 8.48B (where ebit=11.15B, eff_tax_rate=0.2398)
if(is_financial(), null, (ebit * (1 - max(-0.25, min(0.45, eff_tax_rate)))))NOPAT = if(is_financial(), null, (ebit * (1 - max(-0.25, min(0.45, eff_tax_rate))))) = 8.48B (where ebit=11.15B, eff_tax_rate=0.2398)
- Ebit11,151,000,000derived
- Eff Tax Rate0.23984056840828352derived
Next Steps
get_metric_history("CAT", "nopat")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Invested Cap Base lineage (Q4 FY2025) **64.65B** = `max(invested_cap, ttl_capital)`
| Input | Value | Source |
|---|---|---|
| Invested Cap | 37.34B | derived — `get_metric_lineage("CAT", "invested_cap")` |
| Total Capital | 64.65B | derived — `get_metric_lineage("CAT", "ttl_capital")` |
> Invested Cap Base = max(invested_cap, ttl_capital) = 64.65B (where invested_cap=37.34B, ttl_capital=64.65B)
max(invested_cap, ttl_capital)Invested Cap Base = max(invested_cap, ttl_capital) = 64.65B (where invested_cap=37.34B, ttl_capital=64.65B)
- Invested Cap37,337,000,000derived
- Ttl Capital64,648,000,000derived
Next Steps
get_metric_history("CAT", "invested_cap_base")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I need to drill deeper into the inputs. I have: - `invested_cap_base` = max(invested_cap, ttl_capital) = 64.65B (uses ttl_capital since it's larger) - `nopat` needs: ebit and eff_tax_rate Note: The ROIC formula uses `invested_cap_base = 61.30B` but the lineage for `invested_cap_base` says 64.65B. This is because ROIC uses the average invested capital (average of beginning and end of year), while `invested_cap_base` alone is the period-end value. Let me re-read... Actually, looking at the ROIC lineage more carefully, the calculation checks out: 8.48B / 61.30B = 0.1383. The 64.65B figure is the Q4 FY2025 period-end value, but ROIC likely uses an average of the beginning and ending invested capital base across the fiscal year, which explains why it's using 61.30B instead. So the average invested capital across the fiscal year (57.95B to 64.65B) equals 61.30B, which matches what's used in the ROIC calculation—the period-end value in the lineage is different because it's showing the Q4 snapshot. Now I need to trace back the drivers: ttl_capital is the main component pushing invested_cap_base, and I should investigate what's driving ebit and the effective tax rate to understand NOPAT.
Now drilling the next level — `ttl_capital`, `invested_cap`, `ebit`, and `eff_tax_rate` all in parallel.
# CAT — Total Capital lineage (Q4 FY2025) **64.65B** = `ttl_debt + ttl_equity`
| Input | Value | Source |
|---|---|---|
| Total Debt | 43.33B | derived — `get_metric_lineage("CAT", "ttl_debt")` |
| Total Equity | 21.32B | derived — `get_metric_lineage("CAT", "ttl_equity")` |
> Total Capital = ttl_debt + ttl_equity = 64.65B (where ttl_debt=43.33B, ttl_equity=21.32B)
ttl_debt + ttl_equityTotal Capital = ttl_debt + ttl_equity = 64.65B (where ttl_debt=43.33B, ttl_equity=21.32B)
- Ttl Debt43,330,000,000derived
- Ttl Equity21,318,000,000derived
Next Steps
get_metric_history("CAT", "ttl_capital")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Effective Tax Rate lineage (FY2025) **0.2398** = `coalesce((income_tax / pretax_inc), (income_tax / (net_income + income_tax)), ((pretax_inc - net_income) / pretax_inc))`
| Input | Value | Source |
|---|---|---|
| Income Tax | 2.77B | derived — `get_metric_lineage("CAT", "income_tax")` |
| Pretax Income | 11.54B | derived — `get_metric_lineage("CAT", "pretax_inc")` |
| Net Income | 8.88B | derived — `get_metric_lineage("CAT", "net_income")` |
> Effective Tax Rate = coalesce((income_tax / pretax_inc), (income_tax / (net_income + income_tax)), ((pretax_inc - net_income) / pretax_inc)) = 0.2398 (where income_tax=2.77B, pretax_inc=11.54B, net_income=8.88B)
coalesce((income_tax / pretax_inc), (income_tax / (net_income + income_tax)), ((pretax_inc - net_income) / pretax_inc))Effective Tax Rate = coalesce((income_tax / pretax_inc), (income_tax / (net_income + income_tax)), ((pretax_inc - net_income) / pretax_inc)) = 0.2398 (where income_tax=2.77B, pretax_inc=11.54B, net_income=8.88B)
- Income Tax2,768,000,000derived
- Pretax Inc11,541,000,000derived
- Net Income8,884,000,000derived
Next Steps
get_metric_history("CAT", "eff_tax_rate")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Invested Cap lineage (Q4 FY2025) **37.34B** = `if(is_financial(), null, add(working_cap, ppe, gwill, intang))`
| Input | Value | Source |
|---|---|---|
| Working Cap | 15.93B | derived — `get_metric_lineage("CAT", "working_cap")` |
| Property, Plant & Equipment | 15.85B | derived — `get_metric_lineage("CAT", "ppe")` |
| Goodwill | 5.32B | derived — `get_metric_lineage("CAT", "gwill")` |
| Intangible Assets | 241.00M | derived — `get_metric_lineage("CAT", "intang")` |
> Invested Cap = if(is_financial(), null, add(working_cap, ppe, gwill, intang)) = 37.34B (where working_cap=15.93B, ppe=15.85B, gwill=5.32B, intang=241.00M)
if(is_financial(), null, add(working_cap, ppe, gwill, intang))Invested Cap = if(is_financial(), null, add(working_cap, ppe, gwill, intang)) = 37.34B (where working_cap=15.93B, ppe=15.85B, gwill=5.32B, intang=241.00M)
- Working Cap15,927,000,000derived
- Ppe15,848,000,000derived
- Gwill5,321,000,000derived
- Intang241,000,000derived
Next Steps
get_metric_history("CAT", "invested_cap")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — EBIT lineage (FY2025) **11.15B** = `oper_inc`
| Input | Value | Source |
|---|---|---|
| Operating Income | 11.15B | derived — `get_metric_lineage("CAT", "oper_inc")` |
> EBIT = oper_inc = 11.15B (where oper_inc=11.15B)
oper_incEBIT = oper_inc = 11.15B (where oper_inc=11.15B)
- Oper Inc11,151,000,000derived
Next Steps
get_metric_history("CAT", "ebit")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I need to drill further. The key inputs that need further drilling: 1. `ttl_debt` (43.33B) - feeds ttl_capital 2. `ttl_equity` (21.32B) - feeds ttl_capital 3. `oper_inc` (11.15B) - feeds EBIT 4. `income_tax` (2.77B) - feeds eff_tax_rate 5. `pretax_inc` (11.54B) - feeds eff_tax_rate 6. `net_income` (8.88B) - feeds eff_tax_rate 7. `working_cap` (15.93B) - feeds invested_cap 8. `ppe` (15.85B) - feeds invested_cap 9. `gwill` (5.32B) - feeds invested_cap 10. `intang` (241M) - feeds invested_cap Since ttl_capital (64.65B) exceeds invested_cap (37.34B), the ROIC calculation uses ttl_capital as the denominator, making the debt and equity components the critical path to trace. On the income statement side, the key drivers are oper_inc, income_tax, pretax_inc, and net_income. I need to drill into these in parallel since they feed both EBIT and the effective tax rate calculation. I'm also noticing a discrepancy—the ROIC formula shows invested_cap_base at 61.30B while the lineage indicates 64.65B for Q4 FY2025, which suggests the ROIC might be using an average of beginning and end-of-year values. Let me verify this calculation: if (FY2024 invested_cap_base + 64.65B) / 2 = 61.30B, then FY2024 invested_cap_base would be 57.95B. The lineage for invested_cap_base only shows the Q4 FY2025 value as max(invested_cap, ttl_capital), so the averaging must be happening within the ROIC formula itself rather than in the invested_cap_base calculation. So the 61.30B figure in the ROIC calculation is the averaged invested capital across the period, while 64.65B is just the period-end snapshot. Let me verify this by checking if the FY2024 invested capital value, when averaged with FY2025's beginning balance, gives me 61.30B. Now I need to drill down into the remaining components—operating income, total debt, total equity, income tax, pretax income, and net income—to trace them back to the as-filed XBRL data and see which are base metrics versus derived. I'll work through these in parallel to understand the full lineage. The ROIC formula itself has guard conditions that check for negative invested capital or results exceeding 500%, neither of which apply here. But there's still that discrepancy between the 61.30B shown in the ROIC calculation versus the 64.65B in the invested capital lineage—it's possible MetricDuck is averaging beginning and ending period values, or using a different time period altogether. Let me note this difference and move on to examining the other critical path nodes with the as-filed numbers.
Several inputs are still derived. Now drilling `oper_inc`, `ttl_debt`, `ttl_equity`, `income_tax`, `pretax_inc`, and `net_income` in parallel to reach the as-filed XBRL layer.
# CAT — Operating Income lineage (FY2025) **11.15B** = `coalesce(OperatingIncomeLoss, ProfitLossFromOperatingActivities, (revenues - ttl_oper_exps))`
| Input | Value | Source |
|---|---|---|
| OperatingIncomeLoss | 11.15B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
| Revenues | 67.59B | derived — `get_metric_lineage("CAT", "revenues")` |
| Total Oper Expenses | 56.44B | derived — `get_metric_lineage("CAT", "ttl_oper_exps")` |
> Operating Income = coalesce(OperatingIncomeLoss, ProfitLossFromOperatingActivities, (revenues - ttl_oper_exps)) = 11.15B (where OperatingIncomeLoss=11.15B, revenues=67.59B, ttl_oper_exps=56.44B)
coalesce(OperatingIncomeLoss, ProfitLossFromOperatingActivities, (revenues - ttl_oper_exps))Operating Income = coalesce(OperatingIncomeLoss, ProfitLossFromOperatingActivities, (revenues - ttl_oper_exps)) = 11.15B (where OperatingIncomeLoss=11.15B, revenues=67.59B, ttl_oper_exps=56.44B)
- OperatingIncomeLoss11,151,000,000baseviewer.metricduck.com/…
- Revenues67,589,000,000derived
- Ttl Oper Exps56,438,000,000derived
Next Steps
get_metric_history("CAT", "oper_inc")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Total Debt lineage (Q4 FY2025) **43.33B** = `coalesce(Borrowings, (debt_current_total + lt_debt))`
| Input | Value | Source |
|---|---|---|
| Debt Current Total | 12.63B | derived — `get_metric_lineage("CAT", "debt_current_total")` |
| Long-Term Debt | 30.70B | derived — `get_metric_lineage("CAT", "lt_debt")` |
> Total Debt = coalesce(Borrowings, (debt_current_total + lt_debt)) = 43.33B (where debt_current_total=12.63B, lt_debt=30.70B)
coalesce(Borrowings, (debt_current_total + lt_debt))Total Debt = coalesce(Borrowings, (debt_current_total + lt_debt)) = 43.33B (where debt_current_total=12.63B, lt_debt=30.70B)
- Debt Current Total12,634,000,000derived
- Lt Debt30,696,000,000derived
Next Steps
get_metric_history("CAT", "ttl_debt")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Income Tax lineage (FY2025) **2.77B** = `coalesce(IncomeTaxExpenseBenefit, IncomeTaxExpense, IncomeTaxExpenseContinuingOperations, null)`
| Input | Value | Source |
|---|---|---|
| IncomeTaxExpenseBenefit | 2.77B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
> Income Tax = coalesce(IncomeTaxExpenseBenefit, IncomeTaxExpense, IncomeTaxExpenseContinuingOperations, null) = 2.77B (where IncomeTaxExpenseBenefit=2.77B)
coalesce(IncomeTaxExpenseBenefit, IncomeTaxExpense, IncomeTaxExpenseContinuingOperations, null)Income Tax = coalesce(IncomeTaxExpenseBenefit, IncomeTaxExpense, IncomeTaxExpenseContinuingOperations, null) = 2.77B (where IncomeTaxExpenseBenefit=2.77B)
- IncomeTaxExpenseBenefit2,768,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "income_tax")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Total Equity lineage (Q4 FY2025) **21.32B** = `coalesce(StockholdersEquity, ShareholdersEquity, TotalEquity, Equity, EquityAttributableToOwnersOfParent, StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest)`
| Input | Value | Source |
|---|---|---|
| StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest | 21.32B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
> Total Equity = coalesce(StockholdersEquity, ShareholdersEquity, TotalEquity, Equity, EquityAttributableToOwnersOfParent, StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest) = 21.32B (where StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest=21.32B)
coalesce(StockholdersEquity, ShareholdersEquity, TotalEquity, Equity, EquityAttributableToOwnersOfParent, StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest)Total Equity = coalesce(StockholdersEquity, ShareholdersEquity, TotalEquity, Equity, EquityAttributableToOwnersOfParent, StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest) = 21.32B (where StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest=21.32B)
- StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest21,318,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "ttl_equity")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Pretax Income lineage (FY2025) **11.54B** = `coalesce(IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest, IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments, ProfitLossBeforeTax, IncomeLossAttributableToParent)`
| Input | Value | Source |
|---|---|---|
| IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInv… | 11.54B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
> Pretax Income = coalesce(IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest, IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments, ProfitLossBeforeTax, IncomeLossAttributableToParent) = 11.54B (where IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments=11.54B)
coalesce(IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest, IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments, ProfitLossBeforeTax, IncomeLossAttributableToParent)Pretax Income = coalesce(IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest, IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments, ProfitLossBeforeTax, IncomeLossAttributableToParent) = 11.54B (where IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments=11.54B)
- IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments11,541,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "pretax_inc")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Net Income lineage (FY2025) **8.88B** = `coalesce(NetIncomeLossAvailableToCommonStockholdersBasic, NetIncomeLossAttributableToParent, NetIncomeLoss, ProfitLoss, ProfitLossAttributableToOwnersOfParent)`
| Input | Value | Source |
|---|---|---|
| NetIncomeLossAvailableToCommonStockholdersBasic | 8.88B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
| ProfitLoss | 8.88B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
> Net Income = coalesce(NetIncomeLossAvailableToCommonStockholdersBasic, NetIncomeLossAttributableToParent, NetIncomeLoss, ProfitLoss, ProfitLossAttributableToOwnersOfParent) = 8.88B (where NetIncomeLossAvailableToCommonStockholdersBasic=8.88B, ProfitLoss=8.88B)
coalesce(NetIncomeLossAvailableToCommonStockholdersBasic, NetIncomeLossAttributableToParent, NetIncomeLoss, ProfitLoss, ProfitLossAttributableToOwnersOfParent)Net Income = coalesce(NetIncomeLossAvailableToCommonStockholdersBasic, NetIncomeLossAttributableToParent, NetIncomeLoss, ProfitLoss, ProfitLossAttributableToOwnersOfParent) = 8.88B (where NetIncomeLossAvailableToCommonStockholdersBasic=8.88B, ProfitLoss=8.88B)
- NetIncomeLossAvailableToCommonStockholdersBasic8,884,000,000baseviewer.metricduck.com/…
- ProfitLoss8,882,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "net_income")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I have most of the base XBRL facts. Let me also drill: 1. `debt_current_total` - needed for ttl_debt 2. `lt_debt` - needed for ttl_debt 3. `working_cap` - needed for invested_cap (but since ttl_capital > invested_cap, invested_cap isn't in the critical path for ROIC, but good to complete the tree) Also, I need to figure out the discrepancy between invested_cap_base = 61.30B (used in ROIC) vs 64.65B (from the lineage). I suspect ROIC uses an average of beginning and ending invested_cap_base. Let me get the FY2024 invested_cap_base to check. Actually, looking at the ROIC lineage more carefully, the invested_cap_base input of 61.30B appears to be an average between the FY2024 ending balance and the FY2025 ending balance of 64.65B. I need to pull the FY2024 invested_cap_base to verify this calculation. I should also trace back the debt components—current debt and long-term debt—to their underlying XBRL facts, and I'll work through these in parallel.
Almost at the base layer. I still need to drill `debt_current_total` and `lt_debt` to XBRL, and I need the FY2024 `invested_cap_base` to explain the averaging behind the 61.30B denominator used in ROIC.
# CAT — Long-Term Debt lineage (Q4 FY2025) **30.70B** = `coalesce(LongTermDebtNoncurrent, LongTermNotesAndLoans, LongTermNotesPayable, LongTermDebtAndCapitalLeaseObligations, LongtermBorrowings, LongTermDebt, ConvertibleDebtNoncurrent, LongTermDebtAndLeaseObligationExcludingCurrentMaturities, LongTermDebtAndFinanceLeaseObligationsNoncurrent, 0)`
| Input | Value | Source |
|---|---|---|
| LongTermDebtNoncurrent | 30.70B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
| LongTermDebtAndCapitalLeaseObligations | 50.71B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000021/index.h… |
> Long-Term Debt = coalesce(LongTermDebtNoncurrent, LongTermNotesAndLoans, LongTermNotesPayable, LongTermDebtAndCapitalLeaseObligations, LongtermBorrowings, LongTermDebt, ConvertibleDebtNoncurrent, LongTermDebtAndLeaseObligationExcludingCurrentMaturities, LongTermDebtAndFinanceLeaseObligationsNoncurrent, 0) = 30.70B (where LongTermDebtNoncurrent=30.70B, LongTermDebtAndCapitalLeaseObligations=50.71B)
coalesce(LongTermDebtNoncurrent, LongTermNotesAndLoans, LongTermNotesPayable, LongTermDebtAndCapitalLeaseObligations, LongtermBorrowings, LongTermDebt, ConvertibleDebtNoncurrent, LongTermDebtAndLeaseObligationExcludingCurrentMaturities, LongTermDebtAndFinanceLeaseObligationsNoncurrent, 0)Long-Term Debt = coalesce(LongTermDebtNoncurrent, LongTermNotesAndLoans, LongTermNotesPayable, LongTermDebtAndCapitalLeaseObligations, LongtermBorrowings, LongTermDebt, ConvertibleDebtNoncurrent, LongTermDebtAndLeaseObligationExcludingCurrentMaturities, LongTermDebtAndFinanceLeaseObligationsNoncurrent, 0) = 30.70B (where LongTermDebtNoncurrent=30.70B, LongTermDebtAndCapitalLeaseObligations=50.71B)
- LongTermDebtNoncurrent30,696,000,000baseviewer.metricduck.com/…
- LongTermDebtAndCapitalLeaseObligations50,714,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "lt_debt")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Debt Current Total lineage (Q4 FY2025) **12.63B** = `coalesce(DebtCurrent, CurrentBorrowingsAndCurrentPortionOfNoncurrentBorrowings, (st_debt + lt_debt_cur_portion))`
| Input | Value | Source |
|---|---|---|
| Short-Term Debt | 5.51B | derived — `get_metric_lineage("CAT", "st_debt")` |
| Long-Term Debt Cur Portion | 7.12B | derived — `get_metric_lineage("CAT", "lt_debt_cur_portion")` |
> Debt Current Total = coalesce(DebtCurrent, CurrentBorrowingsAndCurrentPortionOfNoncurrentBorrowings, (st_debt + lt_debt_cur_portion)) = 12.63B (where st_debt=5.51B, lt_debt_cur_portion=7.12B)
coalesce(DebtCurrent, CurrentBorrowingsAndCurrentPortionOfNoncurrentBorrowings, (st_debt + lt_debt_cur_portion))Debt Current Total = coalesce(DebtCurrent, CurrentBorrowingsAndCurrentPortionOfNoncurrentBorrowings, (st_debt + lt_debt_cur_portion)) = 12.63B (where st_debt=5.51B, lt_debt_cur_portion=7.12B)
- St Debt5,514,000,000derived
- Lt Debt Cur Portion7,120,000,000derived
Next Steps
get_metric_history("CAT", "debt_current_total")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Invested Cap Base lineage (Q4 FY2024) **57.95B** = `max(invested_cap, ttl_capital)`
| Input | Value | Source |
|---|---|---|
| Invested Cap | 33.00B | derived — `get_metric_lineage("CAT", "invested_cap")` |
| Total Capital | 57.95B | derived — `get_metric_lineage("CAT", "ttl_capital")` |
> Invested Cap Base = max(invested_cap, ttl_capital) = 57.95B (where invested_cap=33.00B, ttl_capital=57.95B)
max(invested_cap, ttl_capital)Invested Cap Base = max(invested_cap, ttl_capital) = 57.95B (where invested_cap=33.00B, ttl_capital=57.95B)
- Invested Cap33,003,000,000derived
- Ttl Capital57,949,000,000derived
Next Steps
get_metric_history("CAT", "invested_cap_base")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I have the FY2024 invested_cap_base = 57.95B. Let me verify the average: (57.95B + 64.65B) / 2 = 122.60B / 2 = 61.30B ✓ So the ROIC formula indeed uses the average of beginning (FY2024 end) and ending (FY2025 end) invested_cap_base, which equals 61.30B. Now I still need to drill: 1. `st_debt` (5.51B) - feeds debt_current_total 2. `lt_debt_cur_portion` (7.12B) - feeds debt_current_total These are the last remaining derived inputs. Let me verify the tax rate calculation: income_tax / pretax_inc = 2.768B / 11.541B = 23.98% ✓ And NOPAT = ebit × (1 - eff_tax_rate) = 11.151B × (1 - 0.2398) = 8.47B ✓ Now I'm checking the capital structure calculations: average invested capital comes to 61.30B, total capital at year-end is 64.648B, and ROIC works out to 13.83%. The math all checks out. I think I have enough detail to present the full picture now.
The FY2024 `invested_cap_base` = 57.95B confirms the averaging: (57.95 + 64.65) / 2 = **61.30B** — exactly the denominator in ROIC. Now drilling the last two derived nodes to reach XBRL base.
# CAT — Long-Term Debt Cur Portion lineage (Q4 FY2025) **7.12B** = `coalesce(LongTermDebtCurrent, CurrentPortionOfLongTermDebt, CurrentPortionOfLongtermBorrowings, ConvertibleDebtCurrent, LongTermDebtAndCapitalLeaseObligationsCurrent, LongTermDebtAndFinanceLeaseObligationsCurrent, 0)`
| Input | Value | Source |
|---|---|---|
| LongTermDebtAndCapitalLeaseObligationsCurrent | 7.12B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000021/index.h… |
> Long-Term Debt Cur Portion = coalesce(LongTermDebtCurrent, CurrentPortionOfLongTermDebt, CurrentPortionOfLongtermBorrowings, ConvertibleDebtCurrent, LongTermDebtAndCapitalLeaseObligationsCurrent, LongTermDebtAndFinanceLeaseObligationsCurrent, 0) = 7.12B (where LongTermDebtAndCapitalLeaseObligationsCurrent=7.12B)
coalesce(LongTermDebtCurrent, CurrentPortionOfLongTermDebt, CurrentPortionOfLongtermBorrowings, ConvertibleDebtCurrent, LongTermDebtAndCapitalLeaseObligationsCurrent, LongTermDebtAndFinanceLeaseObligationsCurrent, 0)Long-Term Debt Cur Portion = coalesce(LongTermDebtCurrent, CurrentPortionOfLongTermDebt, CurrentPortionOfLongtermBorrowings, ConvertibleDebtCurrent, LongTermDebtAndCapitalLeaseObligationsCurrent, LongTermDebtAndFinanceLeaseObligationsCurrent, 0) = 7.12B (where LongTermDebtAndCapitalLeaseObligationsCurrent=7.12B)
- LongTermDebtAndCapitalLeaseObligationsCurrent7,120,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "lt_debt_cur_portion")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
# CAT — Short-Term Debt lineage (Q4 FY2025) **5.51B** = `coalesce(CommercialPaper, ShortTermDebt, ShortTermBorrowings, ShorttermBorrowings, 0)`
| Input | Value | Source |
|---|---|---|
| ShortTermBorrowings | 5.51B | base — [filing](https://viewer.metricduck.com/?doc=/filings/0000018230/0000018230-26-000008/index.h… |
> Short-Term Debt = coalesce(CommercialPaper, ShortTermDebt, ShortTermBorrowings, ShorttermBorrowings, 0) = 5.51B (where ShortTermBorrowings=5.51B)
coalesce(CommercialPaper, ShortTermDebt, ShortTermBorrowings, ShorttermBorrowings, 0)Short-Term Debt = coalesce(CommercialPaper, ShortTermDebt, ShortTermBorrowings, ShorttermBorrowings, 0) = 5.51B (where ShortTermBorrowings=5.51B)
- ShortTermBorrowings5,514,000,000baseviewer.metricduck.com/…
Next Steps
get_metric_history("CAT", "st_debt")The value's time seriesget_xbrl_facts("CAT", search="<input>")Drill a base input to its fact
Now I have the complete derivation tree all the way to the XBRL base. Let me compile the full picture. **Summary of the derivation tree for CAT ROIC FY2025:** **Top level:** ROIC = NOPAT / avg(invested_cap_base) = 8.476B / 61.299B = **13.83%** Source: CAT 10-K, accession 0000018230-26-000008 --- **NOPAT branch:** NOPAT comes from operating income of 11.151B multiplied by one minus the effective tax rate of 23.98%, which gives me 8.477B. The operating income itself is pulled directly from the XBRL base as OperatingIncomeLoss. Now I need to finish calculating the effective tax rate by dividing income tax expense by pretax income. The effective tax rate formula uses the income tax divided by pretax income, which comes to 23.98% and falls within the acceptable bounds of -25% to 45%. For the invested capital base in the ROIC calculation, I'm averaging the beginning and end of year figures—$57.949B and $64.648B respectively—to get approximately $61.30B. Now I'm verifying the invested capital base calculation, which takes the maximum of either the sum of working capital, property and equipment, goodwill, and intangibles, or the sum of total debt and total equity. The total capital approach yields $64.648B, which exceeds the component-based calculation of $37.337B, so total capital drives the invested capital base figure. The current portion comes from a different filing, so I need to note that distinction. Now let me verify the calculations: the effective tax rate works out to about 24%, which gives me a NOPAT of roughly 8.5 billion, and combining that with total capital of about 64.6 billion completes the picture.
I now have the complete tree. Let me compile the full derivation.
61298500000.0
0.23984056840828352
8476544159.999999
0.13828295669551458
All the math checks out perfectly. Now let me write the complete, comprehensive answer walking the full derivation tree for CAT's ROIC FY2025.
DigestPayload · 6,300 chars
All arithmetic verified. Here is the complete derivation tree.
---
## CAT ROIC FY2025 — Full Derivation Tree
**Source filing for all base XBRL facts (unless noted): CAT 10-K, accession `0000018230-26-000008`**
---
### Level 1 — Top Formula
```
ROIC = NOPAT / avg(invested_cap_base)
= $8,476,537,822 / $61,298,500,000
= 13.83%
```
Guard rails in the formula null out the result if `invested_cap_base` is negative or if the annualised ratio would exceed 5× (500%). Neither fires here.
The **denominator is the average** of period-beginning and period-ending `invested_cap_base` — MetricDuck uses the two balance-sheet snapshots:
| Period | invested_cap_base |
|--------|-------------------|
| Q4 FY2024 (beginning of FY2025) | $57,949,000,000 |
| Q4 FY2025 (ending of FY2025) | $64,648,000,000 |
| **Average (used in ROIC)** | **$61,298,500,000** |
---
### Level 2 — NOPAT
```
NOPAT = EBIT × (1 − eff_tax_rate)
= $11,151,000,000 × (1 − 0.23984)
= $8,476,544,160 [rounds to $8,476,537,822 with full precision]
```
#### Level 3a — EBIT
```
EBIT = oper_inc
= OperatingIncomeLoss ← XBRL base fact
= $11,151,000,000
```
> **As-filed XBRL concept:** `OperatingIncomeLoss` = **$11,151,000,000** (CAT 10-K `0000018230-26-000008`)
#### Level 3b — Effective Tax Rate
```
eff_tax_rate = income_tax / pretax_inc [primary coalesce branch]
= $2,768,000,000 / $11,541,000,000
= 23.984%
```
(Clamped to the range [−25%, 45%]; 23.98% is within bounds — no clamping applied.)
| Input | XBRL concept | As-filed value |
|-------|-------------|----------------|
| `income_tax` | `IncomeTaxExpenseBenefit` | **$2,768,000,000** |
| `pretax_inc` | `IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments` | **$11,541,000,000** |
| `net_income` (fallback only) | `NetIncomeLossAvailableToCommonStockholdersBasic` | **$8,884,000,000** |
All three from CAT 10-K `0000018230-26-000008`.
---
### Level 2 — invested_cap_base (period-end, FY2025)
```
invested_cap_base = max(invested_cap, ttl_capital)
= max($37,337,000,000, $64,648,000,000)
= $64,648,000,000 ← ttl_capital wins
```
#### Level 3 — Total Capital (the binding input)
```
ttl_capital = ttl_debt + ttl_equity
= $43,330,000,000 + $21,318,000,000
= $64,648,000,000
```
##### Level 4 — Total Equity
```
ttl_equity = StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest
= $21,318,000,000
```
> **XBRL base:** `StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest` = **$21,318,000,000** (10-K `0000018230-26-000008`)
##### Level 4 — Total Debt
```
ttl_debt = debt_current_total + lt_debt
= $12,634,000,000 + $30,696,000,000
= $43,330,000,000
```
###### Level 5 — Long-Term Debt (non-current)
```
lt_debt = LongTermDebtNoncurrent ← XBRL base
= $30,696,000,000
```
> **XBRL base:** `LongTermDebtNoncurrent` = **$30,696,000,000** (10-K `0000018230-26-000008`)
###### Level 5 — Current Debt Total
```
debt_current_total = st_debt + lt_debt_cur_portion
= $5,514,000,000 + $7,120,000,000
= $12,634,000,000
```
| Component | XBRL concept | As-filed value | Filing |
|-----------|-------------|----------------|--------|
| `st_debt` | `ShortTermBorrowings` | **$5,514,000,000** | 10-K `0000018230-26-000008` |
| `lt_debt_cur_portion` | `LongTermDebtAndCapitalLeaseObligationsCurrent` | **$7,120,000,000** | `0000018230-26-000021`* |
> \* `lt_debt_cur_portion` resolves from a companion filing (`0000018230-26-000021`), not the primary 10-K, because `LongTermDebtCurrent` was absent from the main filing and the coalesce waterfall fell to `LongTermDebtAndCapitalLeaseObligationsCurrent` found there.
#### Level 3 — Invested Cap (not binding, shown for completeness)
```
invested_cap = working_cap + ppe + gwill + intang
= $15,927M + $15,848M + $5,321M + $241M
= $37,337,000,000
```
Since $37.34B < $64.65B, `invested_cap` does **not** drive `invested_cap_base` — `ttl_capital` takes the max.
---
### Cross-check summary
| Step | Numerator | Denominator | Result |
|------|-----------|-------------|--------|
| eff_tax_rate | $2,768M | $11,541M | 23.984% |
| NOPAT | $11,151M × 0.76016 | — | $8,477M |
| avg invested_cap_base | ($57,949M + $64,648M) | 2 | $61,299M |
| **ROIC** | **$8,477M** | **$61,299M** | **13.83%** |
---
FINAL ANSWER:
MetricDuck computes CAT's FY2025 ROIC as **13.83%**, derived as follows (all base facts from CAT 10-K accession `0000018230-26-000008` unless noted):
**Formula:** `ROIC = NOPAT / avg(invested_cap_base)`
**NOPAT = $8,476,537,822**
- EBIT = OperatingIncomeLoss (XBRL base) = **$11,151,000,000**
- Effective Tax Rate = IncomeTaxExpenseBenefit / Pretax Income = $2,768,000,000 / $11,541,000,000 = **23.984%**
- `IncomeTaxExpenseBenefit` (XBRL base) = $2,768,000,000
- `IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments` (XBRL base) = $11,541,000,000
- NOPAT = $11,151M × (1 − 0.23984) = **$8,477M**
**avg(invested_cap_base) = $61,298,500,000** — average of period-beginning and period-ending balance-sheet snapshots:
- Q4 FY2024 invested_cap_base = $57,949,000,000
- Q4 FY2025 invested_cap_base = $64,648,000,000
- Average = (57,949 + 64,648) / 2 = **$61,298,500,000**
Each period's `invested_cap_base = max(invested_cap, ttl_capital)` — ttl_capital dominates in both years:
- ttl_capital (FY2025 end) = ttl_debt + ttl_equity = $43,330M + $21,318M = **$64,648M**
- ttl_equity = `StockholdersEquityIncludingPortionAttributableToNoncontrollingInterest` (XBRL base) = **$21,318,000,000**
- ttl_debt = debt_current_total + lt_debt = $12,634M + $30,696M = **$43,330M**
- lt_debt = `LongTermDebtNoncurrent` (XBRL base) = **$30,696,000,000**
- debt_current_total = st_debt + lt_debt_cur_portion = $5,514M + $7,120M = **$12,634M**
- st_debt = `ShortTermBorrowings` (XBRL base) = **$5,514,000,000**
- lt_debt_cur_portion = `LongTermDebtAndCapitalLeaseObligationsCurrent` (XBRL base, accession `0000018230-26-000021`) = **$7,120,000,000**
Final: ROIC = $8,477M / $61,299M = **13.83%** (CAT 10-K FY2025)A real, unedited AI agent run (Sonnet 4.6, captured from MetricDuck's own evaluation set): MetricDuck MCP for the data + the full metric lineage, a calculator for the arithmetic (effective tax rate, the debt bridge, the two-year-end average) — shown in full. Every figure is MetricDuck-sourced; gold read from primary SEC EDGAR (never MetricDuck's own output); verdict = pass. Curation is limited to the short summary; the trace itself — thinking, tool calls, results, and final answer — is exactly as captured. See the method →
MetricDuck — the free, self-serve first-source financial data layer beneath whatever agent you run (not another model). Every figure is traced back to its source — click any to verify.
Run this on your own ticker — connect your agent in 30 seconds.
Connect free →