재무 모델 — xlsx 를 DB 의 일급 entity 로
한 줄 정의
ic skill 의 ic/finance/{3fs_*,scenario_deltas,exit_matrix,irr_analysis} 산출물을 6-table typed model 로 승격. xlsx 가 source 가 아니라 DB 가 source, xlsx 는 ingest 입력 + export 출력. DSL formula + topo evaluator 가 cell 재계산 deterministic. fund_investment 가 cash flow + IRR carrier — 한 deal 의 여러 fund × 여러 round 별 IRR 독립 산출.
본 페이지는 index 의 L1 (relational compute substrate) 이다. 이 relational 값을 지배하는 판단 (가정·calibration·comp·base_rate) 은 그 위 L2 — artifact-first judgment layer (D-index-45) 가 typed fact 로 보존하며, citation
index_field(ref{deal,field}) 로 여기 relational field 에 링크된다. “왜 이 driver/exit_multiple/probability 가 이 값인가” 추적 =get_judgment_provenance. 3-layer 전체 = /services/index § 3-layer 모델.
왜 필요한가
ic skill 의 현재 흐름:
회사 IR pack
↓ vision_ingest
dataroom/*.{pdf,pptx,xlsx}
↓ /ic 19-agent orchestration (3-5시간)
ic/finance/3fs_base/v7.xlsx ← scenario 4종 × 3FS 모델 (8 sheet)
ic/finance/scenario_deltas/v7.yaml ← 4 scenario × ~15 driver
ic/finance/exit_matrix/v7.yaml ← scenario × timing × path leaf 트리
ic/finance/irr_analysis/v7.xlsx ← 확률가중 IRR 산출
ic/memo/v8.md ← IRR 23.4% 라는 한 줄 cite
↓ PDF render + Teams reply
산출물 휘발 — 다음 deal 도 grep 으로 재추출5 격차:
| 격차 | 현재 (xlsx + yaml + markdown) | 결과 |
|---|---|---|
| Cross-deal driver benchmark | portfolio 의 churn / gross_margin / IRR 시계열 grep 으로 못 풀음 | ”axec/axev 포폴 평균 gross margin?” 답 토큰 폭증 |
| Citation chain | IC memo “IRR 23.4%” 가 xlsx 어느 cell, 어느 driver 에서 왔는지 trace 불가 | LP audit 시 “한 숫자라도 잡히면” IRR 신뢰 무너짐 (ic skill citation_trace.py 본질) |
| Time-travel | Q2 IC 시점의 IRR vs 현재 IRR diff 안 됨 | 의사결정 archaeology 불가 |
| 펀드별 IRR 분리 | 1호 + 2호 동시 투자 시 각각 IRR 산출 수작업 | Iippo / Sentry 같은 multi-fund deal 의 정합성 안 잡힘 |
| Sanity check 휘발 | ic skill 의 4 check 가 매번 재실행. 누적 audit 없음 | 모순 반복 (Superman v4 “11,250백만원 (1,200억 × 18.75%)” 4-number 모순 같은 사고) |
→ DB 가 source 면 위 5 격차 모두 SQL aggregate / FK / trigger 로 자연 해결.
6-table SoT
financial_model (deal 별 1+, version)
│
├─ financial_driver (driver tree DAG — code, kind, formula DSL, dependencies[])
│ ↑ topological sort 로 평가 순서 결정
│
├─ financial_scenario (Upside/Base/Mgmt/Downside, probability, driver_changes)
│ ↑ ic skill 의 PR-J 4-scenario 정합
│
├─ financial_driver_value (model × driver × scenario × period_index → value)
│ ↑ scenario 가 baseline 위에 override 만 — driver_changes 의 DB 형태
│
├─ financial_output (model × scenario × output_code × period?)
│ ↑ irr / moic / npv / exit_val / runway / revenue_year_5 ...
│ ↑ inputs_hash 가 driver_value snapshot sha256 — reproducibility lock
│
└─ exit_matrix_leaf (scenario × timing × path)
↑ ic skill exit_matrix yaml 의 3-level tree 의 DB 형태
↑ probability × proceeds_krw + dead_leaf/concentration flag (check_exit_matrix.py 결과 캐시)Schema (SQL skeleton)
-- per-entity schema (axe_ia_001 / axe_ia_002 / ...)
CREATE TABLE financial_model (
id uuid PRIMARY KEY,
deal_id uuid NOT NULL REFERENCES shared.deal(id),
version int NOT NULL,
name text NOT NULL, -- e.g., "Iippo IC v8 base model"
time_axis_kind text NOT NULL CHECK (time_axis_kind IN ('year','quarter','month')),
start_period date NOT NULL, -- e.g., 2025-01-01 (Y0)
horizon_periods int NOT NULL, -- e.g., 7 (Y0~Y7)
currency text NOT NULL DEFAULT 'KRW',
unit_scale numeric NOT NULL DEFAULT 1, -- 1 / 1000 / 1000000 (천원/백만원)
base_revenue_period0 numeric, -- e.g., 120,000,000 (Iippo Y0 매출)
created_by text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
locked_at timestamptz, -- 후 immutable
source_xlsx_sha256 text,
source_xlsx_citation jsonb, -- {kind:"onedrive", drive_item_id, version, sheet}
source_yaml_citations jsonb DEFAULT '[]'::jsonb, -- scenario_deltas/exit_matrix yaml refs
UNIQUE (deal_id, version)
);
CREATE TABLE financial_driver (
id uuid PRIMARY KEY,
model_id uuid NOT NULL REFERENCES financial_model(id) ON DELETE CASCADE,
code text NOT NULL, -- e.g., "revenue_growth_y1"
kind text NOT NULL CHECK (kind IN ('input','derived','output')),
formula text, -- DSL — null if input
dependencies text[] NOT NULL DEFAULT '{}', -- 다른 driver code list
units text NOT NULL, -- '%', 'KRW', 'count', 'months', 'multiple'
category text NOT NULL, -- 'revenue', 'cost', 'opex', 'capex', 'financing', 'wc'
description text,
display_order int,
UNIQUE (model_id, code)
);
CREATE TABLE financial_scenario (
id uuid PRIMARY KEY,
model_id uuid NOT NULL REFERENCES financial_model(id) ON DELETE CASCADE,
code text NOT NULL, -- 'base', 'upside', 'mgmt', 'downside', 'custom_*'
name text NOT NULL, -- 'AXE Base'
kind text NOT NULL CHECK (kind IN ('base','upside','mgmt','downside','custom')),
probability numeric(5,4) NOT NULL, -- 0.0000 ~ 1.0000 (per-scenario, 합 = 1)
description text,
driver_changes jsonb NOT NULL DEFAULT '{}'::jsonb, -- narrative {story, rationale[], key_assumption_overrides}
parent_scenario_id uuid REFERENCES financial_scenario(id), -- fork chain
locked_at timestamptz,
UNIQUE (model_id, code)
);
CREATE TABLE financial_driver_value (
model_id uuid NOT NULL,
driver_code text NOT NULL,
scenario_id uuid NOT NULL REFERENCES financial_scenario(id) ON DELETE CASCADE,
period_index int NOT NULL, -- 0 ~ horizon_periods
value numeric,
is_override bool NOT NULL DEFAULT false, -- true = scenario override on baseline
PRIMARY KEY (model_id, driver_code, scenario_id, period_index),
FOREIGN KEY (model_id, driver_code) REFERENCES financial_driver(model_id, code)
);
CREATE TABLE financial_output (
id uuid PRIMARY KEY,
model_id uuid NOT NULL REFERENCES financial_model(id) ON DELETE CASCADE,
scenario_id uuid NOT NULL REFERENCES financial_scenario(id) ON DELETE CASCADE,
output_code text NOT NULL, -- 'irr', 'moic', 'npv', 'exit_valuation', 'axe_proceeds_total'
period_index int, -- null = terminal output, int = time series
value numeric,
computed_at timestamptz NOT NULL DEFAULT now(),
inputs_hash text NOT NULL, -- sha256(driver_value snapshot) — reproducibility
UNIQUE (model_id, scenario_id, output_code, period_index)
);
CREATE TABLE exit_matrix_leaf (
id uuid PRIMARY KEY,
scenario_id uuid NOT NULL REFERENCES financial_scenario(id) ON DELETE CASCADE,
timing text NOT NULL, -- '3y', '5y', '7y', 'never'
path text NOT NULL, -- 'ma', 'ipo', 'secondary', 'writedown', 'ma_strategic', 'partial'
probability numeric(5,4) NOT NULL, -- 0.0000~1.0000 (per timing, 합 = 1)
description text,
proceeds_krw numeric, -- 회사 전체 exit proceeds (EqV or EV)
axe_proceeds_krw numeric, -- AXE 회수 (proceeds × ownership_pct_fd × dilution)
recovery_rate numeric(5,4), -- writedown 시 5-15% 잔존 (D-PR 22 wd-assumption)
dead_leaf bool NOT NULL DEFAULT false, -- check_exit_matrix.py 결과
concentration bool NOT NULL DEFAULT false, -- 단일 leaf P > 10% (concentration warning)
UNIQUE (scenario_id, timing, path)
);상세 RLS · trigger · index 는 Phase 0 migration SQL 참조.
fund_investment
본 서비스의 두 번째 핵심 abstraction (D-index-5).
deal 은 회사 단위 thesis. fund_investment 는 cash flow + IRR carrier.
왜 3차원 N:M?
실 데이터:
- Iippo: 1 deal × 2 fund (1호 99,998,912 + 2호 100,000,000, 같은 round Pre-A)
- Sentry: 1 deal × 1 fund × multi-round option (1호 5억 + 후속 5억 pro-rata option future)
- Canopy: 1 deal × 1 fund × 다른 시점 multi-round (1호 BW 5억 initial + 1호 신주 follow 1억 v5)
세 deal 모두 N:M 의 다른 축. 단일 (deal, fund) FK pair 로는 부족.
Schema
CREATE TABLE shared.fund_investment (
id uuid PRIMARY KEY,
deal_id uuid NOT NULL REFERENCES shared.deal(id),
fund_entity_id text NOT NULL REFERENCES shared.entity(id), -- e.g., 'axe_ia_001'
round_label text NOT NULL, -- '초기', 'follow-on v5', 'pro-rata option'
instrument text NOT NULL, -- 'RCPS', 'BW', 'SAFE', '신주', '보통주'
committed_krw numeric NOT NULL, -- 약정 금액
invested_krw numeric, -- 실 납입 (paid 후 set)
share_count numeric, -- 주식 수
price_per_share numeric, -- 주당 가격
entry_date date, -- 결의/계약일
paid_date date, -- 납입일 (status=paid 후 set)
pre_money_krw numeric, -- 진입 시점
post_money_krw numeric,
ownership_pct_post numeric(7,6), -- 0.000000 ~ 1.000000
ownership_pct_fd numeric(7,6), -- F/D 희석 후
status text NOT NULL CHECK (status IN
('committed','paid','locked_in','written_off','partial_exited','exited')),
conditions jsonb DEFAULT '[]'::jsonb, -- PCC trigger 같은 조건
conditions_met_at timestamptz, -- 조건부 → 무조건 전환 시점
evidence_citations jsonb DEFAULT '[]'::jsonb, -- 계약서 OneDrive ref 등
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (deal_id, fund_entity_id, round_label)
);
CREATE INDEX fund_investment_deal_idx ON shared.fund_investment (deal_id);
CREATE INDEX fund_investment_fund_idx ON shared.fund_investment (fund_entity_id);
CREATE INDEX fund_investment_status_idx ON shared.fund_investment (status) WHERE status IN ('committed','paid','locked_in');Per-fund IRR 계산
-- financial_output 의 axe_proceeds_total 산출 → fund_investment.ratio 로 split
-- Iippo 케이스:
-- financial_output (scenario=base, output_code=axe_proceeds_total) = 9.4억 (Y5 회수)
-- fund_investment Iippo×axe_ia_001 ratio = 99,998,912 / 199,998,912 = 0.500003
-- fund_investment Iippo×axe_ia_002 ratio = 100,000,000 / 199,998,912 = 0.499997
-- ↓
-- 1호 회수 = 9.4억 × 0.500003 ≈ 4.70억
-- 1호 IRR = irr(cash_flow = [-99,998,912 @ 2026-05-15, +4.70억 @ 2030-06-30])
-- 2호 회수 = 9.4억 × 0.499997 ≈ 4.70억
-- 2호 IRR = irr(cash_flow = [-100,000,000 @ 2026-09-?? (PCC 6 후), +4.70억 @ 2030-06-30])
--
-- 같은 회사 같은 회수 비율이지만 paid_date 가 다르면 IRR 다름 (2호 납입 지연 → IRR 약간 ↓)view fund_investment_irr:
CREATE VIEW shared.fund_investment_irr AS
SELECT
fi.id AS fund_investment_id,
fi.deal_id,
fi.fund_entity_id,
fi.round_label,
fi.committed_krw,
fi.invested_krw,
fi.paid_date,
fs.scenario_id,
fs.code AS scenario_code,
fs.probability AS scenario_probability,
fo.value AS total_axe_proceeds_krw,
-- fund_investment 비례 split
fi.committed_krw / SUM(fi.committed_krw) OVER (PARTITION BY fi.deal_id) AS ratio,
fo.value * (fi.committed_krw / SUM(fi.committed_krw) OVER (PARTITION BY fi.deal_id))
AS fund_share_proceeds_krw,
-- IRR 계산은 Rust 측 compute_outputs 가 채워서 별 row 로 저장 (output_code='irr_per_fund')
FROM shared.fund_investment fi
JOIN financial_scenario fs ON fs.model_id IN (
SELECT id FROM financial_model WHERE deal_id = fi.deal_id ORDER BY version DESC LIMIT 1
)
JOIN financial_output fo ON fo.scenario_id = fs.id AND fo.output_code = 'axe_proceeds_total';이 view 위에 확률가중 IRR 합산도 SQL aggregate 한 줄.
DSL Formula
왜 한정 DSL?
xlsx formula 를 그대로 못 옮김 — cell ref (B14) 를 driver ref (revenue_y2) 로 매핑 필요. 또한 Excel 의 ~500 함수 중 IC memo cite 하는 건 10개 미만. 한정 DSL 이 (a) parser 단순, (b) audit 가능, (c) 보안 (eval 안 함).
문법 (10 operators)
expr = term (('+' | '-') term)*
term = factor (('*' | '/') factor)*
factor = number | driver_ref | func_call | '(' expr ')'
driver_ref = identifier '[' period ']' | identifier
period = 'y0' | 'y1' | ... | 'y<n>' | 'current'
func_call = func_name '(' args ')'
func_name = 'min' | 'max' | 'if' | 'sum' | 'avg' | 'lag' | 'growth' | 'cum'예제:
# 매출 = 직전 매출 × (1 + 성장률)
revenue[y1] = revenue[y0] * (1 + revenue_growth_y1)
revenue[y2] = revenue[y1] * (1 + revenue_growth_y2)
# ...
revenue[y_n] = lag(revenue, 1) * (1 + lag(revenue_growth, 0))
# 매출원가 = 매출 × (1 - 매출총이익률)
cogs = revenue * (1 - gross_margin_terminal)
# 영업이익 = 매출 - 매출원가 - 판관비
ebit = revenue - cogs - opex_sm - opex_rnd - opex_ga
opex_sm = revenue * opex_sm_per_revenue
opex_rnd = revenue * opex_rnd_per_revenue
opex_ga = revenue * opex_ga_per_revenue
# 운전자본
ar = revenue * ar_days / 365
inventory = cogs * inventory_days / 365
ap = cogs * ap_days / 365
# 세후 영업이익 + CAPEX
nopat = ebit * (1 - tax_rate)
capex = revenue * capex_per_revenue
# 자유현금흐름 + 잔여가치 + IRR
fcf = nopat + depreciation - capex - delta_wc
terminal_value = ebit[exit_year] * exit_multiple
exit_valuation = if(path == 'ipo', terminal_value, terminal_value * 0.85) # M&A discount
axe_proceeds = exit_valuation * ownership_pct_fdTopological evaluator
Rust petgraph::algo::toposort:
- DAG 구성:
(driver_code) -[depends_on]-> (driver_code)edge - cycle detect —
toposort가 cycle 감지 시 fail-fast (운영자에게 명시적 오류) - period 별 evaluation:
- p=0: input driver value 읽기 (driver_value 테이블)
- p=1..horizon: derived driver 를 toposort 순서로 평가
lag(driver, n)는 p-n 의 cached value 조회
- scenario 별 4 단계 반복 (base / upside / mgmt / downside)
- 결과 →
financial_outputrow insert (output_code = irr / moic / npv / exit_valuation / etc) inputs_hash= sha256(serialized driver_value snapshot) — 같은 input 으로 다시 돌리면 같은 hash + 같은 output
Reproducibility lock
compute_outputs(model_id=X, scenario_id=Y) 호출
↓ driver_value snapshot 읽기 → sha256
↓ financial_output 의 (model, scenario, output_code) 마다 inputs_hash 비교
↓ 같으면 skip (이미 계산됨), 다르면 재산출 + inputs_hash update→ ic skill 의 tests/fixtures/{DEAL}.json (lockfile baseline) 패턴 완성. PR 머지 전 fixture diff 자동 검출.
xlsx round-trip
ingest (xlsx → DB)
ingest_financial_model_xlsx(deal_id, xlsx_blob, hint?) MCP tool. LLM 보조 driver tree extract:
1. xlsx 의 sheet 목록 + cell range 파싱 (Rust `calamine`)
2. LLM prompt (Anthropic Sonnet, 1 call ~ 60s):
"Sheet 'Base' 의 row 'Revenue', 'COGS', 'Gross Profit', ...
의 cell B14:H14 가 무엇의 어떤 시계열을 표현하는지 추정.
Schema = financial_driver row 예시 [...]."
3. LLM 응답 → 제안 financial_driver rows + dependencies
4. ctx review queue 에 propose (사용자 confirm/edit/reject)
5. confirmed → financial_driver + financial_driver_value 적재
6. exit_matrix yaml 은 직접 파싱 (LLM 불필요) — schema 정형
7. scenario_deltas yaml 도 직접 (driver value override 만)
8. xlsx 의 IRR cell 과 DB compute_outputs 결과 비교 → ±1pp diff 시 warnvision-heavy 시점만 API direct (D-bp-artifact-7 layer 1 정합). 일상 propose 는 Claude Code OAuth (Max plan).
export (DB → xlsx)
export_xlsx(model_id, scenarios[]). driver tree → xlsx sheet 재생성:
1. 시나리오마다 한 sheet (Base / Upside / Mgmt / Downside)
2. row = driver (display_order 순), column = period (y0..y_n)
3. cell value = financial_driver_value.value (input) 또는 evaluator 산출 (derived)
4. derived cell 은 xlsx formula 도 출력 ('=B14*(1+B$3)') — 사용자가 xlsx 안에서 trace 가능
5. exit_matrix → 별 sheet (scenario × timing × path 표)
6. financial_output (IRR / MOIC / NPV) → Output sheetic skill 의 기존 ic/finance/3fs_base/v8.xlsx 와 cell-by-cell 비교 가능 — Phase 0 acceptance test.
Sanity check 흡수
ic skill 의 4 check 가 index 의 DB CHECK + trigger + validate_financial_model tool 로 이전:
| ic skill check | index 측 대응 |
|---|---|
xlsx_integrity.py (5 assertion: BS/CF formula coverage, IS Y-o-Y, Retained Earnings flow, Driver range sanity, cross-scenario shape) | trigger validate_driver_tree — DAG cycle / orphan driver / dependency 누락 검출. cross-scenario shape = scenario × driver_code coverage matrix 검사 |
check_arithmetic.py (paragraph self-claim 산수 검증) | memo artifact propose 시 numeric claim 추출 → financial_output cell 비교. validate_memo_arithmetic(memo_artifact_id, model_id) tool |
check_exit_matrix.py (dead leaf / concentration / downside semantic / WD recovery 0%) | trigger exit_matrix_sanity — INSERT/UPDATE 시 자동 검사. dead_leaf / concentration flag 자동 set |
citation_trace.py (memo 의 단위 동반 숫자 trace) | artifact citation 의 kind: "index.financial_output" 가 강제. trace 안 되는 숫자 = orphan citation warning |
ic skill 의 4 Python script 가 index Phase 1 후 deprecate — DB-side enforcement 가 더 결정론적.
3 deal worked example (실 데이터 기반)
Iippo (킵코퍼레이션, iipuda)
기초 데이터: /Users/axe/Library/CloudStorage/OneDrive-AXE/AXE - Ventures/1_Project/Prj_Iippo/ic/finance/* (memo v8, scenario_deltas v7, exit_matrix v7).
target_company + deal:
target_company:
legal_name: "주식회사 킵코퍼레이션"
brand_name: "iipuda"
biz_no: "TBD (dataroom 06.정관_등본)"
sector: "Medical Tourism Platform"
founding_date: "TBD"
deal:
deal_code: "Iippo"
target_company: Iippo
primary_entity_id: "axe_ia_001" # 1호가 리드 (블라인드 펀드)
stage: "Closed" # 2026-05-06 IC v8 통과
owner_email: "[email protected]"fund_investment — Iippo 의 1:N split (D-index-5 의 핵심 검증 케이스):
fund_investments:
- fund_entity_id: "axe_ia_001"
round_label: "Pre-A RCPS 1호 v9.0"
instrument: "RCPS"
committed_krw: 99998912 # 16,832주 × 5,941원
share_count: 16832
price_per_share: 5941
entry_date: "2026-04-30" # v9.0 sign-off APPROVED
paid_date: "2026-05-15"
pre_money_krw: 6000000000 # 60억
post_money_krw: 6200000000 # 62억
ownership_pct_post: 0.016130 # 1호 단독 1.613% (1호 + 2호 = 3.226%)
ownership_pct_fd: 0.010325 # F/D 1.0325% (희석 0.64x 후)
status: "paid"
conditions: [] # 무조건 GO
evidence_citations:
- kind: onedrive
path: "dataroom/07.리드투자_서류준비/RCPS_v9.0/"
- fund_entity_id: "axe_ia_002"
round_label: "Pre-A RCPS 2호 v6 (Conditional)"
instrument: "RCPS"
committed_krw: 100000000 # 잠정 1.5-2.0억 미확정 (강태훈 IC #2)
share_count: null # 협상 진행 중
price_per_share: 5941 # 같은 round 같은 단가
entry_date: null # 협상 미완
paid_date: null # 6 PCC 후
pre_money_krw: 6000000000
post_money_krw: 6200000000
ownership_pct_post: 0.016129 # 1.613%
ownership_pct_fd: 0.010325
status: "committed"
conditions: # 6 PCC trigger
- "PCC #3 — KPI 정합성 + AXEV 소개 병원 status"
- "PCC #4 — 앤틀러 RCPS amend + Michael Lin SAFE amend"
- "PCC #5 — 이사회 관찰권 + Pro-rata 명시"
- "PCC #6 — Q4 anti-dilution 법무 검토"
- "운영 신호 — 샤오홍슈 캠페인 + Q1-Q2 2026 경영성과"
- "품질 KPI — iipuda Guide 인증 dashboard 가동"
evidence_citations:
- kind: onedrive
path: "ic/memo/v8.md#1.1.5"financial_model (v7 base 기준):
financial_model:
deal_code: "Iippo"
version: 7
name: "Iippo IC v7 base model"
time_axis_kind: "year"
start_period: "2025-01-01" # Y0 = 2025 가결산
horizon_periods: 7 # Y0 ~ Y7 (2025~2032)
currency: "KRW"
unit_scale: 1
base_revenue_period0: 120000000 # 1.20억 = 2025 가결산
source_xlsx_citation:
kind: onedrive
path: "Prj_Iippo/ic/finance/3fs_base/v7.xlsx"financial_scenario (4종):
financial_scenarios:
- code: base
name: "AXE Base"
kind: base
probability: 0.50
description: "AXE 보수화 — 회사 IR 8개월 200병원 시뮬레이션을 시장 ramp 평균 (월 +5병원) 으로 할인"
driver_changes:
story: "병원 ramp 월 +5, Y3 매출 34.6억, 2030 EBITDA 38억 × EV/EBITDA 12x = 456억 EV"
key_assumption_overrides:
hospital_ramp: "월 +5병원 (vs Mgmt 월 +25)"
china_share: "60% 유지, 다변화 Y3 부터"
exit_multiple: "EV/EBITDA 12x"
- code: mgmt
name: "Mgmt Case"
kind: mgmt
probability: 0.10
description: "회사 IR 가정 그대로 lift"
driver_changes:
story: "Y1 200병원/14.75억, Y5 275억, 회사 주장 2030 EV 2조"
- code: upside
name: "Upside"
kind: upside
probability: 0.30 # base 보다 약간 낮음
driver_changes:
story: "닥터스클럽 leverage 폭발 + 일본/대만 가속 + M&A premium 18x"
- code: downside
name: "Downside"
kind: downside
probability: 0.10
driver_changes:
story: "Y3 매출 stall + 중국 의존 충격"financial_driver (15 driver — scenario_deltas yaml 정합):
financial_drivers:
- code: revenue_growth_y1
kind: input
units: multiple
category: revenue
description: "Y1 매출 성장 multiplier (revenue[y1] / revenue[y0])"
- code: revenue_growth_y2
kind: input
units: multiple
category: revenue
- code: revenue_growth_y3
kind: input
# ... y4, y5, y6, y7
- code: gross_margin_terminal
kind: input
units: percent
category: cost
- code: opex_sm_per_revenue
kind: input
units: percent
category: opex
- code: opex_rnd_per_revenue
kind: input
- code: opex_ga_per_revenue
kind: input
- code: ar_days
kind: input
units: count
category: wc
- code: inventory_days
kind: input
- code: ap_days
kind: input
- code: capex_per_revenue
kind: input
units: percent
category: capex
- code: depreciation_years
kind: input
units: count
- code: tax_rate
kind: input
units: percent
# Derived
- code: revenue
kind: derived
formula: "lag(revenue, 1) * (1 + revenue_growth_y[period])"
dependencies: ["revenue", "revenue_growth_y1", ..., "revenue_growth_y7"]
units: KRW
category: revenue
- code: ebit
kind: derived
formula: "revenue * gross_margin_terminal - revenue * (opex_sm_per_revenue + opex_rnd_per_revenue + opex_ga_per_revenue)"
dependencies: ["revenue", "gross_margin_terminal", "opex_sm_per_revenue", "opex_rnd_per_revenue", "opex_ga_per_revenue"]
units: KRW
category: revenue
# ... 추가 derived (fcf / nopat / exit_valuation / axe_proceeds)financial_driver_value (base scenario 일부):
financial_driver_values:
# base scenario
- { scenario: base, driver: revenue_growth_y1, period: 1, value: 6.5 } # Y1 = 7.8억 (Y0 × 6.5)
- { scenario: base, driver: revenue_growth_y2, period: 2, value: 2.4 } # Y2 = 18.7억
- { scenario: base, driver: revenue_growth_y3, period: 3, value: 1.85 } # Y3 = 34.6억
- { scenario: base, driver: revenue_growth_y4, period: 4, value: 1.55 }
- { scenario: base, driver: revenue_growth_y5, period: 5, value: 1.40 } # Y5 = 75억
- { scenario: base, driver: revenue_growth_y6, period: 6, value: 1.30 }
- { scenario: base, driver: revenue_growth_y7, period: 7, value: 1.25 }
- { scenario: base, driver: gross_margin_terminal, period: 5, value: 0.85 }
- { scenario: base, driver: opex_sm_per_revenue, period: 5, value: 0.35 }
- { scenario: base, driver: opex_rnd_per_revenue, period: 5, value: 0.12 }
- { scenario: base, driver: opex_ga_per_revenue, period: 5, value: 0.20 }
- { scenario: base, driver: ar_days, period: 5, value: 30 }
- { scenario: base, driver: inventory_days, period: 5, value: 0 }
- { scenario: base, driver: ap_days, period: 5, value: 30 }
- { scenario: base, driver: capex_per_revenue, period: 5, value: 0.02 }
- { scenario: base, driver: depreciation_years, period: 5, value: 5 }
- { scenario: base, driver: tax_rate, period: 5, value: 0.22 }
# ... upside / mgmt / downside override (scenario_deltas yaml 의 다른 값)exit_matrix_leaf (Iippo base 5y 일부):
exit_matrix_leaves:
# base × 5y × ma
- { scenario: base, timing: '5y', path: ma, probability: 0.55, axe_proceeds_krw: 1235000000 }
# base × 5y × ipo
- { scenario: base, timing: '5y', path: ipo, probability: 0.20, axe_proceeds_krw: 1000000000 }
# base × 5y × secondary
- { scenario: base, timing: '5y', path: secondary, probability: 0.20, axe_proceeds_krw: 600000000 }
# base × 5y × writedown
- { scenario: base, timing: '5y', path: writedown, probability: 0.05, recovery_rate: 0.10 }
# ... 3y / 7y / mgmt / upside / downside 동형financial_output (compute_outputs 산출):
financial_outputs:
- { scenario: base, output_code: axe_proceeds_total, value: 940000000 } # Y5 base 회수 9.4억
- { scenario: base, output_code: irr, value: 0.470 } # 47.0%
- { scenario: base, output_code: moic, value: 4.70 } # 회수/투자 ≈ 4.7x
# 확률가중 (4 scenario × probability)
- { scenario: weighted, output_code: irr_success_only, value: 0.539 } # 성공 IRR 53.9% (memo §1.1)
- { scenario: weighted, output_code: irr_loss_included, value: 0.370 } # 손실 포함 IRR 37.0%
- { scenario: weighted, output_code: moic_loss_included, value: 14.9 } # MoM 14.9xPer-fund IRR (fund_investment 별):
# financial_output 의 axe_proceeds_total = 9.4억 (base)
# 1호 ratio = 99,998,912 / 199,998,912 = 0.500003
# 2호 ratio = 100,000,000 / 199,998,912 = 0.499997
fund_investment_irrs:
- { fund: axe_ia_001, scenario: base,
paid_date: "2026-05-15", proceeds_at: "2030-06-30",
cash_flow: [-99998912, +470004700],
irr: 0.4732, moic: 4.70 }
- { fund: axe_ia_002, scenario: base,
paid_date: "2026-08-15", # PCC 6 후 3 개월 가정
proceeds_at: "2030-06-30",
cash_flow: [-100000000, +469995300],
irr: 0.4801, moic: 4.70 } # 같은 회수, paid 3 개월 지연 → IRR 약간 ↑ (보유 기간 짧음)Sentry (센티넬딥액티브)
기초 데이터: /Users/axe/Library/CloudStorage/OneDrive-AXE/AXE - Ventures/1_Project/Prj_Sentry/ic/{memo/v4.md, finance/*}.
target_company:
legal_name: "주식회사 센티넬딥액티브"
biz_no: "708-86-02988"
sector: "AI Asset Management"
founding_date: "2023"
deal:
deal_code: "Sentry"
primary_entity_id: "axe_ia_001"
stage: "Closed" # 2026-05-14 v4 만장 찬성
fund_investments:
- fund_entity_id: "axe_ia_001"
round_label: "Pre-A Bridge RCPS"
instrument: "RCPS"
committed_krw: 500068750 # 4,495주 × 111,250원
share_count: 4495
price_per_share: 111250
entry_date: "2026-05-06" # 현대차 5-6 날인
paid_date: "2026-05-08"
pre_money_krw: 9290000000 # 92.9억
post_money_krw: 9790000000 # 97.9억
ownership_pct_post: 0.0473 # 4.73%
ownership_pct_fd: 0.0446 # 4.46% F/D
status: "paid"
- fund_entity_id: "axe_ia_001"
round_label: "Series A Pro-rata Option"
instrument: "TBD" # 후속 라운드 시 결정
committed_krw: 500000000 # 추가 5억 option
status: "committed" # 옵션 — 6 개월 KPI 충족 시 행사
conditions:
- "Series A 라운드 진입 확정"
- "후속 6개월 KPI 충족"
# financial_model (Sentry v3 기준 — 본 docs 의 worked example 은 abbreviate)
financial_model:
version: 3
source_xlsx_citation:
path: "Prj_Sentry/ic/finance/3fs_base/v3.xlsx"
scenarios:
- { code: upside, probability: 0.19, axe_proceeds: 23600000000 } # 236억 (5y M&A_strategic or IPO)
- { code: base, probability: 0.49 }
- { code: mgmt, probability: 0.05 }
- { code: downside, probability: 0.27 }
outputs:
irr_success_only: 0.599 # 59.9% (memo §1.1)
irr_loss_included: 0.414 # 41.4%
moic_success_only: 16.8
moic_loss_included: 13.2Sentry 는 1 deal × 1 fund × 2 round (initial + future option) — fund_investment 2 row.
Canopy (사이클로이드, bardream)
기초 데이터: Prj_Canopy/ic/{memo/v5_final.md, finance/*}.
target_company:
legal_name: "주식회사 사이클로이드"
brand_name: "bardream"
sector: "Electric Mobility Subscription"
deal:
deal_code: "Canopy"
primary_entity_id: "axe_ia_001"
stage: "Closed" # v5 final 2026-05-15
fund_investments:
- fund_entity_id: "axe_ia_001"
round_label: "Initial BW (Pre-A)"
instrument: "BW" # Bond with Warrants
committed_krw: 500000000 # 5억
entry_date: "TBD"
paid_date: "TBD"
pre_money_krw: 6500000000 # v4 기준 (v5 협상 anchor 80억 F/D 81.28억)
status: "paid"
- fund_entity_id: "axe_ia_001"
round_label: "v5 신주 follow-on"
instrument: "신주"
committed_krw: 100000000 # 1억 follow (Soohun framing)
entry_date: "2026-05-15" # v5 final
paid_date: "TBD"
pre_money_krw: 8000000000 # O/S Pre 80억 (Post 100억, F/D Pre 81.28억)
post_money_krw: 10000000000
status: "committed"
conditions:
- "AXEC 자금 별도 plug (§10 CP-5)"
- "컨소시엄 분담 시도 (부산창경 등)"
# financial_model (Canopy v1)
financial_model:
version: 1
source_xlsx_citation:
path: "Prj_Canopy/ic/finance/3fs_base/v1.xlsx"
scenarios:
- { code: upside, probability: 0.25 }
- { code: base, probability: 0.45 }
- { code: downside, probability: 0.30 }
exit_assumptions:
fleet_year_5: 5500 # V3 base 5,500대
market_share: 0.30 # 30% (서울시 PM 25만대 expansion)
ebitda_year_5_krw: 6641000000 # 66.41억 (57.5 + 광고 element 8.91)
exit_multiple_ev_ebitda: 12
exit_ev_krw: 79700000000 # 797억
exit_net_debt_krw: 30000000000 # 300억
exit_eqv_fd_krw: 49800000000 # 498.28억
outputs:
# D-index-16 (2026-05-28): per-leaf methodology 통일. V5_final 정합 데이터로
# per-leaf 가 27% 매칭 검증 완료 (Canopy 26.39%, baseline 27%, Δ=0.01).
# 아래 anchor 산출은 deprecated — V1 → V5_final 정합 후 자동 일치.
irr_loss_included_per_leaf: 0.27 # ⭐ IC PASS (per-leaf, D-index-16)
hurdle_irr: 0.15
irr_excess: 0.119 # +11.9pp 여유Canopy 는 1 deal × 1 fund × 2 round (다른 시점 + 다른 instrument BW → 신주).
3 deal cross-check 표
| 항목 | Iippo | Sentry | Canopy |
|---|---|---|---|
| Multi-fund | 2 fund (1호+2호) ⭐ | 1 fund | 1 fund |
| Multi-round | 1 round | 2 round (initial + future option) | 2 round (initial + follow-on) ⭐ |
| Instrument 변화 | RCPS only | RCPS → TBD (옵션) | BW → 신주 ⭐ |
| Total committed | 199,998,912원 | 500,068,750원 (+ 5억 option) | 500,000,000원 (+ 1억 follow) |
| Scenarios | 4 (base/mgmt/upside/downside) | 4 | 3 (upside/base/downside) |
| Probability base | 0.50 | 0.49 | 0.45 |
| Success IRR (per-leaf) | 53.9% | 59.9% | 44.1% (V5 정합 후) |
| IC pass IRR (loss-included, per-leaf) | 37% ⭐ | 41% ⭐ | 27% ⭐ |
| Hold years | 4.17y | 5.4y | 4.67y |
| Exit multiple | EV/EBITDA 12x | PER 15x (upside) / 8x (base) | EV/EBITDA 12x |
| Key memo | v8 (2026-05-06) | v4 (2026-05-14) | v5_final (2026-05-15) |
세 deal 이 fund_investment 의 3 차원 N:M 을 모두 cover — Phase 0 acceptance fixture (D-index-10).
MCP tools (financial 관련)
⚠ design-era 이름 — 아래 표는 D-index-4/5 설계 시 가안한 tool 명세다. served tool 의 현행 SoT 는 /services/index § MCP 도구 카탈로그 (27개). 매핑:
ingest_financial_model_xlsx→import_xlsx/propose_artifacts_from_ingest,compare_drivers_across_deals→cross_deal_benchmark,export_xlsx→export_lp_model/export_lp_bundle,get_financial_model→get_deal. IRR 은weighting인자 없이 IRR(E[CF]) 가 유일 canonical (D-index-25/32 —success_only/loss_includedweighting 폐기).compute_full_model(DSL evaluator) +compute_3fs(IS/BS/CF) 가 추가됨.
| Tool | Scope | 기능 |
|---|---|---|
ingest_financial_model_xlsx(deal_id, xlsx_blob, hint?) | write | LLM 보조 driver tree extract → propose financial_model + drivers + values |
propose_financial_model(deal_id, drivers, scenarios, values, exit_matrix) | write | DB 직접 (xlsx 없이) |
update_driver(model_id, code, formula?, dependencies?, units?) | write | unlocked 만 |
update_driver_value(model_id, driver_code, scenario_id, period_index, value) | write | unlocked 만 |
create_scenario(model_id, code, name, kind, probability, driver_changes, overrides{}) | write | parent_scenario fork chain |
compute_outputs(model_id, scenario_id?) | write | topo evaluator 실행 → output row 적재. inputs_hash 비교 |
get_financial_model(model_id, include_drivers?, include_values?) | read | model + components |
list_scenarios(model_id) | read | scenario 4종 + probability |
query_driver_series(deal_id, driver_code, periods[], scenarios[]) | read | cross-deal driver benchmark — 본 서비스 핵심 query |
| `query_irr(deal_id, fund_investment_id?, weighting=‘success_only' | 'loss_included’)` | read |
compare_drivers_across_deals(driver_code, deal_ids[], scenarios[]) | read | cross-portfolio benchmark |
lock_financial_model(model_id) | approve | immutable 전환 + locked_at set |
export_xlsx(model_id, scenario_ids[]) | read | round-trip 재생성 |
validate_financial_model(model_id) | read | ic skill 의 4 check 통합 결과 |
Phase 0 Acceptance Bar
D-index-10 의 검증 fixture:
| Test | 조건 |
|---|---|
| A1 | 3 deal seed yaml → index DB ingest 성공 (target_company + deal + fund_investment + financial_model + financial_driver + financial_scenario + financial_driver_value + exit_matrix_leaf 모두 적재) |
| A2 | compute_outputs(iippo_model_id, base_scenario_id) 결과의 axe_proceeds_total 가 ic skill 의 irr_analysis/v7.xlsx cell J42 와 ±1% 일치 |
| A3 | query_irr(iippo_deal_id, fund_investment_id=axe_ia_001, weighting='success_only') = 53.9% ±0.5pp |
| A4 | query_irr(iippo_deal_id, fund_investment_id=axe_ia_002, weighting='success_only') 가 1호 IRR 과 다름 (paid_date 지연 반영) |
| A5 | compare_drivers_across_deals('gross_margin_terminal', [iippo, sentry, canopy], ['base']) 가 3 row 반환 |
| A6 | export_xlsx(iippo_model_id, [base_scenario_id]) 결과 xlsx 가 원본 3fs_base/v7.xlsx 와 ±0 driver cell diff |
| A7 | validate_financial_model(iippo_model_id) 4 check 모두 PASS (또는 ic skill 의 기존 warning 과 100% 일치) |
| A8 | Blueprint artifact 의 IC memo citation = { kind: "index.financial_output", model_id, scenario_id: "base", output_code: "irr" } resolve 시 0.470 반환 |
8 test 통과 시 Phase 0 완료.
관련 페이지
- /services/index — 서비스 main
- /services/index/schema-catalog — 14 schema 상세 spec
- /services/index/skill-evolution —
--push-to-indexflow + ic skill 진화 - /services/index/skill-integration — 3 skill 통합 아키텍처 + atomic propose + idempotency + 3-layer error model
- /ops/decisions D-index-4 — financial_model 6-table 결정
- /ops/decisions D-index-5 — fund_investment N:M 결정
- /ops/decisions D-index-10 — 3 deal Phase 0 fixture
- /ops/roadmap M7 — 3 Phase 구조