Оценка компании методом DCF
Строит модель оценки компании в Excel методом дисконтирования денежных потоков с расчётом WACC, сценариями и таблицами чувствительности.
- Что делает
- Строит модель оценки компании в Excel методом дисконтирования денежных потоков с расчётом WACC, сценариями и таблицами чувствительности.
- Когда брать
- Когда нужно оценить компанию методом DCF, посчитать внутреннюю стоимость акции или построить прогноз денежных потоков.
- Когда не брать
- Если нужно быстро сравнить компанию с аналогами: для этого есть сравнительный анализ (comps).
- Пример запроса
- Построй DCF-модель для компании Apple с тремя сценариями и таблицами чувствительности.
- Нужно подключить
- Excel или Python (openpyxl), источники финансовых данных
- Работает лучше с
- MCP-сервер Daloopa
Входит в плагин model-builder. В Cowork и Claude Code можно поставить плагин целиком.
Как включить
- Скачайте архив и распакуйте его.
- Положите папку
dcf-modelв~/.claude/skills/. - Откройте Claude Code и опишите задачу своими словами: Claude подхватит скилл по описанию.
Текст
---
name: dcf-model
description: Создание настоящей DCF-модели (дисконтирование денежных потоков) для оценки акций. Берёт финансовые данные из отчётов SEC и аналитических обзоров, строит подробный прогноз денежных потоков с корректным расчётом WACC, делает анализ чувствительности и выдаёт профессиональные модели в Excel с кратким резюме для руководства. Используй, когда нужно оценить компанию методом DCF, посчитать внутреннюю стоимость или построить подробную финансовую модель с прогнозом роста и расчётом терминальной стоимости.
---
Построитель DCF-моделей
Обзор
Этот скилл создаёт DCF-модели институционального качества для оценки акций по стандартам инвестиционных банков. Каждый анализ даёт подробную модель Excel (анализ чувствительности находится внизу листа DCF).
Инструменты
- По умолчанию используй всю информацию, которую дал пользователь, и доступные MCP-серверы как источники данных.
Критичные ограничения — прочитай их первыми
Эти ограничения действуют на протяжении всей работы над DCF-моделью. Просмотри их перед началом:
Среда: Office JS или Python/openpyxl:
- Если ты работаешь внутри Excel (надстройка Office / среда Office JS): используй Office JS напрямую, НЕ используй Python/openpyxl. Формулы записывай через
range.formulas = [["=D19*(1+$B$8)"]]. Отдельный шаг пересчёта не нужен: Excel считает сам. Для оформления используйrange.format.*. Правило «формулы вместо зашитых чисел» действует и здесь: для расчётных ячеек задавай.formulas, а не.values. - Если ты создаёшь отдельный файл .xlsx (без живой сессии Excel): используй Python/openpyxl, как описано ниже, а перед сдачей запусти
recalc.py. - Остальная часть скилла приводит примеры на openpyxl: в среде Office JS переводи их в вызовы API Office JS, но все принципы (строки с формулами, комментарии к ячейкам, контрольные точки по разделам, циклы для таблиц чувствительности) действуют одинаково.
⚠️ Ловушка объединённых ячеек в Office JS: когда строишь заголовки разделов с объединёнными ячейками, НЕ вызывай .merge(), а потом не задавай .values для объединённого диапазона: Office JS по-прежнему сообщает исходные размеры диапазона и выдаст ошибку InvalidArgument: The number of rows or columns in the input array doesn't match the size or dimensions of the range. Вместо этого запиши значение только в левую верхнюю ячейку, затем объедини и отформатируй весь диапазон:
// WRONG — throws InvalidArgument:
const hdr = ws.getRange("A7:H7");
hdr.merge();
hdr.values = [["MARKET DATA & KEY INPUTS"]]; // 1×1 array vs 1×8 range → fails
// CORRECT — value first on single cell, then merge + format the range:
ws.getRange("A7").values = [["MARKET DATA & KEY INPUTS"]];
const hdr = ws.getRange("A7:H7");
hdr.merge();
hdr.format.fill.color = "#1F4E79";
hdr.format.font.bold = true;
hdr.format.font.color = "#FFFFFF";
Это относится к каждому объединённому заголовку раздела в DCF (рыночные данные, блоки сценариев, прогноз денежных потоков, терминальная стоимость, сводка по оценке, таблицы чувствительности).
Формулы вместо зашитых чисел (НЕ ОБСУЖДАЕТСЯ):
- Каждая ячейка прогноза, маржи, коэффициента дисконтирования, приведённой стоимости (PV) и чувствительности ОБЯЗАНА быть живой формулой Excel, а не значением, посчитанным в Python и записанным числом
- В openpyxl:
ws["D20"] = "=D19*(1+$B$8)"— правильно;ws["D20"] = calculated_revenue— НЕПРАВИЛЬНО - Зашитые числа допустимы только в трёх случаях: (1) исходные исторические данные, (2) драйверы допущений (темпы роста, вводные для WACC, терминальный рост g), (3) текущие рыночные данные (цена акции, остаток долга)
- Если ты ловишь себя на том, что считаешь что-то в Python и записываешь результат, ОСТАНОВИСЬ. Модель должна пересчитываться, когда пользователь меняет допущение.
Проверяй каждый шаг вместе с пользователем (НЕ строй модель от начала до конца за один заход):
- После получения данных → покажи пользователю блок исходных вводных (выручка, маржа, акции, чистый долг) и подтверди, прежде чем делать прогноз
- После прогноза выручки → покажи прогнозную верхнюю строку и темпы роста, подтверди, прежде чем строить маржу
- После построения FCF → покажи весь график FCF, подтверди логику, прежде чем считать WACC
- После WACC → покажи расчёт и вводные, подтверди, прежде чем дисконтировать
- После терминальной стоимости и PV → покажи переход от стоимости предприятия к стоимости капитала (EV → стоимость капитала → на акцию), подтверди, прежде чем строить таблицы чувствительности
- Лови ошибки на каждом этапе: неверное допущение по марже, найденное после построения таблиц чувствительности, означает пересборку всего, что ниже
Таблицы чувствительности:
- Используй НЕЧЁТНОЕ число строк и столбцов (стандарт: 5×5, иногда 7×7) — это гарантирует настоящую центральную ячейку
- Центральная ячейка = базовый сценарий. Построй значения осей так, чтобы заголовок средней строки и заголовок среднего столбца точно равнялись допущениям модели (например, если базовый WACC = 9,0 %, то средняя строка равна 9,0 %; если терминальный рост g = 3,0 %, то средний столбец равен 3,0 %). Значит, результат в центральной ячейке должен равняться фактической расчётной цене акции модели — это проверка на здравый смысл, что таблица построена правильно.
- Выдели центральную ячейку средне-синей заливкой (
#BDD7EE) и жирным шрифтом, чтобы сразу было видно, какая ячейка — базовый сценарий. - Заполни ВСЕ ячейки (обычно 3 таблицы × 25 ячеек = 75) полными формулами пересчёта DCF
- Используй циклы openpyxl (или Office JS), чтобы записывать формулы программно
- БЕЗ текста-заглушек, БЕЗ линейных приближений, БЕЗ ручных шагов
- Каждая ячейка должна пересчитывать полный DCF для своей комбинации допущений
Комментарии к ячейкам:
- Добавляй комментарии к ячейкам В МОМЕНТ создания каждого зашитого значения
- Формат: «Источник: [Система/Документ], [Дата], [Ссылка на место], [URL, если есть]»
- У каждой синей вводной ячейки должен быть комментарий, прежде чем переходить к следующему разделу
- Не откладывай на конец и не пиши «TODO: добавить источник»
Планирование раскладки модели:
- Определи положение строк ВСЕХ разделов ДО записи любых формул
- Сначала запиши ВСЕ заголовки и подписи
- Затем запиши ВСЕ разделители разделов и пустые строки
- ПОТОМ записывай формулы по зафиксированным позициям строк
- Проверяй формулы сразу после создания
Пересчёт формул:
- Перед сдачей запусти
python recalc.py model.xlsx 30 - Исправляй ВСЕ ошибки, пока статус не станет «success»
- Нужно ноль ошибок в формулах (#REF!, #DIV/0!, #VALUE! и т. д.)
Блоки сценариев:
- Создай отдельные блоки для сценариев Bear/Base/Bull (пессимистичный, базовый, оптимистичный)
- Внутри каждого блока покажи допущения по горизонтали по годам прогноза
- Используй формулы IF:
=IF($B$6=1,[Bear cell],IF($B$6=2,[Base cell],[Bull cell])) - Проверь, что формулы ссылаются на правильные ячейки блока сценария
Рабочий процесс DCF
Шаг 1: Получение и проверка данных
Получи данные с MCP-серверов, из данных пользователя и из интернета.
Приоритет источников данных:
- MCP-серверы (если настроены) — структурированные финансовые данные от поставщиков вроде Daloopa
- Данные пользователя — исторические финансовые данные из его исследований
- Веб-поиск и загрузка страниц — текущие цены, бета, долг и денежные средства, когда нужно
Чек-лист проверки:
- Проверь, чистый долг это или чистые денежные средства (критично для оценки)
- Подтверди число акций с учётом разводнения (проверь недавние выкупы и новые выпуски)
- Убедись, что историческая маржа согласуется с бизнес-моделью
- Сверь темпы роста выручки с отраслевыми ориентирами
- Проверь, что налоговая ставка разумна (обычно 21–28 %)
Шаг 2: Исторический анализ (3–5 лет)
Проанализируй и задокументируй:
- Тренды роста выручки: рассчитай CAGR, определи драйверы
- Динамика маржи: отслеживай валовую маржу, маржу EBIT, маржу FCF
- Капиталоёмкость: D&A и CapEx в % от выручки
- Эффективность оборотного капитала: изменения NWC в % от прироста выручки
- Показатели рентабельности: тренды ROIC, ROE
Создай сводные таблицы:
Исторические показатели (LTM):
Выручка: $X млн
Рост выручки: X % CAGR
Валовая маржа: X %
Маржа EBIT: X %
D&A в % от выручки: X %
CapEx в % от выручки: X %
Маржа FCF: X %
Шаг 3: Прогноз выручки
Методология:
- Начни с последней фактической выручки (LTM или последний финансовый год)
- Примени темпы роста для каждого года прогноза
- Показывай и суммы в долларах, И рассчитанный рост в %
Схема темпов роста:
- Годы 1–2: более высокий рост с учётом видимости в ближайшей перспективе
- Годы 3–4: постепенное замедление к среднеотраслевому
- Год 5 и дальше: приближение к терминальному темпу роста
Структура формулы:
- Выручка(год N) = Выручка(год N−1) × (1 + темп роста)
- Рост %(год N) = Выручка(год N) / Выручка(год N−1) − 1
Подход с тремя сценариями:
Bear Case: консервативный рост (например, 8–12 %)
Base Case: наиболее вероятный сценарий (например, 12–16 %)
Bull Case: оптимистичный рост (например, 16–20 %)
Шаг 4: Моделирование операционных расходов
Анализ постоянных и переменных затрат:
Операционные расходы должны отражать реалистичный операционный леверидж:
- Продажи и маркетинг (S&M): обычно 15–40 % выручки в зависимости от бизнес-модели
- Исследования и разработки (R&D): обычно 10–30 % для технологических компаний
- Общие и административные расходы (G&A): обычно 8–15 % выручки, с ростом компании показывают леверидж
Ключевые принципы:
- ВСЕ проценты считай от ВЫРУЧКИ, а не от валовой прибыли
- Моделируй операционный леверидж: доля должна снижаться по мере роста выручки
- Держи отдельные статьи для S&M, R&D, G&A
- Рассчитывай EBIT = валовая прибыль − общие операционные расходы
Схема расширения маржи:
Сейчас → Цель (год 5)
Валовая маржа: X % → Y % (обоснуй масштабом и эффективностью)
Маржа EBIT: X % → Y % (результат роста выручки и операционного левериджа)
Шаг 5: Расчёт свободного денежного потока
Строй FCF в правильной последовательности:
EBIT
(−) Налоги (EBIT × налоговая ставка)
= NOPAT (операционная прибыль после налогов)
(+) D&A (неденежный расход, % от выручки)
(−) CapEx (% от выручки, обычно 4–8 %)
(−) Δ NWC (изменение оборотного капитала)
= Свободный денежный поток до обслуживания долга (Unlevered FCF)
Моделирование оборотного капитала:
- Считай как % от изменения выручки (прироста выручки)
- Типичный диапазон: от −2 % до +2 % от изменения выручки
- Отрицательное число = источник денег (высвобождение оборотного капитала)
- Положительное число = использование денег (рост оборотного капитала)
Поддерживающий и ростовой CapEx:
- Поддерживающий CapEx: поддерживает текущую деятельность (~2–3 % выручки)
- Ростовой CapEx: поддерживает расширение (ещё 2–5 % выручки)
- Общий CapEx должен соответствовать стратегии роста компании
Шаг 6: Исследование стоимости капитала (WACC)
Методология CAPM для стоимости собственного капитала:
Стоимость собственного капитала = Безрисковая ставка + Бета × Премия за риск акций
Где:
- Безрисковая ставка = текущая доходность 10-летних казначейских облигаций
- Бета = 5-летняя месячная бета акции относительно рыночного индекса
- Премия за риск акций = 5,0–6,0 % (рыночный стандарт)
Расчёт стоимости долга:
Стоимость долга после налогов = Стоимость долга до налогов × (1 − налоговая ставка)
Определи стоимость долга до налогов по:
- Кредитному рейтингу (если он есть)
- Текущей доходности облигаций компании
- Процентным расходам / общему долгу из финансовой отчётности
Веса структуры капитала:
Рыночная стоимость капитала = Текущая цена акции × Число акций
Чистый долг = Общий долг − Денежные средства и эквиваленты
Стоимость предприятия = Рыночная капитализация + Чистый долг
Вес капитала = Рыночная капитализация / Стоимость предприятия
Вес долга = Чистый долг / Стоимость предприятия
WACC = (Стоимость собственного капитала × Вес капитала) + (Стоимость долга после налогов × Вес долга)
Особые случаи:
- Положение чистых денежных средств: если денежные средства больше долга, чистый долг ОТРИЦАТЕЛЕН
- Вес долга может быть отрицательным
- Расчёт WACC соответственно корректируется
- Нет долга: WACC = стоимость собственного капитала
Типичные диапазоны WACC:
- Крупные устойчивые компании: 7–9 %
- Растущие компании: 9–12 %
- Высокий рост и высокий риск: 12–15 %
Шаг 7: Применение ставки дисконтирования (прогноз на 5–10 лет)
Конвенция середины года:
- Предполагается, что денежные потоки возникают в середине года
- Периоды дисконтирования: 0,5; 1,5; 2,5; 3,5; 4,5 и т. д.
- Коэффициент дисконтирования = 1 / (1 + WACC)^период
Расчёт приведённой стоимости:
Для каждого года прогноза:
PV от FCF = FCF до обслуживания долга × Коэффициент дисконтирования
Пример (год 1):
FCF = $1 000
WACC = 10 %
Период = 0,5
Коэффициент дисконтирования = 1 / (1,10)^0,5 = 0,9535
PV = $1 000 × 0,9535 = $954
Выбор периода прогноза:
- 5 лет: стандарт для большинства анализов
- 7–10 лет: растущие компании с долгим горизонтом
- 3 года: зрелый, стабильный бизнес
Шаг 8: Расчёт терминальной стоимости
Метод вечного роста (предпочтительный):
Терминальный FCF = FCF последнего года × (1 + терминальный темп роста)
Терминальная стоимость = Терминальный FCF / (WACC − терминальный темп роста)
Критичное ограничение: терминальный рост < WACC (иначе стоимость бесконечна)
Выбор терминального темпа роста:
- Консервативный: 2,0–2,5 % (темп роста ВВП)
- Умеренный: 2,5–3,5 %
- Агрессивный: 3,5–5,0 % (только для лидеров рынка)
Не превышай: безрисковую ставку или долгосрочный рост ВВП
Метод мультипликатора выхода (альтернатива):
Терминальная стоимость = EBITDA последнего года × Мультипликатор выхода
Откуда брать мультипликатор выхода:
- Торговые мультипликаторы сопоставимых компаний отрасли
- Мультипликаторы предыдущих сделок
- Типичный диапазон: 8–15x EBITDA
Приведённая стоимость терминальной стоимости:
PV терминальной стоимости = Терминальная стоимость / (1 + WACC)^Последний период
Где последний период учитывает момент времени:
Модель на 5 лет с конвенцией середины года: период = 4,5
Проверка терминальной стоимости на здравый смысл:
- Должна составлять 50–70 % стоимости предприятия
- Если больше 75 %, модель, возможно, слишком зависит от терминальных допущений
- Если меньше 40 %, проверь, не слишком ли консервативны терминальные допущения
Шаг 9: Переход от стоимости предприятия к стоимости капитала
Структура сводки по оценке:
(+) Сумма PV прогнозных FCF = $X млн
(+) PV терминальной стоимости = $Y млн
= Стоимость предприятия = $Z млн
(−) Чистый долг [или + чистые денежные средства, если отрицательный] = $A млн
= Стоимость капитала = $B млн
÷ Число акций с учётом разводнения = C млн акций
= Расчётная цена за акцию = $XX.XX
Текущая цена акции = $YY.YY
Расчётная доходность = (Расчётная цена / Текущая цена) − 1 = XX %
Критичные корректировки:
- Чистый долг = общий долг − денежные средства и эквиваленты
- Если положительный: вычитается из EV (снижает стоимость капитала)
- Если отрицательный (чистые денежные средства): прибавляется к EV (повышает стоимость капитала)
- Используй акции с учётом разводнения: включают опционы, RSU, конвертируемые ценные бумаги
- Другие корректировки (если применимо):
- Доли меньшинства
- Пенсионные обязательства
- Обязательства по операционной аренде
Формат вывода оценки:
Компонент оценки,Сумма ($ млн)
PV явных FCF,X.X
PV терминальной стоимости,Y.Y
Стоимость предприятия,Z.Z
(−) Чистый долг,A.A
Стоимость капитала,B.B
,,
Число акций (млн),C.C
Расчётная цена за акцию,$XX.XX
Текущая цена акции,$YY.YY
Расчётный рост/(падение),+XX%
Шаг 10: Анализ чувствительности
Построй три таблицы чувствительности внизу листа DCF, показывающие, как меняется оценка при разных допущениях:
- WACC и терминальный рост — показывает чувствительность стоимости предприятия к ставке дисконтирования и вечному росту
- Рост выручки и маржа EBIT — показывает влияние роста верхней строки и операционного левериджа
- Бета и безрисковая ставка — показывает чувствительность к составляющим стоимости собственного капитала
Реализация: это простые двумерные сетки (НЕ функция Excel «Таблица данных») с формулами в каждой ячейке. Каждая ячейка должна содержать полный пересчёт DCF для своей комбинации допущений. Подробные требования к программному заполнению всех 75 ячеек через openpyxl — в разделе «Критичные ограничения».
<correct_patterns>
В этом разделе собраны все ПРАВИЛЬНЫЕ шаблоны, которым нужно следовать при построении DCF-моделей.
Шаблон выбора блока сценария — следуй этому подходу
Допущения организованы в отдельные блоки для каждого сценария:
КРИТИЧНАЯ СТРУКТУРА — три строки на каждый заголовок раздела:
ДОПУЩЕНИЯ ПЕССИМИСТИЧНОГО СЦЕНАРИЯ (BEAR CASE; заголовок раздела, объедини ячейки по ширине)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),12%,10%,9%,8%,7%
Маржа EBIT (%),45%,44%,43%,42%,41%
ДОПУЩЕНИЯ БАЗОВОГО СЦЕНАРИЯ (BASE CASE; заголовок раздела, объедини ячейки по ширине)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),16%,14%,12%,10%,9%
Маржа EBIT (%),48%,49%,50%,51%,52%
ДОПУЩЕНИЯ ОПТИМИСТИЧНОГО СЦЕНАРИЯ (BULL CASE; заголовок раздела, объедини ячейки по ширине)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),20%,18%,15%,13%,11%
Маржа EBIT (%),50%,51%,52%,53%,54%
В каждом блоке сценария ОБЯЗАТЕЛЬНО должна быть строка заголовков столбцов с годами прогноза (FY2025E, FY2026E и т. д.) сразу под названием раздела. Без неё пользователь не поймёт, какое значение допущения относится к какому году.
Как ссылаться на допущения — создай сводный столбец:
- Ячейка выбора сценария (например, B6) содержит 1 = Bear, 2 = Base или 3 = Bull
- Создай сводный столбец с формулами INDEX или OFFSET, которые берут значения из нужного блока сценария
- Формулы прогноза ссылаются на сводный столбец (чистые ссылки на ячейки)
- Каждый блок сценария содержит полный набор допущений DCF по годам прогноза
Рекомендуемый шаблон сводного столбца (через INDEX): =INDEX(B10:D10, 1, $B$6)
НЕ так — разбросанные по всей модели операторы IF: =IF($B$6=1,[Bear block cell],IF($B$6=2,[Base block cell],[Bull block cell]))
Сводный столбец централизует логику и облегчает аудит модели.
Правильный шаблон прогноза выручки
Создай сводный столбец с формулами INDEX, затем ссылайся на него в прогнозе:
Шаг 1 — сводный столбец для роста FY1: =INDEX([Bear FY1 growth]:[Bull FY1 growth], 1, $B$6)
Шаг 2 — прогноз выручки ссылается на сводный столбец: Revenue Year 1: =D29*(1+$E$10)
Где:
- D29 = выручка предыдущего года
- $E$10 = ячейка сводного столбца для роста FY1 (содержит формулу INDEX)
- $B$6 = выбор сценария (1 = Bear, 2 = Base, 3 = Bull)
Такой подход чище, чем вставка операторов IF в каждую формулу прогноза, и сильно облегчает проверку, какие допущения сценария используются.
Правильный шаблон формул FCF
Используй сводные столбцы с формулами INDEX, затем ссылайся на них в расчётах FCF:
Подход со сводным столбцом:
Статья,Формула,Ссылка
D&A,=E29*$E$21,$E$21 = сводный столбец для % D&A
CapEx,=E29*$E$22,$E$22 = сводный столбец для % CapEx
Δ NWC,=(E29-D29)*$E$23,$E$23 = сводный столбец для % NWC
Unlevered FCF,=E57+E58-E60-E62,E57=NOPAT E58=D&A E60=CapEx E62=Δ NWC
Каждая ячейка сводного столбца содержит формулу INDEX, которая берёт значение из нужного блока сценария в зависимости от выбранного сценария. Так формулы прогноза остаются чистыми и проверяемыми.
Перед записью формул подтверди положение строк блоков сценариев и настрой сводные столбцы.
Правильный формат комментария к ячейке
Каждое зашитое значение требует такого формата:
«Источник: [Система/Документ], [Дата], [Ссылка на место], [URL, если есть]»
Примеры:
Статья,Комментарий об источнике
Цена акции,Источник: скрипт рыночных данных 2025-10-12 цена закрытия
Число акций,Источник: 10-K за FY2024 стр. 45 примечание 12
Историческая выручка,Источник: 10-K за FY2024 стр. 32 консолидированная отчётность
Бета,Источник: скрипт рыночных данных 2025-10-12 5-летняя месячная бета
Консенсус-оценки,Источник: прогноз менеджмента на звонке по итогам 3 кв. 2024
Правильная структура таблицы допущений
ВАЖНО: каждому блоку сценария нужны ТРИ структурных элемента:
- Строка заголовка раздела (объединённые ячейки): например, «ДОПУЩЕНИЯ ПЕССИМИСТИЧНОГО СЦЕНАРИЯ»
- Строка заголовков столбцов с годами — ЭТО ОБЯЗАТЕЛЬНО, НЕ ПРОПУСКАЙ
- Строки данных со значениями допущений
Структура:
ДОПУЩЕНИЯ ПЕССИМИСТИЧНОГО СЦЕНАРИЯ (заголовок раздела — объедини по столбцам A:G)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),X%,X%,X%,X%,X%
Маржа EBIT (%),X%,X%,X%,X%,X%
Терминальный рост,X%,,,,
WACC,X%,,,,
ДОПУЩЕНИЯ БАЗОВОГО СЦЕНАРИЯ (заголовок раздела — объедини по столбцам A:G)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),X%,X%,X%,X%,X%
Маржа EBIT (%),X%,X%,X%,X%,X%
Терминальный рост,X%,,,,
WACC,X%,,,,
ДОПУЩЕНИЯ ОПТИМИСТИЧНОГО СЦЕНАРИЯ (заголовок раздела — объедини по столбцам A:G)
Допущение,FY1,FY2,FY3,FY4,FY5
Рост выручки (%),X%,X%,X%,X%,X%
Маржа EBIT (%),X%,X%,X%,X%,X%
Терминальный рост,X%,,,,
WACC,X%,,,,
БЕЗ строки заголовков столбцов с годами прогноза (FY2025E, FY2026E и т. д.) пользователь не поймёт, какое значение допущения относится к какому году. Эта строка ОБЯЗАТЕЛЬНА.
Затем создай сводный столбец (обычно следующий столбец справа), в котором формулы INDEX берут значения из выбранного блока сценария по ячейке выбора сценария. На этот сводный столбец ссылаются твои формулы прогноза.
Правильный порядок планирования строк
1. СНАЧАЛА запиши ВСЕ заголовки и подписи:
Строка,Содержимое
1,[Название компании] — DCF-модель
2,Тикер | Дата | Конец финансового года
4,Выбор сценария
7,КЛЮЧЕВЫЕ ДОПУЩЕНИЯ
26,Заголовки допущений
27-31,Допущения по росту
...,...
2. Запиши ВСЕ разделители разделов и пустые строки
3. ПОТОМ записывай формулы по зафиксированным позициям строк
4. Проверяй формулы сразу после создания
Думай как на стройке:
- Хорошо: сначала залить фундамент, потом возводить стены (устойчивая конструкция)
- Плохо: сначала возвести стены, потом заливать фундамент (стены рухнут)
Версия для Excel:
- Хорошо: добавить заголовки, потом писать формулы (формулы стабильны)
- Плохо: сначала написать формулы, потом добавлять заголовки (формулы ломаются)
Правильная реализация таблицы чувствительности
ВАЖНО: это НЕ функция Excel «Таблица данных» (Data Table). Это простые сетки, в которые ты записываешь обычные формулы через openpyxl. Да, это примерно 75 формул (3 таблицы по 25 ячеек), но это несложно и обязательно.
Программное заполнение формулами:
Каждая таблица чувствительности должна быть полностью заполнена формулами, которые пересчитывают расчётную цену акции для каждой комбинации допущений. Не используй функцию Excel «Таблица данных» (она требует ручных действий и не автоматизируется через openpyxl).
Подход к реализации — КОНКРЕТНЫЙ ПРИМЕР:
Структура таблицы — сетка 5×5 (НЕЧЁТНЫЕ размеры, базовый сценарий в центре):
Если базовый WACC модели = 9,0 %, а базовый терминальный рост = 3,0 %, построй оси симметрично вокруг этих значений:
WACC и терминальный рост, 2.0%, 2.5%, 3.0%, 3.5%, 4.0%
8.0%, [ф-ла], [ф-ла], [ф-ла], [ф-ла], [ф-ла]
8.5%, [ф-ла], [ф-ла], [ф-ла], [ф-ла], [ф-ла]
9.0%, [ф-ла], [ф-ла], [★ ], [ф-ла], [ф-ла] ← средняя строка = базовый WACC
9.5%, [ф-ла], [ф-ла], [ф-ла], [ф-ла], [ф-ла]
10.0%, [ф-ла], [ф-ла], [ф-ла], [ф-ла], [ф-ла]
↑
средний столбец = базовый терминальный рост g
★ = центральная ячейка. Результат её формулы ДОЛЖЕН равняться фактической расчётной цене акции модели (из сводки по оценке). Примени к этой ячейке средне-синюю заливку (#BDD7EE) и жирный шрифт, чтобы базовый сценарий был визуально закреплён.
Правило значений осей: axis_values = [base - 2*step, base - step, base, base + step, base + 2*step] — симметрично вокруг базового значения, нечётное число значений гарантирует центр.
Шаблон формулы — ячейка B88 (WACC = 8,0 %, терминальный рост = 2,0 %):
Формула в B88 должна пересчитать расчётную цену, используя:
- WACC из заголовка строки:
$A88(8,0 %) - Терминальный рост из заголовка столбца:
B$87(2,0 %)
Рекомендуемый подход: ссылайся на основной расчёт DCF, но подставляй эти значения.
Пример структуры формулы: =([SUM of PV FCFs using $A88 as discount rate] + [Terminal Value using B$87 as growth rate and $A88 as WACC] - [Net Debt]) / [Shares]
ВАЖНО — запиши формулу в КАЖДУЮ ячейку сетки 5×5 (25 ячеек на таблицу, 75 ячеек всего). Используй openpyxl, чтобы записывать эти формулы программно в цикле. НЕ пропускай этот шаг и не оставляй текст-заглушки.
Шаблон реализации на Python:
# Pseudocode for populating sensitivity table
for row_idx, wacc_value in enumerate(wacc_range):
for col_idx, term_growth_value in enumerate(term_growth_range):
# Build formula that uses wacc_value and term_growth_value
formula = f"=<DCF recalc using {wacc_value} and {term_growth_value}>"
ws.cell(row=start_row+row_idx, column=start_col+col_idx).value = formula
Таблицы чувствительности должны работать сразу после открытия модели, без ручных шагов со стороны пользователя.
</correct_patterns>
<common_mistakes>
В этом разделе собраны все НЕПРАВИЛЬНЫЕ шаблоны, которых нужно избегать при построении DCF-моделей.
НЕПРАВИЛЬНО: упрощённые приближения таблиц чувствительности или текст-заглушки
Не используй линейные приближения:
// WRONG - Linear approximation
B97: =B88*(1+(0.096-0.116)) // Assumes linear relationship
// WRONG - Division shortcut
B105: =B88/(1+(E48-0.07)) // Doesn't recalculate full DCF
Не оставляй текст-заглушки:
// НЕПРАВИЛЬНО — заметка-заглушка
"Примечание: используйте функцию Excel «Таблица данных» (Данные → Анализ «что если» → Таблица данных), чтобы заполнить таблицы чувствительности."
// НЕПРАВИЛЬНО — пустые ячейки
[оставить ячейки пустыми, потому что «это сложно»]
Не путай терминологию:
- ❌ «Таблицам чувствительности нужна функция Excel “Таблица данных”» (НЕТ — это конкретный инструмент Excel, который мы не можем использовать)
- ✅ «Таблицы чувствительности — это простые сетки с формулами в каждой ячейке» (ДА — именно это мы строим)
Почему эти упрощения неправильны:
- Формулы линейного приближения на самом деле не пересчитывают DCF, а лишь применяют простые математические поправки
- Зависимости нелинейны, поэтому результаты будут неточными
- Текст-заглушка требует ручного вмешательства пользователя
- Модель не готова к использованию сразу после сдачи
- Это непрофессионально и не годится для клиента
- Пустые ячейки = незавершённый результат
Типичное оправдание, которое нужно ОТВЕРГАТЬ: «Писать больше 75 формул кажется сложным, поэтому я оставлю пользователю заметку, чтобы он закончил вручную».
Реальность: писать 75 формул несложно, если использовать цикл Python с openpyxl. Каждая формула следует одному шаблону — нужно только подставить значения строки и столбца. Это обязательная часть результата.
Вместо этого: заполни каждую ячейку чувствительности формулами, которые пересчитывают полный DCF для этой конкретной комбинации допущений
НЕПРАВИЛЬНО: отсутствие комментариев к ячейкам
Не делай так:
- Создавать все зашитые вводные без комментариев
- Думать «добавлю потом»
- Писать «TODO: добавить источник»
- Оставлять синие вводные без документации
Почему это неправильно:
- Нельзя проверить, откуда взяты данные
- Не соответствует требованиям скилла xlsx
- Не готово к аудиту
- Время тратится на исправление потом
Вместо этого: добавляй комментарий к ячейке В МОМЕНТ создания каждого зашитого значения
НЕПРАВИЛЬНО: сбившиеся ссылки на строки в формулах
Симптом: Раздел FCF ссылается на неверные строки допущений: D&A: =E29*$E$34 // Should be $E$21, but referencing wrong row CapEx: =E29*$E$41 // Should be $E$22, but row shifted
Почему так происходит:
- Сначала написали формулы
- Потом вставили заголовки
- Все ссылки на строки сместились
- Теперь формулы указывают на неверные ячейки → ошибки #REF!
Вместо этого: СНАЧАЛА зафиксируй раскладку строк, ПОТОМ пиши формулы
НЕПРАВИЛЬНО: одна строка на каждое допущение сразу для всех сценариев
Не структурируй допущения так:
Допущение,Bear,Base,Bull
Рост выручки FY1,10%,13%,16%
Рост выручки FY2,9%,12%,15%
Такая вертикальная раскладка мешает увидеть, как допущения меняются по годам внутри каждого сценария.
Почему это неправильно:
- Трудно увидеть, как допущения развиваются по годам внутри каждого сценария
- Сложнее сравнивать допущения сценариев на всём периоде прогноза
- Менее интуитивно для проверки логики сценариев
Вместо этого:
- Создай отдельные блоки для каждого сценария (Bear, Base, Bull)
- Внутри каждого блока покажи допущения по горизонтали по годам прогноза
- Так допущения каждого сценария легче проверять как единый набор
НЕПРАВИЛЬНО: нет границ
Не сдавай модель без границ:
- Нет разделения разделов
- Все ячейки сливаются
- Трудно читать, выглядит непрофессионально
Почему это неправильно:
- Не годится для клиента
- Трудно ориентироваться
- Выглядит любительски
Вместо этого: добавь границы вокруг всех основных разделов
НЕПРАВИЛЬНО: неверные цвета шрифта или нет различия цветов шрифта
Не делай так:
- Весь текст чёрный
- Используются только цвета заливки (шрифт не меняется)
- Путаются синие и чёрные ячейки
Почему это неправильно:
- Нельзя отличить вводные от формул
- Аудит становится невозможным
- Нарушает требования скилла xlsx
Вместо этого: синий шрифт для ВСЕХ зашитых вводных, чёрный для ВСЕХ формул, зелёный для ссылок на листы
НЕПРАВИЛЬНО: операционные расходы от валовой прибыли
Не делай так: S&M: =E33*0.15 // E33 = Gross Profit (WRONG)
Почему это неправильно:
- Операционные расходы масштабируются с выручкой, а не с валовой прибылью
- Получается нереалистичная динамика маржи
- Бизнес на самом деле устроен иначе
Вместо этого: S&M: =E29*0.15 // E29 = Revenue (CORRECT)
ПЯТЬ ГЛАВНЫХ ОШИБОК: СВОДКА
- Сбившиеся ссылки на строки в формулах → определи положение ВСЕХ строк ДО записи формул
- Нет комментариев к ячейкам → добавляй комментарии В МОМЕНТ создания ячеек, а не в конце
- Упрощённые таблицы чувствительности → заполни все ячейки формулами полного пересчёта DCF, а не приближениями
- Неверные ссылки на блоки сценариев → убедись, что формулы IF берут данные из правильных блоков Bear/Base/Bull
- Нет границ → добавь профессиональные границы разделов, чтобы модель выглядела готовой для клиента
Кроме того, учитывай эти ошибки:
Ошибки в расчёте WACC
- Смешивание балансовых и рыночных значений в структуре капитала
- Неверное использование беты капитала вместо беты активов (без рычага)
- Неверное применение налоговой ставки к стоимости долга
- Неверная безрисковая ставка (нужна текущая доходность 10-летних казначейских облигаций)
- Отсутствие поправки на чистый долг или чистые денежные средства
Ошибки в допущениях по росту
- Терминальный рост > WACC (создаёт бесконечную стоимость)
- Темпы роста в прогнозе не согласуются с историческими результатами
- Игнорирование отраслевых ограничений роста
- Рост выручки не согласован с юнит-экономикой
- Расширение маржи без операционного обоснования
Ошибки в терминальной стоимости
- Выбран неверный метод роста (вечный рост или мультипликатор выхода)
- Терминальная стоимость >80 % стоимости предприятия (признак чрезмерной зависимости)
- Терминальная маржа не согласуется с допущениями устойчивого состояния
- Неверный период дисконтирования терминальной стоимости
Ошибки в прогнозе денежных потоков
- Операционные расходы считаются от валовой прибыли вместо выручки
- Проценты D&A и CapEx не соответствуют бизнес-модели
- Изменения оборотного капитала посчитаны неверно
- Налоговая ставка несогласованна по годам
- Ошибки в расчёте NOPAT
Это самые частые ошибки. Перечитай этот раздел перед началом любого построения DCF.
</common_mistakes>
Создание файла Excel
**Этот скилл использует скилл xlsx для всех операций с таблицами.** Скилл xlsx даёт:
- Стандартизированные правила построения формул
- Правила форматирования чисел
- Автоматический пересчёт формул через скрипт
recalc.py - Подробную проверку ошибок и валидацию
Все файлы Excel, созданные этим скиллом, должны соответствовать требованиям скилла xlsx, включая ноль ошибок в формулах и правильный пересчёт.
Критерии качества
Каждая DCF-модель должна максимально соответствовать следующим критериям:
- Реалистичные допущения по выручке и марже, основанные на исторических результатах
- Правильный расчёт стоимости капитала по методологии CAPM
- Всесторонний анализ чувствительности, показывающий диапазоны оценки
- Понятный расчёт терминальной стоимости с обоснованием
- Профессиональная структура модели, позволяющая анализ сценариев
- Прозрачная документация всех ключевых допущений
Требования ко входным данным
Минимально необходимые вводные
- Идентификатор компании: тикер или название компании
- Допущения по росту: темпы роста выручки на период прогноза (или «используй консенсус»)
- Необязательные параметры:
- Период прогноза (по умолчанию: 5 лет)
- Сценарии (допущения по росту и марже Bear/Base/Bull)
- Терминальный темп роста (по умолчанию: 2,5–3,0 %)
- Конкретные вводные для WACC, если не используется CAPM
Структура модели Excel
Архитектура листов
Создай два листа:
- DCF — основная модель оценки с анализом чувствительности внизу
- WACC — расчёт стоимости капитала
ВАЖНО: таблицы чувствительности размещаются ВНИЗУ листа DCF (а не на отдельном листе). Так все результаты оценки собраны вместе.
Пересчёт формул (ОБЯЗАТЕЛЬНО)
После создания или изменения модели Excel пересчитай все формулы с помощью скрипта recalc.py из скилла xlsx:
python recalc.py [path_to_excel_file] [timeout_seconds]
Пример:
python recalc.py AAPL_DCF_Model_2025-10-12.xlsx 30
Скрипт:
- Пересчитывает все формулы на всех листах через LibreOffice
- Сканирует ВСЕ ячейки на ошибки Excel (#REF!, #DIV/0!, #VALUE!, #NAME?, #NULL!, #NUM!, #N/A)
- Возвращает подробный JSON с местами и числом ошибок
Ожидаемый формат вывода:
{
"status": "success", // or "errors_found"
"total_errors": 0, // Total error count
"total_formulas": 42, // Number of formulas in file
"error_summary": {} // Only present if errors found
}
Если найдены ошибки, вывод будет содержать подробности:
{
"status": "errors_found",
"total_errors": 2,
"total_formulas": 42,
"error_summary": {
"#REF!": {
"count": 2,
"locations": ["DCF!B25", "DCF!C25"]
}
}
}
Исправь все ошибки и перезапускай recalc.py, пока статус не станет «success», и только потом сдавай модель.
Стандарты форматирования
ВАЖНО: следуй скиллу xlsx в правилах построения формул и форматирования чисел. Скилл DCF добавляет свои стандарты визуального оформления.
Цветовая схема — два слоя:
Слой 1: цвета шрифта (ОБЯЗАТЕЛЬНО по скиллу xlsx)
- Синий текст (RGB: 0,0,255): ВСЕ зашитые вводные (цена акции, число акций, исторические данные, допущения)
- Чёрный текст (RGB: 0,0,0): ВСЕ формулы и расчёты
- Зелёный текст (RGB: 0,128,0): ссылки на другие листы (ссылки на лист WACC)
Слой 2: цвета заливки — профессиональная сине-серая палитра (по умолчанию, если пользователь не указал иного)
- Держи минимализм: для заливок используй только синий и серый. НЕ добавляй зелёный, жёлтый, оранжевый и несколько акцентных цветов. Модель со слишком большим числом цветов выглядит любительски.
- Палитра заливок по умолчанию:
- Заголовки разделов: тёмно-синий фон (RGB: 31,78,121 /
#1F4E79) с белым жирным текстом - Подзаголовки и заголовки столбцов: светло-синий фон (RGB: 217,225,242 /
#D9E1F2) с чёрным жирным текстом - Ячейки ввода: светло-серый фон (RGB: 242,242,242 /
#F2F2F2) с синим шрифтом — или просто белый фон с синим шрифтом, если нужен максимальный минимализм - Расчётные ячейки: белый фон с чёрным шрифтом
- Итоговые строки и результаты (стоимость на акцию, EV и т. д.): средне-синий фон (RGB: 189,215,238 /
#BDD7EE) с чёрным жирным шрифтом - Вот и всё — 3 синих + 1 серый + белый. Сопротивляйся желанию добавить ещё.
- Шаблоны пользователя и его явные пожелания по цветам ВСЕГДА важнее этих настроек по умолчанию.
Как слои работают вместе:
- Ячейка ввода: синий шрифт + светло-серая заливка = «зашитая вводная»
- Ячейка с формулой: чёрный шрифт + белый фон = «расчётное значение»
- Ссылка на лист: зелёный шрифт + белый фон = «ссылка с другого листа»
- Ключевой результат: чёрный жирный шрифт + средне-синяя заливка = «это ответ»
Цвет шрифта говорит, ЧТО это (ввод, формула, ссылка). Цвет заливки говорит, ГДЕ ты находишься (заголовок, данные, результат).
Стандарты границ (ОБЯЗАТЕЛЬНЫ для профессионального вида)
Толстые границы (1,5 pt) вокруг основных разделов:
- Раздел КЛЮЧЕВЫХ ВВОДНЫХ
- Раздел ДОПУЩЕНИЙ ПРОГНОЗА
- Раздел ПРОГНОЗА ДЕНЕЖНЫХ ПОТОКОВ НА 5 ЛЕТ
- Раздел ТЕРМИНАЛЬНОЙ СТОИМОСТИ
- Раздел СВОДКИ ПО ОЦЕНКЕ
- Каждая таблица АНАЛИЗА ЧУВСТВИТЕЛЬНОСТИ
Средние границы (1 pt) между подразделами:
- Данные о компании и исторические результаты
- Допущения по росту, марже EBIT и параметрам FCF
Тонкие границы (0,5 pt) вокруг таблиц с данными:
- Таблицы допущений сценариев (Bear | Base | Bull | Выбранный)
- Матрица исторических и прогнозных показателей
Без границ: отдельные ячейки внутри таблиц (оставляй чисто и удобно для просмотра)
Границы обязательны: модели без профессиональных границ не годятся для клиента.
Форматы чисел (по стандартам скилла xlsx):
- Годы: формат текстовой строки (например, "2024", а не "2,024")
- Проценты:
0.0%(один знак после запятой) - Валюта:
$#,##0для миллионов;$#,##0.00для значений на акцию — ВСЕГДА указывай единицы в заголовках («Revenue ($mm)») - Нули: числовой формат должен показывать все нули как «-» (например,
$#,##0;($#,##0);-) - Большие числа:
#,##0с разделителем тысяч - Отрицательные числа:
(#,##0)в скобках (НЕ со знаком минус)
Комментарии к ячейкам (ОБЯЗАТЕЛЬНЫ для всех зашитых вводных):
По скиллу xlsx ВСЕ зашитые значения должны иметь комментарии к ячейкам с указанием источника. Формат: «Источник: [Система/Документ], [Дата], [Ссылка на место], [URL, если есть]»
ВАЖНО: добавляй комментарии В МОМЕНТ создания ячеек. Не откладывай на конец.
Подробная структура листа DCF
Раздел 1: Заголовок
Строка,Содержимое
1,[Название компании] — DCF-модель
2,Тикер: [XXX] | Дата: [дата] | Конец финансового года: [FYE]
3,Пусто
4,Ячейка выбора сценария (1=Bear 2=Base 3=Bull)
5,Отображение названия сценария (формула: =IF([Selector]=1"Bear"IF([Selector]=2"Base""Bull")))
Раздел 2: Рыночные данные (НЕ зависят от сценария)
Статья,Значение
Текущая цена акции,$XX.XX
Число акций (млн),XX.X
Рыночная капитализация ($ млн),[Формула]
Чистый долг ($ млн),XXX [или чистые денежные средства, если отрицательный]
Раздел 3: Допущения сценариев DCF
Создай отдельные блоки допущений для каждого сценария (Bear, Base, Bull) с допущениями DCF (рост выручки %, маржа EBIT %, налоговая ставка %, D&A в % от выручки, CapEx в % от выручки, изменение NWC в % от ΔВыручки, терминальный темп роста, WACC), расположенными по горизонтали по годам прогноза. В каждом блоке должны быть заголовок раздела, строка заголовков столбцов с годами прогноза (FY1, FY2 и т. д.) и строки данных. Точная раскладка — в разделе <correct_patterns> «Правильная структура таблицы допущений».
Раздел 4: Исторические и прогнозные финансовые показатели
Ссылайся на сводный столбец (например, «Выбранный сценарий»), который берёт данные из блоков сценариев, а не на разбросанные формулы IF в каждой строке прогноза.
Отчёт о прибылях и убытках ($ млн),2020A,2021A,2022A,2023A,2024E,2025E,2026E
Выручка,XXX,XXX,XXX,XXX,[=E29*(1+$E$10)],[=F29*(1+$E$11)],[=G29*(1+$E$12)]
% роста,XX%,XX%,XX%,XX%,[=E29/D29-1],[=F29/E29-1],[=G29/F29-1]
,,,,,,
Валовая прибыль,XXX,XXX,XXX,XXX,[=E29*E33],[=F29*F33],[=G29*G33]
% маржи,XX%,XX%,XX%,XX%,[=E33/E29],[=F33/F29],[=G33/G29]
,,,,,,
Операционные расходы:,,,,,,,
S&M,XXX,XXX,XXX,XXX,[=E29*0.15],[=F29*0.14],[=G29*0.13]
R&D,XXX,XXX,XXX,XXX,[=E29*0.12],[=F29*0.11],[=G29*0.10]
G&A,XXX,XXX,XXX,XXX,[=E29*0.08],[=F29*0.07],[=G29*0.07]
Всего OpEx,XXX,XXX,XXX,XXX,[=E36+E37+E38],[=F36+F37+F38],[=G36+G37+G38]
,,,,,,
EBIT,XXX,XXX,XXX,XXX,[=E33-E39],[=F33-F39],[=G33-G39]
% маржи,XX%,XX%,XX%,XX%,[=E41/E29],[=F41/F29],[=G41/G29]
,,,,,,
Налоги,(XX),(XX),(XX),(XX),[=E41*$E$24],[=F41*$E$24],[=G41*$E$24]
Налоговая ставка,XX%,XX%,XX%,XX%,[=E43/E41],[=F43/F41],[=G43/G41]
,,,,,,
NOPAT,XXX,XXX,XXX,XXX,[=E41-E43],[=F41-F43],[=G41-G43]
Ключевой шаблон формулы:
- Рост выручки:
=E29*(1+$E$10), где $E$10 — сводный столбец для роста первого года - НЕ так:
=E29*(1+IF($B$6=1,$B$10,IF($B$6=2,$C$10,$D$10)))
Такой подход чище, проще для аудита и предотвращает ошибки в формулах, потому что логика сценариев собрана в одном месте.
Раздел 5: Построение свободного денежного потока
ВАЖНО: убедись, что ссылки на строки указывают на ПРАВИЛЬНЫЕ строки допущений. Проверяй формулы сразу после создания.
Денежный поток ($ млн),2020A,2021A,2022A,2023A,2024E,2025E,2026E
NOPAT,XXX,XXX,XXX,XXX,[=E45],[=F45],[=G45]
(+) D&A,XXX,XXX,XXX,XXX,[=E29*$E$21],[=F29*$E$21],[=G29*$E$21]
% от выручки,XX%,XX%,XX%,XX%,[=E58/E29],[=F58/F29],[=G58/G29]
(-) CapEx,(XX),(XX),(XX),(XX),[=E29*$E$22],[=F29*$E$22],[=G29*$E$22]
% от выручки,XX%,XX%,XX%,XX%,[=E60/E29],[=F60/F29],[=G60/G29]
(-) Δ NWC,(XX),(XX),(XX),(XX),[=(E29-D29)*$E$23],[=(F29-E29)*$E$23],[=(G29-F29)*$E$23]
% от Δ выручки,XX%,XX%,XX%,XX%,[=E62/(E29-D29)],[=F62/(F29-E29)],[=G62/(G29-F29)]
,,,,,,
Unlevered FCF,XXX,XXX,XXX,XXX,[=E57+E58-E60-E62],[=F57+F58-F60-F62],[=G57+G58-G60-G62]
Примеры ссылок на строки (по плану раскладки):
- $E$21 = допущение «% D&A» (сводный столбец, строка 21)
- $E$22 = допущение «% CapEx» (сводный столбец, строка 22)
- $E$23 = допущение «% NWC» (сводный столбец, строка 23)
- E29 = выручка за год (строка 29)
- E45 = NOPAT за год (строка 45)
Перед записью формул: подтверди, что эти номера строк совпадают с фактической раскладкой. Проверь один столбец, затем скопируй вправо.
Раздел 6: Дисконтирование и оценка
Оценка DCF,2024E,2025E,2026E,2027E,2028E,Терминальный
Unlevered FCF ($ млн),XXX,XXX,XXX,XXX,XXX,
Период,0.5,1.5,2.5,3.5,4.5,
Коэффициент дисконтирования,0.XX,0.XX,0.XX,0.XX,0.XX,
PV от FCF ($ млн),XXX,XXX,XXX,XXX,XXX,
,,,,,,
Терминальный FCF ($ млн),,,,,,,XXX
Терминальная стоимость ($ млн),,,,,,,XXX
PV терминальной стоимости ($ млн),,,,,,,XXX
,,,,,,
Сводка по оценке ($ млн),,,,,,
Сумма PV FCF,XXX,,,,,
PV терминальной стоимости,XXX,,,,,
Стоимость предприятия,XXX,,,,,
(-) Чистый долг,(XX),,,,,
Стоимость капитала,XXX,,,,,
,,,,,,
Число акций (млн),XX.X,,,,,
РАСЧЁТНАЯ ЦЕНА ЗА АКЦИЮ,$XX.XX,,,,,
Текущая цена акции,$XX.XX,,,,,
Расчётный рост/(падение),XX%,,,,,
Структура листа WACC
РАСЧЁТ СТОИМОСТИ СОБСТВЕННОГО КАПИТАЛА,,
Безрисковая ставка (10-летние казначейские облигации),X.XX%,[Жёлтый ввод]
Бета (5 лет помесячно),X.XX,[Жёлтый ввод]
Премия за риск акций,X.XX%,[Жёлтый ввод]
Стоимость собственного капитала,X.XX%,[Расчёт синим]
,,
РАСЧЁТ СТОИМОСТИ ДОЛГА,,
Кредитный рейтинг,AA-,[Жёлтый ввод]
Стоимость долга до налогов,X.XX%,[Жёлтый ввод]
Налоговая ставка,XX.X%,[Ссылка на лист DCF]
Стоимость долга после налогов,X.XX%,[Расчёт синим]
,,
СТРУКТУРА КАПИТАЛА,,
Текущая цена акции,$XX.XX,[Ссылка на DCF]
Число акций (млн),XX.X,[Ссылка на DCF]
Рыночная капитализация ($ млн),"X,XXX",[Расчёт]
,,
Общий долг ($ млн),XXX,[Жёлтый ввод]
Денежные средства и эквиваленты ($ млн),XXX,[Жёлтый ввод]
Чистый долг ($ млн),XXX,[Расчёт]
,,
Стоимость предприятия ($ млн),"X,XXX",[Расчёт]
,,
РАСЧЁТ WACC,Вес,Стоимость,Вклад
Капитал,XX.X%,X.X%,X.XX%
Долг,XX.X%,X.X%,X.XX%
,,
СРЕДНЕВЗВЕШЕННАЯ СТОИМОСТЬ КАПИТАЛА,X.XX%,[Зелёный результат]
Ключевые формулы WACC:
Рыночная капитализация = Цена × Число акций
Чистый долг = Общий долг − Денежные средства
Стоимость предприятия = Рыночная капитализация + Чистый долг
Вес капитала = Рыночная капитализация / EV
Вес долга = Чистый долг / EV
WACC = (Стоимость собственного капитала × Вес капитала) + (Стоимость долга после налогов × Вес долга)
Анализ чувствительности (внизу листа DCF)
НАПОМИНАНИЕ О ТЕРМИНОЛОГИИ: «таблицы чувствительности» = простые двумерные сетки с заголовками строк, заголовками столбцов и формулами в каждой ячейке данных. НЕ функция Excel «Таблица данных» (Данные → Анализ «что если» → Таблица данных). Ты будешь записывать обычные формулы Excel в каждую ячейку через openpyxl.
Расположение: строки 87 и ниже на листе DCF (НЕ отдельный лист)
Три таблицы чувствительности, расположенные вертикально друг под другом:
- WACC и терминальный рост (строки 87–100) — сетка 5x5 = 25 ячеек с формулами
- Рост выручки и маржа EBIT (строки 102–115) — сетка 5x5 = 25 ячеек с формулами
- Бета и безрисковая ставка (строки 117–130) — сетка 5x5 = 25 ячеек с формулами
Всего формул для записи: 75 (это обязательно, не по желанию)
ВАЖНО: все ячейки таблиц чувствительности должны быть заполнены формулами программно через openpyxl. НЕ используй ярлыки с линейными приближениями. НЕ оставляй текст-заглушки или заметки о ручных шагах. НЕ оправдывай пустые ячейки тем, что «это сложно» — используй цикл Python, чтобы сгенерировать формулы.
Настройка таблицы:
- Создай структуру таблицы с заголовками строк и столбцов (проверяемые значения допущений)
- Заполни КАЖДУЮ ячейку данных формулой, которая:
- Использует значение заголовка строки (например, WACC = 9,0 %)
- Использует значение заголовка столбца (например, терминальный рост = 3,0 %)
- Пересчитывает полный DCF с этими конкретными допущениями
- Возвращает расчётную цену акции для этого сценария
- При сдаче все ячейки должны содержать рабочие формулы
- Отформатируй ячейки условным форматированием: зелёная шкала для больших значений, красная шкала для меньших
- Выдели жирным ячейку базового сценария
- Оставь 1–2 пустые строки между таблицами
Ручное вмешательство не требуется — таблицы чувствительности должны полностью работать, когда пользователь откроет файл.
Реализация выбора сценария
Структура из трёх сценариев:
Bear Case (пессимистичный сценарий)
- Консервативный рост выручки (нижняя граница исторического диапазона)
- Сжатие маржи или отсутствие расширения
- Более высокий WACC (рост премии за риск)
- Более низкий терминальный темп роста
- Более высокие допущения по CapEx
Base Case (базовый сценарий)
- Рост выручки по консенсусу или прогнозу менеджмента
- Умеренное расширение маржи за счёт операционного левериджа
- Текущий рыночный WACC
- Терминальный рост, согласованный с ВВП (2,5–3,0 %)
- Стандартные допущения по CapEx
Bull Case (оптимистичный сценарий)
- Оптимистичный рост выручки (верхняя граница прогнозов)
- Значительное расширение маржи
- Более низкий WACC (снижение премии за риск)
- Более высокий терминальный рост (3,5–5,0 %)
- Сниженная капиталоёмкость
Реализация формул:
НЕ используй вложенные формулы IF, разбросанные по всей модели. Вместо этого создай сводный столбец, использующий формулы INDEX или OFFSET, чтобы брать данные из нужного блока сценария.
Рекомендуемый шаблон (через INDEX): =INDEX(B10:D10, 1, $B$6), где B10:D10 = значения Bear/Base/Bull, 1 = смещение по строке, $B$6 = ячейка выбора сценария (1, 2 или 3)
Затем ссылайся на сводный столбец во всех прогнозах: Revenue Year 1: =D29*(1+$E$10), где $E$10 — значение сводного столбца для роста первого года.
Такой подход централизует логику сценариев, облегчая аудит и сопровождение модели.
Структура результата
Имя файла: [Ticker]_DCF_Model_[Date].xlsx
Два листа:
- DCF — полная модель со сценариями Bear/Base/Bull и тремя таблицами чувствительности внизу (WACC и терминальный рост, рост выручки и маржа EBIT, бета и безрисковая ставка)
- WACC — расчёт стоимости капитала
Ключевые особенности: выбор сценария (1/2/3), сводный столбец с формулами INDEX/OFFSET, цветовая кодировка ячеек, комментарии ко всем вводным, профессиональные границы
Лучшие практики
Построение модели
- Строй постепенно: заверши каждый раздел, прежде чем идти дальше
- Проверяй по ходу: вводи тестовые числа и проверяй формулы
- Используй единую структуру: похожие расчёты строй по похожим шаблонам
- Комментируй сложные формулы: добавляй заметки к нестандартным расчётам
- Встраивай проверки: проверки сумм и баланса, где применимо
Документация
- Документируй все допущения: объясняй логику ключевых вводных
- Указывай источники данных: отмечай, откуда взято каждое значение
- Объясняй методологию: описывай любые нестандартные подходы
- Отмечай неопределённость: выделяй области с ограниченной видимостью
Контроль качества
- Перепроверяй расчёты: проверяй математику разными способами
- Стресс-тестируй допущения: прогоняй чувствительность, чтобы убедиться, что модель устойчива
- Рецензирование коллегой: пусть кто-то другой проверит формулы
- Контроль версий: сохраняй версии по ходу работы
Типичные вариации
Быстрорастущие технологические компании
- Более длинный период прогноза (7–10 лет)
- Более высокие начальные темпы роста (20–30 %)
- Значительное расширение маржи со временем
- Более высокий WACC (12–15 %)
- Моделируй юнит-экономику (пользователи, ARPU и т. д.)
Зрелые и стабильные компании
- Более короткий период прогноза (3–5 лет)
- Скромные темпы роста (ВВП +1–3 %)
- Стабильная маржа
- Более низкий WACC (7–9 %)
- Фокус на генерации денег и распределении капитала
Циклические компании
- Моделируй на протяжении экономического цикла
- Нормализуй маржу на среднем уровне цикла
- Рассмотри сценарии дна и пика
- Скорректируй бету на цикличность
Компании с несколькими сегментами
- Отдельные DCF для каждого бизнес-подразделения
- Разные темпы роста и маржа по сегментам
- Оценка по сумме частей
- Учти синергии
Устранение неполадок
Если сталкиваешься с ошибками или нереалистичными результатами, прочитай [TROUBLESHOOTING.md](./TROUBLESHOOTING.md): там подробные рекомендации по отладке.
Встраивание в рабочий процесс
В начале построения DCF
- Собери рыночные данные:
- Проверь доступные MCP-серверы с текущими рыночными данными
- Используй веб-поиск и загрузку страниц для цен акций, беты и других рыночных показателей
- Запроси у пользователя, если нужны конкретные данные
- Собери исторические финансовые показатели:
- Проверь доступные MCP-серверы (Daloopa и др.)
- Запроси у пользователя, если через MCP недоступны
- При необходимости извлеки вручную из 10-K
- Начни построение модели по методологии DCF, подробно описанной в этом скилле
Во время построения модели
- Строй модель Excel через openpyxl с формулами (а не с зашитыми значениями)
- Следуй соглашениям скилла xlsx по построению формул и форматированию
- Применяй цвета заливки только по просьбе пользователя или при наличии конкретных брендбуков
Перед сдачей модели (ОБЯЗАТЕЛЬНО)
- Проверь структуру:
- Блоки сценариев Bear/Base/Bull с допущениями по годам прогноза
- Выбор сценария работает, формулы ссылаются на правильные блоки сценариев
- Таблицы чувствительности внизу листа DCF (не на отдельном листе)
- Цвета шрифта: синие вводные, чёрные формулы, зелёные ссылки на листы
- Комментарии к ячейкам у ВСЕХ зашитых вводных
- Профессиональные границы вокруг основных разделов
- Пересчитай формулы: запусти
python recalc.py model.xlsx 30
- Проверь результат:
- Если
statusравен"success"→ переходи к шагу 4 - Если
statusравен"errors_found"→ проверьerror_summaryи прочитай [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) с рекомендациями по отладке
- Исправь ошибки и перезапусти recalc.py, пока статус не станет «success»
- Выборочно проверь формулы:
- Проверь одну формулу FCF: ссылается ли она на правильные строки допущений?
- Смени сценарий: правильно ли обновляется сводный столбец?
- Убедись, что формулы выручки ссылаются на сводный столбец (а не на вложенные формулы IF)
- Сдай модель
Доступные источники данных
- MCP-серверы: если настроены (Daloopa для исторической отчётности)
- Веб-поиск и загрузка страниц: для текущих цен акций, беты и рыночных данных
- Данные пользователя: исторические финансовые показатели, консенсус-оценки
- Ручное извлечение: отчёты SEC EDGAR как запасной вариант
Итоговый чек-лист результата
Перед сдачей DCF-модели:
Обязательно:
- Запусти
python recalc.py model.xlsx 30, пока статус не станет «success» (ноль ошибок в формулах) - Два листа: DCF (с чувствительностью внизу), WACC
- Цвета шрифта: синий = вводные, чёрный = формулы, зелёный = ссылки на листы
- Комментарии к ячейкам у ВСЕХ зашитых вводных
- Таблицы чувствительности полностью заполнены формулами
- Профессиональные границы вокруг основных разделов
Проверка:
- OpEx считаются от выручки (а не от валовой прибыли)
- Терминальная стоимость составляет 50–70 % EV
- Терминальный рост < WACC
- Налоговая ставка 21–28 %
- Имя файла:
[Ticker]_DCF_Model_[Date].xlsx
Перевод: iiuniversitet. Оригинал: https://github.com/anthropics/financial-services/tree/main/plugins/agent-plugins/model-builder/skills/dcf-model, лицензия Apache-2.0. Изменения: перевод на русский язык.
Оригинал на английском
---
name: dcf-model
description: Real DCF (Discounted Cash Flow) model creation for equity valuation. Retrieves financial data from SEC filings and analyst reports, builds comprehensive cash flow projections with proper WACC calculations, performs sensitivity analysis, and outputs professional Excel models with executive summaries. Use when users need to value a company using DCF methodology, request intrinsic value analysis, or ask for detailed financial modeling with growth projections and terminal value calculations.
---
# DCF Model Builder
## Overview
This skill creates institutional-quality DCF models for equity valuation following investment banking standards. Each analysis produces a detailed Excel model (with sensitivity analysis included at the bottom of the DCF sheet).
## Tools
- Default to using all of the information provided by the user and MCP servers available for data sourcing.
## Critical Constraints - Read These First
These constraints apply throughout all DCF model building. Review before starting:
**Environment: Office JS vs Python/openpyxl:**
- **If running inside Excel (Office Add-in / Office JS environment):** Use Office JS directly — do NOT use Python/openpyxl. Write formulas via `range.formulas = [["=D19*(1+$B$8)"]]`. No separate recalc step needed; Excel calculates natively. Use `range.format.*` for styling. The same formulas-over-hardcodes rule applies: set `.formulas`, never `.values` for derived cells.
- **If generating a standalone .xlsx file (no live Excel session):** Use Python/openpyxl as described below, then run `recalc.py` before delivery.
- The rest of this skill uses openpyxl examples — translate to Office JS API calls when in that environment, but all principles (formula strings, cell comments, section checkpoints, sensitivity table loops) apply identically.
**⚠️ Office JS merged cell pitfall:** When building section headers with merged cells, do NOT call `.merge()` then set `.values` on the merged range — Office JS still reports the range's original dimensions and will throw `InvalidArgument: The number of rows or columns in the input array doesn't match the size or dimensions of the range`. Instead, write the value to the top-left cell alone, then merge and format the full range:
```js
// WRONG — throws InvalidArgument:
const hdr = ws.getRange("A7:H7");
hdr.merge();
hdr.values = [["MARKET DATA & KEY INPUTS"]]; // 1×1 array vs 1×8 range → fails
// CORRECT — value first on single cell, then merge + format the range:
ws.getRange("A7").values = [["MARKET DATA & KEY INPUTS"]];
const hdr = ws.getRange("A7:H7");
hdr.merge();
hdr.format.fill.color = "#1F4E79";
hdr.format.font.bold = true;
hdr.format.font.color = "#FFFFFF";
```
This applies to every merged section header in the DCF (market data, scenario blocks, cash flow projection, terminal value, valuation summary, sensitivity tables).
**Formulas Over Hardcodes (NON-NEGOTIABLE):**
- Every projection, margin, discount factor, PV, and sensitivity cell MUST be a live Excel formula — never a value computed in Python and written as a number
- When using openpyxl: `ws["D20"] = "=D19*(1+$B$8)"` is correct; `ws["D20"] = calculated_revenue` is WRONG
- The only hardcoded numbers permitted are: (1) raw historical inputs, (2) assumption drivers (growth rates, WACC inputs, terminal g), (3) current market data (share price, debt balance)
- If you catch yourself computing something in Python and writing the result — STOP. The model must flex when the user changes an assumption.
**Verify Step-by-Step With the User (DO NOT build end-to-end):**
- After data retrieval → show the user the raw inputs block (revenue, margins, shares, net debt) and confirm before projecting
- After revenue projections → show the projected top line and growth rates, confirm before building margin build
- After FCF build → show the full FCF schedule, confirm logic before computing WACC
- After WACC → show the calculation and inputs, confirm before discounting
- After terminal value + PV → show the equity bridge (EV → equity value → per share), confirm before sensitivity tables
- Catch errors at each stage — a wrong margin assumption discovered after sensitivity tables are built means rebuilding everything downstream
**Sensitivity Tables:**
- **Use an ODD number of rows and columns** (standard: 5×5, sometimes 7×7) — this guarantees a true center cell
- **Center cell = base case.** Build the axis values so the middle row header and middle column header exactly equal the model's actual assumptions (e.g., if base WACC = 9.0%, the middle row is 9.0%; if terminal g = 3.0%, the middle column is 3.0%). The center cell's output must therefore equal the model's actual implied share price — this is the sanity check that the table is built correctly.
- **Highlight the center cell** with the medium-blue fill (`#BDD7EE`) + bold font so it's immediately visible which cell is the base case.
- Populate ALL cells (typically 3 tables × 25 cells = 75) with full DCF recalculation formulas
- Use openpyxl loops (or Office JS loops) to write formulas programmatically
- NO placeholder text, NO linear approximations, NO manual steps required
- Each cell must recalculate full DCF for that assumption combination
**Cell Comments:**
- Add cell comments AS each hardcoded value is created
- Format: "Source: [System/Document], [Date], [Reference], [URL if applicable]"
- Every blue input must have a comment before moving to next section
- Do not defer to end or write "TODO: add source"
**Model Layout Planning:**
- Define ALL section row positions BEFORE writing any formulas
- Write ALL headers and labels first
- Write ALL section dividers and blank rows second
- THEN write formulas using the locked row positions
- Test formulas immediately after creation
**Formula Recalculation:**
- Run `python recalc.py model.xlsx 30` before delivery
- Fix ALL errors until status is "success"
- Zero formula errors required (#REF!, #DIV/0!, #VALUE!, etc.)
**Scenario Blocks:**
- Create separate blocks for Bear/Base/Bull cases
- Show assumptions horizontally across projection years within each block
- Use IF formulas: `=IF($B$6=1,[Bear cell],IF($B$6=2,[Base cell],[Bull cell]))`
- Verify formulas reference correct scenario block cells
## DCF Process Workflow
### Step 1: Data Retrieval and Validation
Fetch data from MCP servers, user provided data, and the web.
**Data Sources Priority:**
1. **MCP Servers** (if configured) - Structured financial data from providers like Daloopa
2. **User-Provided Data** - Historical financials from their research
3. **Web Search/Fetch** - Current prices, beta, debt and cash when needed
**Validation Checklist:**
- Verify net debt vs net cash (critical for valuation)
- Confirm diluted shares outstanding (check for recent buybacks/issuances)
- Validate historical margins are consistent with business model
- Cross-check revenue growth rates with industry benchmarks
- Verify tax rate is reasonable (typically 21-28%)
### Step 2: Historical Analysis (3-5 years)
Analyze and document:
- **Revenue growth trends**: Calculate CAGR, identify drivers
- **Margin progression**: Track gross margin, EBIT margin, FCF margin
- **Capital intensity**: D&A and CapEx as % of revenue
- **Working capital efficiency**: NWC changes as % of revenue growth
- **Return metrics**: ROIC, ROE trends
Create summary tables showing:
```
Historical Metrics (LTM):
Revenue: $X million
Revenue growth: X% CAGR
Gross margin: X%
EBIT margin: X%
D&A % of revenue: X%
CapEx % of revenue: X%
FCF margin: X%
```
### Step 3: Build Revenue Projections
**Methodology:**
1. Start with latest actual revenue (LTM or most recent fiscal year)
2. Apply growth rates for each projection year
3. Show both dollar amounts AND calculated growth %
**Growth Rate Framework:**
- Year 1-2: Higher growth reflecting near-term visibility
- Year 3-4: Gradual moderation toward industry average
- Year 5+: Approaching terminal growth rate
**Formula structure:**
- Revenue(Year N) = Revenue(Year N-1) × (1 + Growth Rate)
- Growth %(Year N) = Revenue(Year N) / Revenue(Year N-1) - 1
**Three-scenario approach:**
```
Bear Case: Conservative growth (e.g., 8-12%)
Base Case: Most likely scenario (e.g., 12-16%)
Bull Case: Optimistic growth (e.g., 16-20%)
```
### Step 4: Operating Expense Modeling
**Fixed/Variable Cost Analysis:**
Operating expenses should model realistic operating leverage:
- **Sales & Marketing**: Typically 15-40% of revenue depending on business model
- **Research & Development**: Typically 10-30% for technology companies
- **General & Administrative**: Typically 8-15% of revenue, shows leverage as company scales
**Key principles:**
- ALL percentages based on REVENUE, not gross profit
- Model operating leverage: % should decline as revenue scales
- Maintain separate line items for S&M, R&D, G&A
- Calculate EBIT = Gross Profit - Total OpEx
**Margin expansion framework:**
```
Current State → Target State (Year 5)
Gross Margin: X% → Y% (justify based on scale, efficiency)
EBIT Margin: X% → Y% (result of revenue growth + opex leverage)
```
### Step 5: Free Cash Flow Calculation
**Build FCF in proper sequence:**
```
EBIT
(-) Taxes (EBIT × Tax Rate)
= NOPAT (Net Operating Profit After Tax)
(+) D&A (non-cash expense, % of revenue)
(-) CapEx (% of revenue, typically 4-8%)
(-) Δ NWC (change in working capital)
= Unlevered Free Cash Flow
```
**Working Capital Modeling:**
- Calculate as % of revenue change (delta revenue)
- Typical range: -2% to +2% of revenue change
- Negative number = source of cash (working capital release)
- Positive number = use of cash (working capital build)
**Maintenance vs Growth CapEx:**
- Maintenance CapEx: Sustains current operations (~2-3% revenue)
- Growth CapEx: Supports expansion (additional 2-5% revenue)
- Total CapEx should align with company's growth strategy
### Step 6: Cost of Capital (WACC) Research
**CAPM Methodology for Cost of Equity:**
```
Cost of Equity = Risk-Free Rate + Beta × Equity Risk Premium
Where:
- Risk-Free Rate = Current 10-Year Treasury Yield
- Beta = 5-year monthly stock beta vs market index
- Equity Risk Premium = 5.0-6.0% (market standard)
```
**Cost of Debt Calculation:**
```
After-Tax Cost of Debt = Pre-Tax Cost of Debt × (1 - Tax Rate)
Determine Pre-Tax Cost of Debt from:
- Credit rating (if available)
- Current yield on company bonds
- Interest expense / Total Debt from financials
```
**Capital Structure Weights:**
```
Market Value Equity = Current Stock Price × Shares Outstanding
Net Debt = Total Debt - Cash & Equivalents
Enterprise Value = Market Cap + Net Debt
Equity Weight = Market Cap / Enterprise Value
Debt Weight = Net Debt / Enterprise Value
WACC = (Cost of Equity × Equity Weight) + (After-Tax Cost of Debt × Debt Weight)
```
**Special Cases:**
- **Net Cash Position**: If Cash > Debt, Net Debt is NEGATIVE
- Debt Weight may be negative
- WACC calculation adjusts accordingly
- **No Debt**: WACC = Cost of Equity
**Typical WACC Ranges:**
- Large Cap, Stable: 7-9%
- Growth Companies: 9-12%
- High Growth/Risk: 12-15%
### Step 7: Discount Rate Application (5-10 Year Forecast)
**Mid-Year Convention:**
- Cash flows assumed to occur mid-year
- Discount Period: 0.5, 1.5, 2.5, 3.5, 4.5, etc.
- Discount Factor = 1 / (1 + WACC)^Period
**Present Value Calculation:**
```
For each projection year:
PV of FCF = Unlevered FCF × Discount Factor
Example (Year 1):
FCF = $1,000
WACC = 10%
Period = 0.5
Discount Factor = 1 / (1.10)^0.5 = 0.9535
PV = $1,000 × 0.9535 = $954
```
**Projection Period Selection:**
- **5 years**: Standard for most analyses
- **7-10 years**: High growth companies with longer runway
- **3 years**: Mature, stable businesses
### Step 8: Terminal Value Calculation
**Perpetuity Growth Method (Preferred):**
```
Terminal FCF = Final Year FCF × (1 + Terminal Growth Rate)
Terminal Value = Terminal FCF / (WACC - Terminal Growth Rate)
Critical Constraint: Terminal Growth < WACC (otherwise infinite value)
```
**Terminal Growth Rate Selection:**
- Conservative: 2.0-2.5% (GDP growth rate)
- Moderate: 2.5-3.5%
- Aggressive: 3.5-5.0% (only for market leaders)
**Do not exceed**: Risk-free rate or long-term GDP growth
**Exit Multiple Method (Alternative):**
```
Terminal Value = Final Year EBITDA × Exit Multiple
Where Exit Multiple comes from:
- Industry comparable trading multiples
- Precedent transaction multiples
- Typical range: 8-15x EBITDA
```
**Present Value of Terminal Value:**
```
PV of Terminal Value = Terminal Value / (1 + WACC)^Final Period
Where Final Period accounts for timing:
5-year model with mid-year convention: Period = 4.5
```
**Terminal Value Sanity Check:**
- Should represent 50-70% of Enterprise Value
- If >75%, model may be over-reliant on terminal assumptions
- If <40%, check if terminal assumptions are too conservative
### Step 9: Enterprise to Equity Value Bridge
**Valuation Summary Structure:**
```
(+) Sum of PV of Projected FCFs = $X million
(+) PV of Terminal Value = $Y million
= Enterprise Value = $Z million
(-) Net Debt [or + Net Cash if negative] = $A million
= Equity Value = $B million
÷ Diluted Shares Outstanding = C million shares
= Implied Price per Share = $XX.XX
Current Stock Price = $YY.YY
Implied Return = (Implied Price / Current Price) - 1 = XX%
```
**Critical Adjustments:**
- **Net Debt = Total Debt - Cash & Equivalents**
- If positive: Subtract from EV (reduces equity value)
- If negative (Net Cash): Add to EV (increases equity value)
- **Use Diluted Shares**: Includes options, RSUs, convertible securities
- **Other adjustments** (if applicable):
- Minority interests
- Pension liabilities
- Operating lease obligations
**Valuation Output Format:**
```csv
Valuation Component,Amount ($M)
PV Explicit FCFs,X.X
PV Terminal Value,Y.Y
Enterprise Value,Z.Z
(-) Net Debt,A.A
Equity Value,B.B
,,
Shares Outstanding (M),C.C
Implied Price per Share,$XX.XX
Current Share Price,$YY.YY
Implied Upside/(Downside),+XX%
```
### Step 10: Sensitivity Analysis
Build **three sensitivity tables** at the bottom of the DCF sheet showing how valuation changes with different assumptions:
1. **WACC vs Terminal Growth** - Shows enterprise value sensitivity to discount rate and perpetuity growth
2. **Revenue Growth vs EBIT Margin** - Shows impact of top-line growth and operating leverage
3. **Beta vs Risk-Free Rate** - Shows sensitivity to cost of equity components
**Implementation**: These are simple 2D grids (NOT Excel's "Data Table" feature) with formulas in each cell. Each cell must contain a full DCF recalculation for that specific assumption combination. See Critical Constraints section for detailed requirements on populating all 75 cells programmatically using openpyxl.
<correct_patterns>
This section contains all the CORRECT patterns to follow when building DCF models.
### Scenario Block Selection Pattern - Follow This Approach
**Assumptions are organized in separate blocks for each scenario:**
**CRITICAL STRUCTURE - Three rows per section header:**
```csv
BEAR CASE ASSUMPTIONS (section header, merge cells across)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),12%,10%,9%,8%,7%
EBIT Margin (%),45%,44%,43%,42%,41%
BASE CASE ASSUMPTIONS (section header, merge cells across)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),16%,14%,12%,10%,9%
EBIT Margin (%),48%,49%,50%,51%,52%
BULL CASE ASSUMPTIONS (section header, merge cells across)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),20%,18%,15%,13%,11%
EBIT Margin (%),50%,51%,52%,53%,54%
```
**Each scenario block MUST have a column header row** showing the projection years (FY2025E, FY2026E, etc.) immediately below the section title. Without this, users cannot tell which assumption value corresponds to which year.
**How to reference assumptions - Create a consolidation column:**
1. Case selector cell (e.g., B6) contains 1=Bear, 2=Base, or 3=Bull
2. Create a consolidation column with INDEX or OFFSET formulas to pull from the correct scenario block
3. Projection formulas reference the consolidation column (clean cell references)
4. Each scenario block contains full set of DCF assumptions across projection years
**Recommended consolidation column pattern (using INDEX):**
`=INDEX(B10:D10, 1, $B$6)`
**NOT this - scattered IF statements throughout:**
`=IF($B$6=1,[Bear block cell],IF($B$6=2,[Base block cell],[Bull block cell]))`
The consolidation column approach centralizes logic and makes the model easier to audit.
### Correct Revenue Projection Pattern
**Create a consolidation column with INDEX formulas, then reference it in projections:**
**Step 1 - Consolidation column for FY1 growth:**
`=INDEX([Bear FY1 growth]:[Bull FY1 growth], 1, $B$6)`
**Step 2 - Revenue projection references the consolidation column:**
`Revenue Year 1: =D29*(1+$E$10)`
Where:
- D29 = Prior year revenue
- $E$10 = Consolidation column cell for FY1 growth (contains INDEX formula)
- $B$6 = Case selector (1=Bear, 2=Base, 3=Bull)
**This approach is cleaner than embedding IF statements in every projection formula** and makes it much easier to audit which scenario assumptions are being used.
### Correct FCF Formula Pattern
**Use consolidation columns with INDEX formulas, then reference them in FCF calculations:**
**Consolidation column approach:**
```csv
Item,Formula,Reference
D&A,=E29*$E$21,$E$21 = consolidation column for D&A %
CapEx,=E29*$E$22,$E$22 = consolidation column for CapEx %
Δ NWC,=(E29-D29)*$E$23,$E$23 = consolidation column for NWC %
Unlevered FCF,=E57+E58-E60-E62,E57=NOPAT E58=D&A E60=CapEx E62=Δ NWC
```
**Each consolidation column cell contains an INDEX formula** that pulls from the appropriate scenario block based on case selector. This keeps projection formulas clean and auditable.
Before writing formulas, confirm scenario block row locations and set up consolidation columns.
### Correct Cell Comment Format
**Every hardcoded value needs this format:**
"Source: [System/Document], [Date], [Reference], [URL if applicable]"
**Examples:**
```csv
Item,Source Comment
Stock price,Source: Market data script 2025-10-12 Close price
Shares outstanding,Source: 10-K FY2024 Page 45 Note 12
Historical revenue,Source: 10-K FY2024 Page 32 Consolidated Statements
Beta,Source: Market data script 2025-10-12 5-year monthly beta
Consensus estimates,Source: Management guidance Q3 2024 earnings call
```
### Correct Assumption Table Structure
**CRITICAL: Each scenario block requires THREE structural elements:**
1. **Section header row** (merged cells): e.g., "BEAR CASE ASSUMPTIONS"
2. **Column header row** showing years - THIS IS REQUIRED, DO NOT SKIP
3. **Data rows** with assumption values
**Structure:**
```csv
BEAR CASE ASSUMPTIONS (section header - merge across columns A:G)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),X%,X%,X%,X%,X%
EBIT Margin (%),X%,X%,X%,X%,X%
Terminal Growth,X%,,,,
WACC,X%,,,,
BASE CASE ASSUMPTIONS (section header - merge across columns A:G)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),X%,X%,X%,X%,X%
EBIT Margin (%),X%,X%,X%,X%,X%
Terminal Growth,X%,,,,
WACC,X%,,,,
BULL CASE ASSUMPTIONS (section header - merge across columns A:G)
Assumption,FY1,FY2,FY3,FY4,FY5
Revenue Growth (%),X%,X%,X%,X%,X%
EBIT Margin (%),X%,X%,X%,X%,X%
Terminal Growth,X%,,,,
WACC,X%,,,,
```
**WITHOUT the column header row showing projection years (FY2025E, FY2026E, etc.), users cannot tell which assumption value corresponds to which year. This row is MANDATORY.**
**Then create a consolidation column** (typically the next column to the right) that uses INDEX formulas to pull from the selected scenario block based on the case selector. This consolidation column is what your projection formulas reference.
### Correct Row Planning Process
**1. Write ALL headers and labels FIRST:**
```csv
Row,Content
1,[Company Name] DCF Model
2,Ticker | Date | Year End
4,Case Selector
7,KEY ASSUMPTIONS
26,Assumption headers
27-31,Growth assumptions
...,...
```
**2. Write ALL section dividers and blank rows**
**3. THEN write formulas using the locked row positions**
**4. Test formulas immediately after creation**
**Think of it like construction:**
- Good: Pour foundation, then build walls (stable structure)
- Bad: Build walls, then pour foundation (walls collapse)
**Excel version:**
- Good: Add headers, then write formulas (formulas stable)
- Bad: Write formulas, then add headers (formulas break)
### Correct Sensitivity Table Implementation
**IMPORTANT**: These are NOT Excel's "Data Table" feature. These are simple grids where you write regular formulas using openpyxl. Yes, this means ~75 formulas total (3 tables × 25 cells each), but this is straightforward and required.
**Programmatic Population with Formulas:**
Each sensitivity table must be fully populated with formulas that recalculate the implied share price for each combination of assumptions. **Do not use Excel's Data Table feature** (it requires manual intervention and cannot be automated via openpyxl).
**Implementation approach - CONCRETE EXAMPLE:**
**Table Structure — 5×5 grid (ODD dimensions, base case centered):**
If the model's base WACC = 9.0% and base terminal growth = 3.0%, build the axes symmetrically around those values:
```csv
WACC vs Terminal Growth, 2.0%, 2.5%, 3.0%, 3.5%, 4.0%
8.0%, [fml], [fml], [fml], [fml], [fml]
8.5%, [fml], [fml], [fml], [fml], [fml]
9.0%, [fml], [fml], [★ ], [fml], [fml] ← middle row = base WACC
9.5%, [fml], [fml], [fml], [fml], [fml]
10.0%, [fml], [fml], [fml], [fml], [fml]
↑
middle col = base terminal g
```
**★ = the center cell.** Its formula output MUST equal the model's actual implied share price (from the valuation summary). Apply the medium-blue fill (`#BDD7EE`) and bold font to this cell so the base case is visually anchored.
**Rule for axis values:** `axis_values = [base - 2*step, base - step, base, base + step, base + 2*step]` — symmetric around the base, odd count guarantees a center.
**Formula Pattern - Cell B88 (WACC=8.0%, Terminal Growth=2.0%):**
The formula in B88 should recalculate the implied price using:
- WACC from row header: `$A88` (8.0%)
- Terminal Growth from column header: `B$87` (2.0%)
**Recommended approach:** Reference the main DCF calculation but substitute these values.
**Example formula structure:**
`=([SUM of PV FCFs using $A88 as discount rate] + [Terminal Value using B$87 as growth rate and $A88 as WACC] - [Net Debt]) / [Shares]`
**CRITICAL - Write a formula for EVERY cell in the 5x5 grid (25 cells per table, 75 cells total).** Use openpyxl to write these formulas programmatically in a loop. Do NOT skip this step or leave placeholder text.
**Python implementation pattern:**
```python
# Pseudocode for populating sensitivity table
for row_idx, wacc_value in enumerate(wacc_range):
for col_idx, term_growth_value in enumerate(term_growth_range):
# Build formula that uses wacc_value and term_growth_value
formula = f"=<DCF recalc using {wacc_value} and {term_growth_value}>"
ws.cell(row=start_row+row_idx, column=start_col+col_idx).value = formula
```
**The sensitivity tables must work immediately when the model is opened, with no manual steps required from the user.**
</correct_patterns>
<common_mistakes>
This section contains all the WRONG patterns to avoid when building DCF models.
### WRONG: Simplified Sensitivity Table Approximations or Placeholder Text
**Don't use linear approximations:**
```
// WRONG - Linear approximation
B97: =B88*(1+(0.096-0.116)) // Assumes linear relationship
// WRONG - Division shortcut
B105: =B88/(1+(E48-0.07)) // Doesn't recalculate full DCF
```
**Don't leave placeholder text:**
```
// WRONG - Placeholder note
"Note: Use Excel Data Table feature (Data → What-If Analysis → Data Table) to populate sensitivity tables."
// WRONG - Empty cells
[leaving cells blank because "this is complex"]
```
**Don't confuse terminology:**
- ❌ "Sensitivity tables need Excel's Data Table feature" (NO - that's a specific Excel tool we can't use)
- ✅ "Sensitivity tables are simple grids with formulas in each cell" (YES - this is what we build)
**Why these shortcuts are wrong:**
- Linear approximation formulas don't actually recalculate the DCF - they just apply simple math adjustments
- The relationships are not linear, so the results will be inaccurate
- Placeholder text requires manual user intervention
- Model is not immediately usable when delivered
- Not professional or client-ready
- Empty cells = incomplete deliverable
**Common rationalization to REJECT:**
"Writing 75+ formulas feels complex, so I'll leave a note for the user to complete it manually."
**Reality:** Writing 75 formulas is straightforward when you use a loop in Python with openpyxl. Each formula follows the same pattern - just substitute the row/column values. This is a required part of the deliverable.
**Instead:** Populate every sensitivity cell with formulas that recalculate the full DCF for that specific combination of assumptions
### WRONG: Missing Cell Comments
**Don't do this:**
- Create all hardcoded inputs without comments
- Think "I'll add them later"
- Write "TODO: add source"
- Leave blue inputs without documentation
**Why it's wrong:**
- Can't verify where data came from
- Fails xlsx skill requirements
- Not audit-ready
- Wastes time fixing later
**Instead:** Add cell comment AS EACH hardcoded value is created
### WRONG: Formula Row References Off
**Symptom:**
The FCF section references wrong assumption rows:
`D&A: =E29*$E$34 // Should be $E$21, but referencing wrong row`
`CapEx: =E29*$E$41 // Should be $E$22, but row shifted`
**Why this happens:**
1. Formulas written first
2. Then headers inserted
3. All row references shifted
4. Now formulas point to wrong cells → #REF! errors
**Instead:** Lock row layout FIRST, then write formulas
### WRONG: Single Row for Each Assumption Across Scenarios
**Don't structure assumptions like this:**
```csv
Assumption,Bear,Base,Bull
Revenue Growth FY1,10%,13%,16%
Revenue Growth FY2,9%,12%,15%
```
This vertical layout makes it hard to see the progression across years within each scenario.
**Why it's wrong:**
- Makes it difficult to see assumptions evolving across years within each scenario
- Harder to compare scenario assumptions across full projection period
- Less intuitive for reviewing scenario logic
**Instead:**
- Create separate blocks for each scenario (Bear, Base, Bull)
- Within each block, show assumptions horizontally across projection years
- This makes each scenario's assumptions easier to review as a cohesive set
### WRONG: No Borders
**Don't deliver a model without borders:**
- No section delineation
- All cells blend together
- Hard to read and unprofessional
**Why it's wrong:**
- Not client-ready
- Difficult to navigate
- Looks amateur
**Instead:** Add borders around all major sections
### WRONG: Wrong Font Colors or No Font Color Distinction
**Don't do this:**
- All text is black
- Only use fill colors (no font color changes)
- Mix up which cells are blue vs black
**Why it's wrong:**
- Can't distinguish inputs from formulas
- Auditing becomes impossible
- Violates xlsx skill requirements
**Instead:** Blue text for ALL hardcoded inputs, black text for ALL formulas, green for sheet links
### WRONG: Operating Expenses Based on Gross Profit
**Don't do this:**
`S&M: =E33*0.15 // E33 = Gross Profit (WRONG)`
**Why it's wrong:**
- Operating expenses scale with revenue, not gross profit
- Produces unrealistic margin progression
- Not how businesses actually operate
**Instead:**
`S&M: =E29*0.15 // E29 = Revenue (CORRECT)`
### TOP 5 ERRORS SUMMARY
1. **Formula row references off** → Define ALL row positions BEFORE writing formulas
2. **Missing cell comments** → Add comments AS cells are created, not at end
3. **Simplified sensitivity tables** → Populate all cells with full DCF recalc formulas, not approximations
4. **Scenario block references wrong** → Ensure IF formulas pull from correct Bear/Base/Bull blocks
5. **No borders** → Add professional section borders for client-ready appearance
In addition, be aware of these errors:
### WACC Calculation Errors
- Mixing book and market values in capital structure
- Using equity beta instead of asset/unlevered beta incorrectly
- Wrong tax rate application to cost of debt
- Incorrect risk-free rate (must use current 10Y Treasury)
- Failure to adjust for net debt vs net cash position
### Growth Assumption Flaws
- Terminal growth > WACC (creates infinite value)
- Projection growth rates inconsistent with historical performance
- Ignoring industry growth constraints
- Revenue growth not aligned with unit economics
- Margin expansion without operational justification
### Terminal Value Mistakes
- Using wrong growth method (perpetuity vs exit multiple)
- Terminal value >80% of enterprise value (suggests over-reliance)
- Inconsistent terminal margins with steady state assumptions
- Wrong discount period for terminal value
### Cash Flow Projection Errors
- Operating expenses based on gross profit instead of revenue
- D&A/CapEx percentages misaligned with business model
- Working capital changes not properly calculated
- Tax rate inconsistency between years
- NOPAT calculation errors
**These errors are the most common. Re-read this section before starting any DCF build.**
</common_mistakes>
## Excel File Creation
**This skill uses the `xlsx` skill for all spreadsheet operations.** The xlsx skill provides:
- Standardized formula construction rules
- Number formatting conventions
- Automated formula recalculation via `recalc.py` script
- Comprehensive error checking and validation
All Excel files created by this skill must follow xlsx skill requirements, including zero formula errors and proper recalculation.
## Quality Rubric
Every DCF model must maximize for:
1. **Realistic revenue and margin assumptions** based on historical performance
2. **Appropriate cost of capital calculation** with proper CAPM methodology
3. **Comprehensive sensitivity analysis** showing valuation ranges
4. **Clear terminal value calculation** with supporting rationale
5. **Professional model structure** enabling scenario analysis
6. **Transparent documentation** of all key assumptions
## Input Requirements
### Minimum Required Inputs
1. **Company identifier**: Ticker symbol or company name
2. **Growth assumptions**: Revenue growth rates for projection period (or "use consensus")
3. **Optional parameters**:
- Projection period (default: 5 years)
- Scenario cases (Bear/Base/Bull growth and margin assumptions)
- Terminal growth rate (default: 2.5-3.0%)
- Specific WACC inputs if not using CAPM
## Excel Model Structure
### Sheet Architecture
Create **two sheets**:
1. **DCF** - Main valuation model with sensitivity analysis at bottom
2. **WACC** - Cost of capital calculation
**CRITICAL**: Sensitivity tables go at the BOTTOM of the DCF sheet (not on a separate sheet). This keeps all valuation outputs together.
### Formula Recalculation (MANDATORY)
After creating or modifying the Excel model, **recalculate all formulas** using the recalc.py script from the xlsx skill:
```bash
python recalc.py [path_to_excel_file] [timeout_seconds]
```
Example:
```bash
python recalc.py AAPL_DCF_Model_2025-10-12.xlsx 30
```
The script will:
- Recalculate all formulas in all sheets using LibreOffice
- Scan ALL cells for Excel errors (#REF!, #DIV/0!, #VALUE!, #NAME?, #NULL!, #NUM!, #N/A)
- Return detailed JSON with error locations and counts
**Expected output format:**
```json
{
"status": "success", // or "errors_found"
"total_errors": 0, // Total error count
"total_formulas": 42, // Number of formulas in file
"error_summary": {} // Only present if errors found
}
```
**If errors are found**, the output will include details:
```json
{
"status": "errors_found",
"total_errors": 2,
"total_formulas": 42,
"error_summary": {
"#REF!": {
"count": 2,
"locations": ["DCF!B25", "DCF!C25"]
}
}
}
```
**Fix all errors** and re-run recalc.py until status is "success" before delivering the model.
### Formatting Standards
**IMPORTANT**: Follow the xlsx skill for formula construction rules and number formatting conventions. The DCF skill adds specific visual presentation standards.
**Color Scheme - Two Layers**:
**Layer 1: Font Colors (MANDATORY from xlsx skill)**
- **Blue text (RGB: 0,0,255)**: ALL hardcoded inputs (stock price, shares, historical data, assumptions)
- **Black text (RGB: 0,0,0)**: ALL formulas and calculations
- **Green text (RGB: 0,128,0)**: Links to other sheets (WACC sheet references)
**Layer 2: Fill Colors — Professional Blue/Grey Palette (Default unless user specifies otherwise)**
- **Keep it minimal** — use only blues and greys for fills. Do NOT introduce greens, yellows, oranges, or multiple accent colors. A model with too many colors looks amateurish.
- **Default fill palette:**
- **Section headers**: Dark blue (RGB: 31,78,121 / `#1F4E79`) background with white bold text
- **Sub-headers/column headers**: Light blue (RGB: 217,225,242 / `#D9E1F2`) background with black bold text
- **Input cells**: Light grey (RGB: 242,242,242 / `#F2F2F2`) background with blue font — or just white with blue font if you want maximum minimalism
- **Calculated cells**: White background with black font
- **Output/summary rows** (per-share value, EV, etc.): Medium blue (RGB: 189,215,238 / `#BDD7EE`) background with black bold font
- **That's it — 3 blues + 1 grey + white.** Resist the urge to add more.
- User-provided templates or explicit color preferences ALWAYS override these defaults.
**How the layers work together:**
- Input cell: Blue font + light grey fill = "Hardcoded input"
- Formula cell: Black font + white background = "Calculated value"
- Sheet link: Green font + white background = "Reference from another sheet"
- Key output: Black bold font + medium blue fill = "This is the answer"
**Font color tells you WHAT it is (input/formula/link). Fill color tells you WHERE you are (header/data/output).**
### Border Standards (REQUIRED for Professional Appearance)
**Thick borders** (1.5pt) around major sections:
- KEY INPUTS section
- PROJECTION ASSUMPTIONS section
- 5-YEAR CASH FLOW PROJECTION section
- TERMINAL VALUE section
- VALUATION SUMMARY section
- Each SENSITIVITY ANALYSIS table
**Medium borders** (1pt) between sub-sections:
- Company Details vs Historical Performance
- Growth Assumptions vs EBIT Margin vs FCF Parameters
**Thin borders** (0.5pt) around data tables:
- Scenario assumption tables (Bear | Base | Bull | Selected)
- Historical vs projected financials matrix
**No borders:** Individual cells within tables (keep clean, scannable)
**Borders are mandatory** - models without professional borders are not client-ready.
**Number Formats** (follows xlsx skill standards):
- **Years**: Format as text strings (e.g., "2024" not "2,024")
- **Percentages**: `0.0%` (one decimal place)
- **Currency**: `$#,##0` for millions; `$#,##0.00` for per-share - ALWAYS specify units in headers ("Revenue ($mm)")
- **Zeros**: Use number formatting to make all zeros "-" (e.g., `$#,##0;($#,##0);-`)
- **Large numbers**: `#,##0` with thousands separator
- **Negative numbers**: `(#,##0)` in parentheses (NOT minus sign)
**Cell Comments (MANDATORY for all hardcoded inputs)**:
Per the xlsx skill, ALL hardcoded values must have cell comments documenting the source. Format: "Source: [System/Document], [Date], [Reference], [URL if applicable]"
**CRITICAL**: Add comments AS CELLS ARE CREATED. Do not defer to the end.
### DCF Sheet Detailed Structure
**Section 1: Header**
```csv
Row,Content
1,[Company Name] DCF Model
2,Ticker: [XXX] | Date: [Date] | Year End: [FYE]
3,Blank
4,Case Selector Cell (1=Bear 2=Base 3=Bull)
5,Case Name Display (formula: =IF([Selector]=1"Bear"IF([Selector]=2"Base""Bull")))
```
**Section 2: Market Data (NOT case dependent)**
```csv
Item,Value
Current Stock Price,$XX.XX
Shares Outstanding (M),XX.X
Market Cap ($M),[Formula]
Net Debt ($M),XXX [or Net Cash if negative]
```
**Section 3: DCF Scenario Assumptions**
Create separate assumption blocks for each scenario (Bear, Base, Bull) with DCF-specific assumptions (Revenue Growth %, EBIT Margin %, Tax Rate %, D&A % of Revenue, CapEx % of Revenue, NWC Change % of ΔRev, Terminal Growth Rate, WACC) laid out horizontally across projection years. Each block must include section header, column header row showing the projection years (FY1, FY2, etc.), and data rows. See `<correct_patterns>` section "Correct Assumption Table Structure" for the exact layout.
**Section 4: Historical & Projected Financials**
**Reference a consolidation column (e.g., "Selected Case") that pulls from scenario blocks**, not scattered IF formulas in every projection row.
```csv
Income Statement ($M),2020A,2021A,2022A,2023A,2024E,2025E,2026E
Revenue,XXX,XXX,XXX,XXX,[=E29*(1+$E$10)],[=F29*(1+$E$11)],[=G29*(1+$E$12)]
% growth,XX%,XX%,XX%,XX%,[=E29/D29-1],[=F29/E29-1],[=G29/F29-1]
,,,,,,
Gross Profit,XXX,XXX,XXX,XXX,[=E29*E33],[=F29*F33],[=G29*G33]
% margin,XX%,XX%,XX%,XX%,[=E33/E29],[=F33/F29],[=G33/G29]
,,,,,,
Operating Expenses:,,,,,,,
S&M,XXX,XXX,XXX,XXX,[=E29*0.15],[=F29*0.14],[=G29*0.13]
R&D,XXX,XXX,XXX,XXX,[=E29*0.12],[=F29*0.11],[=G29*0.10]
G&A,XXX,XXX,XXX,XXX,[=E29*0.08],[=F29*0.07],[=G29*0.07]
Total OpEx,XXX,XXX,XXX,XXX,[=E36+E37+E38],[=F36+F37+F38],[=G36+G37+G38]
,,,,,,
EBIT,XXX,XXX,XXX,XXX,[=E33-E39],[=F33-F39],[=G33-G39]
% margin,XX%,XX%,XX%,XX%,[=E41/E29],[=F41/F29],[=G41/G29]
,,,,,,
Taxes,(XX),(XX),(XX),(XX),[=E41*$E$24],[=F41*$E$24],[=G41*$E$24]
Tax rate,XX%,XX%,XX%,XX%,[=E43/E41],[=F43/F41],[=G43/G41]
,,,,,,
NOPAT,XXX,XXX,XXX,XXX,[=E41-E43],[=F41-F43],[=G41-G43]
```
**Key Formula Pattern**:
- Revenue growth: `=E29*(1+$E$10)` where $E$10 is consolidation column for Year 1 growth
- NOT: `=E29*(1+IF($B$6=1,$B$10,IF($B$6=2,$C$10,$D$10)))`
This approach is cleaner, easier to audit, and prevents formula errors by centralizing the scenario logic.
**Section 5: Free Cash Flow Build**
**CRITICAL**: Verify row references point to the CORRECT assumption rows. Test formulas immediately after creation.
```csv
Cash Flow ($M),2020A,2021A,2022A,2023A,2024E,2025E,2026E
NOPAT,XXX,XXX,XXX,XXX,[=E45],[=F45],[=G45]
(+) D&A,XXX,XXX,XXX,XXX,[=E29*$E$21],[=F29*$E$21],[=G29*$E$21]
% of Rev,XX%,XX%,XX%,XX%,[=E58/E29],[=F58/F29],[=G58/G29]
(-) CapEx,(XX),(XX),(XX),(XX),[=E29*$E$22],[=F29*$E$22],[=G29*$E$22]
% of Rev,XX%,XX%,XX%,XX%,[=E60/E29],[=F60/F29],[=G60/G29]
(-) Δ NWC,(XX),(XX),(XX),(XX),[=(E29-D29)*$E$23],[=(F29-E29)*$E$23],[=(G29-F29)*$E$23]
% of Δ Rev,XX%,XX%,XX%,XX%,[=E62/(E29-D29)],[=F62/(F29-E29)],[=G62/(G29-F29)]
,,,,,,
Unlevered FCF,XXX,XXX,XXX,XXX,[=E57+E58-E60-E62],[=F57+F58-F60-F62],[=G57+G58-G60-G62]
```
**Row reference examples** (based on layout planning):
- $E$21 = D&A % assumption (consolidation column, row 21)
- $E$22 = CapEx % assumption (consolidation column, row 22)
- $E$23 = NWC % assumption (consolidation column, row 23)
- E29 = Revenue for year (row 29)
- E45 = NOPAT for year (row 45)
**Before writing formulas**: Confirm these row numbers match the actual layout. Test one column, then copy across.
**Section 6: Discounting & Valuation**
```csv
DCF Valuation,2024E,2025E,2026E,2027E,2028E,Terminal
Unlevered FCF ($M),XXX,XXX,XXX,XXX,XXX,
Period,0.5,1.5,2.5,3.5,4.5,
Discount Factor,0.XX,0.XX,0.XX,0.XX,0.XX,
PV of FCF ($M),XXX,XXX,XXX,XXX,XXX,
,,,,,,
Terminal FCF ($M),,,,,,,XXX
Terminal Value ($M),,,,,,,XXX
PV Terminal Value ($M),,,,,,,XXX
,,,,,,
Valuation Summary ($M),,,,,,
Sum of PV FCFs,XXX,,,,,
PV Terminal Value,XXX,,,,,
Enterprise Value,XXX,,,,,
(-) Net Debt,(XX),,,,,
Equity Value,XXX,,,,,
,,,,,,
Shares Outstanding (M),XX.X,,,,,
IMPLIED PRICE PER SHARE,$XX.XX,,,,,
Current Stock Price,$XX.XX,,,,,
Implied Upside/(Downside),XX%,,,,,
```
### WACC Sheet Structure
```csv
COST OF EQUITY CALCULATION,,
Risk-Free Rate (10Y Treasury),X.XX%,[Yellow input]
Beta (5Y monthly),X.XX,[Yellow input]
Equity Risk Premium,X.XX%,[Yellow input]
Cost of Equity,X.XX%,[Calculated blue]
,,
COST OF DEBT CALCULATION,,
Credit Rating,AA-,[Yellow input]
Pre-Tax Cost of Debt,X.XX%,[Yellow input]
Tax Rate,XX.X%,[Link to DCF sheet]
After-Tax Cost of Debt,X.XX%,[Calculated blue]
,,
CAPITAL STRUCTURE,,
Current Stock Price,$XX.XX,[Link to DCF]
Shares Outstanding (M),XX.X,[Link to DCF]
Market Capitalization ($M),"X,XXX",[Calculated]
,,
Total Debt ($M),XXX,[Yellow input]
Cash & Equivalents ($M),XXX,[Yellow input]
Net Debt ($M),XXX,[Calculated]
,,
Enterprise Value ($M),"X,XXX",[Calculated]
,,
WACC CALCULATION,Weight,Cost,Contribution
Equity,XX.X%,X.X%,X.XX%
Debt,XX.X%,X.X%,X.XX%
,,
WEIGHTED AVERAGE COST OF CAPITAL,X.XX%,[Green output]
```
**Key WACC Formulas:**
```
Market Cap = Price × Shares
Net Debt = Total Debt - Cash
Enterprise Value = Market Cap + Net Debt
Equity Weight = Market Cap / EV
Debt Weight = Net Debt / EV
WACC = (Cost of Equity × Equity Weight) + (After-tax Cost of Debt × Debt Weight)
```
### Sensitivity Analysis (Bottom of DCF Sheet)
**TERMINOLOGY REMINDER**: "Sensitivity tables" = simple 2D grids with row headers, column headers, and formulas in each data cell. NOT Excel's "Data Table" feature (Data → What-If Analysis → Data Table). You will use openpyxl to write regular Excel formulas into each cell.
**Location**: Rows 87+ on DCF sheet (NOT a separate sheet)
**Three sensitivity tables, vertically stacked:**
1. **WACC vs Terminal Growth** (rows 87-100) - 5x5 grid = 25 cells with formulas
2. **Revenue Growth vs EBIT Margin** (rows 102-115) - 5x5 grid = 25 cells with formulas
3. **Beta vs Risk-Free Rate** (rows 117-130) - 5x5 grid = 25 cells with formulas
**Total formulas to write: 75** (this is required, not optional)
**CRITICAL**: All sensitivity table cells must be populated programmatically with formulas using openpyxl. DO NOT use linear approximation shortcuts. DO NOT leave placeholder text or notes about manual steps. DO NOT rationalize leaving cells empty because "it's complex" - use a Python loop to generate the formulas.
**Table Setup:**
1. Create table structure with row/column headers (the assumption values to test)
2. Populate EVERY data cell with a formula that:
- Uses the row header value (e.g., WACC = 9.0%)
- Uses the column header value (e.g., Terminal Growth = 3.0%)
- Recalculates the full DCF with those specific assumptions
- Returns the implied share price for that scenario
3. All cells must contain working formulas when delivered
4. Format cells with conditional formatting: Green scale for higher values, red scale for lower values
5. Bold the base case cell
6. Leave 1-2 blank rows between tables
**No manual intervention required** - the sensitivity tables must be fully functional when the user opens the file.
## Case Selector Implementation
**Three-Case Framework:**
### Bear Case
- Conservative revenue growth (low end of historical range)
- Margin compression or no expansion
- Higher WACC (risk premium increase)
- Lower terminal growth rate
- Higher CapEx assumptions
### Base Case
- Consensus or management guidance revenue growth
- Moderate margin expansion based on operating leverage
- Current market-implied WACC
- GDP-aligned terminal growth (2.5-3.0%)
- Standard CapEx assumptions
### Bull Case
- Optimistic revenue growth (high end of projections)
- Significant margin expansion
- Lower WACC (reduced risk premium)
- Higher terminal growth (3.5-5.0%)
- Reduced CapEx intensity
**Formula Implementation:**
**DO NOT use nested IF formulas scattered throughout.** Instead, create a consolidation column that uses INDEX or OFFSET formulas to pull from the appropriate scenario block.
**Recommended pattern (using INDEX):**
`=INDEX(B10:D10, 1, $B$6)` where `B10:D10` = Bear/Base/Bull values, `1` = row offset, `$B$6` = case selector cell (1, 2, or 3)
**Then reference the consolidation column** in all projections:
`Revenue Year 1: =D29*(1+$E$10)` where $E$10 is the consolidation column value for Year 1 growth.
This approach centralizes scenario logic, making the model easier to audit and maintain.
## Deliverables Structure
**File naming**: `[Ticker]_DCF_Model_[Date].xlsx`
**Two sheets**:
1. **DCF** - Complete model with Bear/Base/Bull cases + three sensitivity tables at bottom (WACC vs Terminal Growth, Revenue Growth vs EBIT Margin, Beta vs Risk-Free Rate)
2. **WACC** - Cost of capital calculation
**Key features**: Case selector (1/2/3), consolidation column with INDEX/OFFSET formulas, color-coded cells, cell comments on all inputs, professional borders
## Best Practices
### Model Construction
1. **Build incrementally**: Complete each section before moving to next
2. **Test as building**: Enter sample numbers to verify formulas
3. **Use consistent structure**: Similar calculations follow similar patterns
4. **Comment complex formulas**: Add notes for unusual calculations
5. **Build in checks**: Sum checks and balance checks where applicable
### Documentation
1. **Document all assumptions**: Explain reasoning behind key inputs
2. **Cite data sources**: Note where each data point came from
3. **Explain methodology**: Describe any non-standard approaches
4. **Flag uncertainties**: Highlight areas with limited visibility
### Quality Control
1. **Cross-check calculations**: Verify math in multiple ways
2. **Stress test assumptions**: Run sensitivity to ensure model is robust
3. **Peer review**: Have someone else check formulas
4. **Version control**: Save versions as work progresses
## Common Variations
### High-Growth Technology Companies
- Longer projection period (7-10 years)
- Higher initial growth rates (20-30%)
- Significant margin expansion over time
- Higher WACC (12-15%)
- Model unit economics (users, ARPU, etc.)
### Mature/Stable Companies
- Shorter projection period (3-5 years)
- Modest growth rates (GDP +1-3%)
- Stable margins
- Lower WACC (7-9%)
- Focus on cash generation and capital allocation
### Cyclical Companies
- Model through economic cycle
- Normalize margins at mid-cycle
- Consider trough and peak scenarios
- Adjust beta for cyclicality
### Multi-Segment Companies
- Separate DCFs for each business unit
- Different growth rates and margins by segment
- Sum-of-parts valuation
- Consider synergies
## Troubleshooting
**If you encounter errors or unreasonable results, read [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) for detailed debugging guidance.**
## Workflow Integration
### At Start of DCF Build
1. **Gather market data**:
- Check for available MCP servers for current market data
- Use web search/fetch for stock prices, beta, and other market metrics
- Request from user if specific data is needed
2. **Gather historical financials**:
- Check for available MCP servers (Daloopa, etc.)
- Request from user if not available via MCP
- Manual extraction from 10-Ks if necessary
3. **Begin model construction** using the DCF methodology detailed in this skill
### During Model Construction
1. **Build Excel model** using openpyxl with formulas (not hardcoded values)
2. **Follow xlsx skill conventions** for formula construction and formatting
3. **Apply fill colors only if requested** by user or if specific brand guidelines are provided
### Before Delivering Model (MANDATORY)
1. **Verify structure**:
- Scenario blocks for Bear/Base/Bull with assumptions across projection years
- Case selector functional with formulas referencing correct scenario blocks
- Sensitivity tables at bottom of DCF sheet (not separate sheet)
- Font colors: Blue inputs, black formulas, green sheet links
- Cell comments on ALL hardcoded inputs
- Professional borders around major sections
2. **Recalculate formulas**: Run `python recalc.py model.xlsx 30`
3. **Check output**:
- If `status` is `"success"` → Continue to step 4
- If `status` is `"errors_found"` → Check `error_summary` and read [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) for debugging guidance
4. **Fix errors and re-run recalc.py** until status is "success"
5. **Spot-check formulas**:
- Test one FCF formula - does it reference the correct assumption rows?
- Change case selector - does the consolidation column update properly?
- Verify revenue formulas reference consolidation column (not nested IF formulas)
6. **Deliver model**
### Available Data Sources
- **MCP servers**: If configured (Daloopa for historical financials)
- **Web search/fetch**: For current stock prices, beta, and market data
- **User-provided data**: Historical financials, consensus estimates
- **Manual extraction**: SEC EDGAR filings as fallback
## Final Output Checklist
Before delivering DCF model:
**Required:**
- Run `python recalc.py model.xlsx 30` until status is "success" (zero formula errors)
- Two sheets: DCF (with sensitivity at bottom), WACC
- Font colors: Blue=inputs, Black=formulas, Green=sheet links
- Cell comments on ALL hardcoded inputs
- Sensitivity tables fully populated with formulas
- Professional borders around major sections
**Validation:**
- OpEx based on revenue (not gross profit)
- Terminal value 50-70% of EV
- Terminal growth < WACC
- Tax rate 21-28%
- File naming: `[Ticker]_DCF_Model_[Date].xlsx`
Источник: anthropics/financial-services / model-builder / dcf-model ↗. Ссылка проверена 2026-10-10.
Тот же скилл есть в: anthropics/financial-services / pitch-agent / dcf-model; anthropics/financial-services / financial-analysis / dcf-model.