Excel Author

Создавайте проверяемые финансовые книги в headless-режиме через openpyxl.

Метаданные навыка

ИсточникОпциональный (устанавливается по запросу) — установите командой hermes skills install official/finance/excel-author
Путьoptional-skills/finance/excel-author
Версия1.0.0
АвторAnthropic (adapted by Nous Research)
ЛицензияApache-2.0
Платформыlinux, macos, windows
Тегиexcel, openpyxl, finance, spreadsheet, modeling
Связанные навыкиxlsx, pptx-author, dcf-model, comps-analysis, lbo-model, 3-statement-model

Справочник: полный SKILL.md

инфо

Ниже приведено полное определение навыка, которое Hermes Agent загружает при его активации. Именно этот текст агент видит как инструкцию в момент работы навыка.

excel-author

Создайте .xlsx-файл на диске с помощью openpyxl. Соблюдайте банковские соглашения, описанные ниже — модель должна поддаваться аудиту, оставаться гибкой при изменении допущений и читаться человеком, который её не строил.

Адаптировано из навыков xlsx-author и audit-xls Anthropic в репозитории anthropics/financial-services. Ветки MCP / Office-JS / Cowork убраны — навык рассчитан на headless Python.

Контракт на вывод

  • Пишите в ./out/<name>.xlsx. Папку ./out/ создайте, если она не существует.
  • В финальном сообщении верните относительный путь к файлу — чтобы следующие инструменты могли его подхватить.
  • Одна логическая модель — один файл. Не дописывайте в существующую книгу, если пользователь явно не попросил.

Установка

pip install "openpyxl>=3.0"

Базовые соглашения (обязательны)

Цвет ячеек: синий / чёрный / зелёный

  • Синий (Font(color="0000FF")) — захардкоженный ввод от человека: драйверы выручки, WACC, темп роста в терминальном периоде, рыночные данные.
  • Чёрный (по умолчанию) — формула. Любая производная ячейка содержит живую формулу Excel.
  • Зелёный (Font(color="006100")) — ссылка на другой лист или внешний файл.

Проверяющий сразу видит, что является допущением, а что — расчётом.

Формулы вместо захардкоженных значений

Каждая расчётная ячейка ОБЯЗАНА содержать строку-формулу — никаких чисел, вычисленных в Python и вставленных как значение.

# WRONG — silent bug waiting to happen
ws["D20"] = revenue_prior_year * (1 + growth)

# CORRECT — flexes when the user changes the assumption
ws["D20"] = "=D19*(1+$B$8)"

Захардкоженные числа допускаются только в следующих случаях:

  1. Исторические фактические данные (реальная выручка, отчётный EBITDA и т.д.)
  2. Драйверы допущений, которые пользователь должен менять (темпы роста, WACC, терминальный g)
  3. Текущие рыночные данные (цена акции, размер долга) — с комментарием к ячейке, фиксирующим источник и дату

Поймали себя на том, что вычисляете значение в Python и записываете результат — стоп.

Именованные диапазоны для межлистовых ссылок

Используйте именованные диапазоны для любой величины, на которую ссылаются с другого листа, из презентации или меморандума.

from openpyxl.workbook.defined_name import DefinedName
wb.defined_names["WACC"] = DefinedName("WACC", attr_text="Inputs!$C$8")
# then elsewhere:
calc["D30"] = "=D29/WACC"

Вкладка проверок баланса

Включите вкладку Checks, которая сводит всё воедино и показывает TRUE/FALSE:

  • Баланс сходится (активы = обязательства + капитал)
  • Денежный поток привязан к изменению кэша между периодами в балансе
  • Сумма частей сходится с консолидированными итогами
  • Нет посторонних захардкоженных значений внутри расчётных диапазонов

Пример:

checks = wb.create_sheet("Checks")
checks["A2"] = "BS balances"
checks["B2"] = "=IS!D20-IS!D21-IS!D22"
checks["C2"] = "=ABS(B2)<0.01"  # TRUE/FALSE

Комментарии к каждой захардкоженной ячейке

Добавляйте комментарий в момент создания ячейки, не потом.

from openpyxl.comments import Comment
ws["C2"] = 1_250_000_000
ws["C2"].font = Font(color="0000FF")
ws["C2"].comment = Comment("Source: 10-K FY2024, p.47, revenue line", "analyst")

Формат: Source: [System/Document], [Date], [Reference], [URL if applicable].

Не откладывайте указание источника. Никаких TODO: add source.

Каркас: типовая финансовая модель

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.comments import Comment
from openpyxl.utils import get_column_letter
from pathlib import Path

BLUE = Font(color="0000FF")
BLACK = Font(color="000000")
GREEN = Font(color="006100")
BOLD = Font(bold=True)
HEADER_FILL = PatternFill("solid", fgColor="1F4E79")
HEADER_FONT = Font(color="FFFFFF", bold=True)

wb = Workbook()

# --- Inputs tab ---
inp = wb.active
inp.title = "Inputs"
inp["A1"] = "MARKET DATA & KEY INPUTS"
inp["A1"].font = HEADER_FONT
inp["A1"].fill = HEADER_FILL
inp.merge_cells("A1:C1")

inp["B3"] = "Revenue FY2024"
inp["C3"] = 1_250_000_000
inp["C3"].font = BLUE
inp["C3"].comment = Comment("Source: 10-K FY2024 p.47", "model")

inp["B4"] = "Growth Rate"
inp["C4"] = 0.12
inp["C4"].font = BLUE

# --- Calc tab ---
calc = wb.create_sheet("DCF")
calc["B2"] = "Projected Revenue"
calc["C2"] = "=Inputs!C3*(1+Inputs!C4)"   # formula, black

# --- Checks tab ---
chk = wb.create_sheet("Checks")
chk["A2"] = "BS balances"
chk["B2"] = "=ABS(BS!D20-BS!D21-BS!D22)<0.01"

Path("./out").mkdir(exist_ok=True)
wb.save("./out/model.xlsx")

Заголовки секций с объединёнными ячейками

Особенность openpyxl: при слиянии значение задаётся на верхней левой ячейке, а стиль применяется ко всему диапазону отдельно.

ws["A7"] = "CASH FLOW PROJECTION"
ws["A7"].font = HEADER_FONT
ws.merge_cells("A7:H7")
for col in range(1, 9):  # A..H
    ws.cell(row=7, column=col).fill = HEADER_FILL

Таблицы чувствительности

Строятся циклами — никаких захардкоженных формул на каждую ячейку. Правила:

  • Нечётное количество строк/столбцов (5×5 или 7×7) — гарантирует истинную центральную ячейку.
  • Центральная ячейка = базовый сценарий. Заголовок центральной строки/столбца должен совпадать с реальным WACC и терминальным g модели — тогда центральный результат даёт базовую подразумеваемую цену акции. Это и есть проверка на адекватность.
  • Выделите центральную ячейку средне-синей заливкой ("BDD7EE") и жирным шрифтом.
  • Каждая ячейка — полная формула пересчёта, без приближений.
# 5x5 WACC (rows) x terminal growth (cols) sensitivity
wacc_axis = [0.08, 0.085, 0.09, 0.095, 0.10]        # center row = base 9.0%
term_axis = [0.02, 0.025, 0.03, 0.035, 0.04]        # center col = base 3.0%

start_row = 40
ws.cell(row=start_row, column=1).value = "Implied Share Price ($)"
ws.cell(row=start_row, column=1).font = BOLD

for j, g in enumerate(term_axis):
    ws.cell(row=start_row+1, column=2+j).value = g
    ws.cell(row=start_row+1, column=2+j).font = BLUE

for i, w in enumerate(wacc_axis):
    r = start_row + 2 + i
    ws.cell(row=r, column=1).value = w
    ws.cell(row=r, column=1).font = BLUE
    for j, g in enumerate(term_axis):
        c = 2 + j
        # Full DCF recalc formula (simplified for illustration).
        # In a real model this references the full projection block.
        ws.cell(row=r, column=c).value = (
            f"=SUMPRODUCT(FCF_range,1/(1+{w})^year_offset) + "
            f"FCF_terminal*(1+{g})/({w}-{g})/(1+{w})^terminal_year"
        )

# Highlight center cell (base case)
center = ws.cell(row=start_row+2+len(wacc_axis)//2,
                 column=2+len(term_axis)//2)
center.fill = PatternFill("solid", fgColor="BDD7EE")
center.font = BOLD

Пересчёт перед передачей

openpyxl записывает строки формул, но не вычисляет их. Excel пересчитает при открытии, однако downstream-потребители (скрипты автопроверки, CI) требуют готовых значений.

Перед передачей запустите LibreOffice или отдельный шаг пересчёта:

# LibreOffice headless recalc
libreoffice --headless --calc --convert-to xlsx ./out/model.xlsx --outdir ./out/

Либо воспользуйтесь вспомогательным Python-скриптом (см. scripts/recalc.py в этом навыке).

Планирование разметки модели

Прежде чем писать какую-либо формулу:

  1. Определите позиции строк ВСЕХ секций
  2. Запишите ВСЕ заголовки и метки
  3. Добавьте ВСЕ разделители секций и пустые строки
  4. ЗАТЕМ пишите формулы, используя зафиксированные позиции строк

Это предотвращает каскадное смещение ссылок, когда вставка строки заголовка после написанных формул сдвигает все нижние ссылки.

Пошаговая сверка с пользователем

Для крупных моделей (DCF, трёхотчётная, LBO) делайте паузы и показывайте промежуточные артефакты, не дожидаясь конца. Поймать неверное допущение по марже до того, как построены таблицы чувствительности, — экономит час работы.

Схема контрольных точек:

  • После блока Inputs → покажите исходные данные, подтвердите перед проекциями
  • После прогнозов выручки → подтвердите верхнюю строку и рост
  • После расчёта FCF → подтвердите полный график
  • После WACC → подтвердите допущения
  • После оценки → подтвердите equity bridge
  • ЗАТЕМ стройте таблицы чувствительности

Когда НЕ использовать этот навык

  • Пользователь работает в живой сессии Excel с доступным Office MCP — управляйте его активной книгой напрямую.
  • Нужен чистый экспорт таблицы без формул — csv или pandas.to_excel проще.
  • Дашборды и графики с насыщенной интерактивностью — используйте полноценный BI-инструмент.

Авторство

Соглашения (синий/чёрный/зелёный, формулы вместо захардкоженных значений, именованные диапазоны, правила таблиц чувствительности) адаптированы из плагинного набора Anthropic «Claude for Financial Services», лицензия Apache-2.0. Оригинал: https://github.com/anthropics/financial-services/tree/main/plugins/vertical-plugins/financial-analysis/skills/xlsx-author

перевод и редактура:

обновлено

⌕ ESC