Files
All-in-one-Financial-Analysis/atlas-terminal/claude.md
T
shawnkim1997andClaude Opus 4.6 51cbaf7f8d feat: major codebase audit — 21 routers, 37 services, 12 pages fully documented
- Add missing numpy, scipy, dbnomics to requirements.txt (fixes ImportError on fresh install)
- Sync claude.md with actual codebase: §3 file structure (37 services, 21 routers),
  §5 API endpoints (92 routes), §6 frontend pages (12), §13 TODO status
- Update README.md with current architecture (92 API routes, 21 routers, 37 services),
  multi-asset overview, research grid, macro dashboard, screener+backtest,
  multi-jurisdiction filings, and 2026-03-26 changelog entry
- Add new routers: dart, edinet, fmp, macro, research
- Add new services: cache, dart_fetcher, dart_filing_service, economic_calendar,
  ecos_fetcher, edinet_filing_service, fmp_client, global_macro_quadrant,
  kpi_history_service, macro_cycle, macro_fetcher, oecd_cycle,
  peer_comparison_service, research_dashboard, smart_money_service, yield_fx_service
- Add new frontend: macro page, screener+backtest, research grid components,
  overview (Equity/ETF/Commodity), filings (SEC/DART/EDINET), error boundaries
- Remove 6 unused services: copilot_context, crypto_fetcher, fx_fetcher,
  gemini_analysis, market_data, technical_analysis
- Remove obsolete docs: .agent/, AGENT.md, ATLAS_EVALUATION.md, docs/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:39:07 +00:00

639 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# claude.md — ATLAS Terminal Build Guide
> 이 문서는 Claude Code 에이전트가 프로젝트를 빌드할 때 참조하는 마스터 가이드입니다.
> 모든 에이전트는 작업 시작 전 이 문서를 반드시 읽어야 합니다.
> **마지막 수정: 2026-03-26**
---
## 1. Project Identity
| 항목 | 내용 |
|------|------|
| **이름** | ATLAS Terminal (Advanced Terminal for Liquid Asset Surveillance) |
| **목적** | 개인 투자자에게 기관급 투자 리서치를 단일 인터페이스로 제공 |
| **핵심 철학** | 금융 정보 비대칭 해소 — 기술로 리테일 투자자의 무기를 평등하게 |
| **디자인** | Bloomberg Terminal의 정보 밀도 + Notion의 깔끔함 + 다크 모드 |
| **스택** | Next.js 14 (App Router) + FastAPI + SQLite/PostgreSQL + Gemini API |
| **프로젝트 루트** | `/Users/seonpil/Library/Mobile Documents/com~apple~CloudDocs/Documents/FQDC Project/atlas-terminal/` |
---
## 2. Architecture Principles (절대 규칙)
### 2.1 하이브리드 분리 원칙
```
정성 데이터 (Qualitative) → LLM (Gemini) → 텍스트 분석만
정량 데이터 (Quantitative) → Pandas + yfinance/yahooquery → 숫자/계산만
```
- **절대 LLM에 숫자 계산을 맡기지 않는다** — LLM은 텍스트 분석, 번역, 요약만 담당
- 모든 재무 지표(DCF, DuPont, Altman Z, F-Score)는 Python 코드로 계산
- 이 원칙을 위반하면 비용 폭발 + 정확도 하락
### 2.2 토큰 최적화 (비용 통제)
- 10-K 원문을 LLM에 보내기 전 반드시 `sec_parser.py`로 Item 1A~9A만 추출
- `text_chunker.py``smart_chunk()`로 10,000자 이내로 압축 (head+tail 보존)
- Gemini 호출은 탭당 최대 1~2회로 제한
- 429 에러 시 `_generate_with_retry()`로 60초 대기 후 재시도
### 2.3 다단계 폴백 체인 (기능별 — 코드와 일치)
“한 줄 체인”이 아니라 **엔드포인트/서비스마다** 소스 순서가 다르다. 아래가 실제 구현 기준이다.
| 영역 | 1순위 | 2순위 | 비고 |
|------|--------|--------|------|
| 가격·차트·`info`·배당 등 | yfinance | yahooquery | `market_data`, `technical`, 대부분 라우터 |
| 연간 재무제표 (`/api/financials/.../statements`) | yfinance | yahooquery | 연간만 필터 |
| DCF 입력·`market_fetcher` 연간 집계 | yahooquery (TTM 보강) | yfinance (분기 합산 등) | `server/services/market_fetcher.py` |
| 히스토리컬 밸류·재무 비율·어닝콜 (선택) | FMP (`FMP_API_KEY` 있을 때만) | yahooquery `summary_detail` / `financial_data` | yfinance `info``server/services/fmp_client.py` |
| 거시 (FRED/OECD/ECOS) | FRED 공개 CSV / ECOS 키 | — | `server/services/macro_fetcher.py` |
레거시 서술(참고): 티커 메타/추정 등 일부 경로는 `fast_info``info` → 재무표 순으로 보강한다.
- 모든 숫자 파싱에 `_safe_float()` 사용 (`server/utils/safe_float.py`)
- 실패 시 빈 DataFrame 또는 None 반환, 절대 에러를 UI에 노출하지 않음
### 2.4 모듈 분리 원칙
- **한 파일 = 한 책임** — 단일 파일 3000줄 금지
- 파일당 최대 300줄 목표
- 비즈니스 로직 → `server/services/`, API 엔드포인트 → `server/routers/`
- 프론트엔드 컴포넌트는 기능별로 분리
### 2.5 Multi-Key Column Lookup (중요!)
yfinance와 yahooquery는 같은 데이터의 컬럼명이 다르다:
- yfinance: `"Total Revenue"` (띄어쓰기)
- yahooquery: `"TotalRevenue"` (CamelCase)
프론트엔드에서 **파이프 구분자 패턴**으로 해결:
```tsx
function getValue(periodData: Record<string, any>, key: string) {
const keys = key.split("|");
for (const k of keys) {
const v = periodData[k.trim()];
if (v != null && typeof v === "number") return v;
}
return null;
}
// 사용 예: getValue(data, "TotalRevenue|Total Revenue|Revenue")
```
---
## 3. 현재 File Structure (실제 아키텍처)
```
atlas-terminal/
├── apps/web/ # Next.js 14 프론트엔드
│ ├── src/app/
│ │ ├── layout.tsx # 루트 레이아웃 (AppShell 래퍼)
│ │ ├── page.tsx # Overview — Multi-Asset (Equity/ETF/Commodity 자동분기)
│ │ ├── globals.css # Tailwind + Terminal Noir 기본 스타일
│ │ ├── error.tsx # 세그먼트 레벨 에러 바운더리
│ │ ├── global-error.tsx # 루트 레벨 에러 바운더리
│ │ ├── not-found.tsx # 404 페이지
│ │ ├── research/page.tsx # 리서치 그리드 (F-Score, DuPont, Sankey, Waterfall, Anomaly)
│ │ ├── valuation/page.tsx # 5-Tab: DCF, Sensitivity, Monte Carlo, Tornado, Reverse DCF
│ │ ├── technical/page.tsx # TradingView 캔들차트 + RSI/MACD/Bollinger/Fibonacci/Ichimoku
│ │ ├── markets/page.tsx # 재무제표 테이블 + 섹터 히트맵
│ │ ├── macro/page.tsx # 거시 5탭(FRED/Cycle/OECD/Korea/Calendar) + Quadrant/YieldFX/SmartMoney
│ │ ├── earnings/page.tsx # EPS Beat/Miss + Revenue + Next Earnings
│ │ ├── news/page.tsx # Split-view: 기사 리스트 + iframe 원문
│ │ ├── screener/page.tsx # 종목 스크리너 + 전략 백테스트
│ │ ├── portfolio/page.tsx # 포지션 CRUD + Risk Metrics + OCR
│ │ ├── filings/page.tsx # 공시 원문 — SEC/DART/EDINET 자동분기 (5탭 + AI 요약)
│ │ ├── settings/page.tsx # API Key 관리
│ │ ├── components/
│ │ │ ├── app-shell.tsx # 3-panel 레이아웃 래퍼 (SSR-safe dynamic import)
│ │ │ ├── sidebar.tsx # 좌측 네비게이션 (12개 메뉴)
│ │ │ ├── ticker-bar.tsx # 상단 실시간 지수 바 (S&P, NASDAQ, KOSPI, BTC)
│ │ │ ├── chat-panel.tsx # 우측 AI Copilot 채팅
│ │ │ ├── filings/
│ │ │ │ └── FilingsViewer.tsx # 공시 뷰어 (IntersectionObserver scroll-spy)
│ │ │ ├── macro/
│ │ │ │ ├── GlobalMacroQuadrantChart.tsx # 성장 vs 인플레 Z-score 산점도
│ │ │ │ ├── YieldFxDualAxisChart.tsx # US10Y 스프레드 vs FX 이중축
│ │ │ │ └── SmartMoneyPanel.tsx # Copper/Gold + RORO 패널
│ │ │ ├── markets/
│ │ │ │ ├── HeatmapSection.tsx # 섹터 히트맵 (S&P/NASDAQ/KOSPI/FTSE)
│ │ │ │ ├── EconomicCalendar.tsx # 글로벌 경제 이벤트
│ │ │ │ ├── KoreaMonitor.tsx # 한국 경제 지표 (ECOS)
│ │ │ │ ├── MacroCycleHeatmap.tsx # 매크로 사이클 히트맵
│ │ │ │ └── OECDCycleChart.tsx # OECD CLI 차트
│ │ │ ├── overview/
│ │ │ │ ├── EquityOverview.tsx # 주식 오버뷰 (섹터, DuPont, Altman Z)
│ │ │ │ ├── ETFOverview.tsx # ETF 오버뷰 (보유종목, 섹터비중)
│ │ │ │ ├── CommodityOverview.tsx # 원자재 오버뷰 (계절성, 상관관계)
│ │ │ │ ├── KpiSection.tsx # 분기 KPI 스파크라인
│ │ │ │ └── PeerComparison.tsx # 동종업계 밸류에이션 비교
│ │ │ └── research/
│ │ │ ├── ResearchGridLayout.tsx # 12-col CSS 그리드 레이아웃
│ │ │ ├── FScorePanel.tsx # Piotroski F-Score 이력 (9항목)
│ │ │ ├── DuPontTree.tsx # 3-Factor ROE 분해 트리
│ │ │ ├── SankeyWidget.tsx # 손익 Sankey (@nivo/sankey)
│ │ │ ├── WaterfallWidget.tsx # 영업이익 워터폴 (@nivo/bar)
│ │ │ ├── AnomalyChips.tsx # YoY 이상치 + Gemini 설명
│ │ │ └── types.ts # 리서치 대시보드 타입 정의
│ │ └── lib/
│ │ ├── use-ticker.ts # 티커 상태 훅 (localStorage + CustomEvent, hydration-safe)
│ │ ├── api.ts # API 클라이언트 유틸 (apiFetch, apiPost)
│ │ ├── ticker-alias.ts # 자연어→티커 매핑 ("gold"→GC=F, "samsung"→005930.KS)
│ │ └── filing-jurisdiction.ts # 티커→관할권 추론 (SEC/DART/EDINET)
│ ├── next.config.mjs # /api/* → localhost:8000 프록시
│ ├── tailwind.config.ts # Terminal Noir 컬러 토큰
│ └── package.json
├── server/ # FastAPI 백엔드
│ ├── main.py # FastAPI app + 21개 라우터 등록
│ ├── routers/ # API 엔드포인트 (21개)
│ │ ├── analysis.py # POST /api/analysis — Gemini LLM 분석 (strategy/risks/mda/forensic)
│ │ ├── chat.py # /api/chat — AI Copilot
│ │ ├── crypto.py # /api/crypto — 암호화폐 가격
│ │ ├── dart.py # /api/dart — Korea DART 기업검색 + 사업보고서 섹션
│ │ ├── earnings.py # /api/earnings — history|calendar|quarterly|transcript
│ │ ├── edgar.py # /api/edgar — SEC 10-K 다운로드 + 파싱
│ │ ├── edinet.py # /api/edinet — Japan EDINET 링크 + 섹션 (optional key)
│ │ ├── estimates.py # /api/estimates — 애널리스트 추정치
│ │ ├── financials.py # /api/financials — statements/highlights/kpi-history/ratios
│ │ ├── fmp.py # /api/fmp — Key metrics, ratios (optional FMP key)
│ │ ├── fx.py # /api/fx — 환율
│ │ ├── insider.py # /api/insider — 내부자 거래 + 기관보유
│ │ ├── macro.py # /api/macro — FRED/OECD/ECOS/Quadrant/YieldFX/SmartMoney/Calendar
│ │ ├── market_data.py # /api/market — 시세/섹터/헬스/트렌드/피어/Sankey/Radar/ETF/원자재
│ │ ├── markets.py # /api/markets — 섹터 히트맵
│ │ ├── news.py # /api/news — Finviz + Google + Yahoo RSS
│ │ ├── portfolio.py # /api/portfolio — CRUD + Risk + OCR
│ │ ├── research.py # /api/research — 퀀트 대시보드 (F-Score/DuPont/Sankey/Waterfall/Anomaly)
│ │ ├── screener.py # /api/screener — 종목 검색 + 백테스트
│ │ ├── technical.py # /api/technical — indicators/chart-data/fibonacci/ichimoku
│ │ └── valuation.py # /api/valuation — DCF/Sensitivity/Monte Carlo/Tornado/Reverse DCF
│ ├── services/ # 비즈니스 로직 (37개)
│ │ ├── backtester.py # 전략 백테스트 (SMA/RSI/Buy&Hold)
│ │ ├── cache.py # 인메모리 TTL 캐시 데코레이터
│ │ ├── commodity_analysis.py # 원자재 계절성·상관관계
│ │ ├── dart_fetcher.py # DART API 클라이언트 (기업검색)
│ │ ├── dart_filing_service.py # DART 사업보고서 ZIP/XML → 섹션 매핑 + 캐시
│ │ ├── dcf_engine.py # excel_style_dcf, dcf_10y_2stage, reverse_dcf (scipy brentq)
│ │ ├── economic_calendar.py # 경제 캘린더 데이터
│ │ ├── ecos_fetcher.py # 한국은행 ECOS 매크로 데이터
│ │ ├── edinet_filing_service.py # EDINET API v2 + 링크 폴백
│ │ ├── etf_analysis.py # ETF 보유종목·섹터비중
│ │ ├── exchange_resolver.py # 거래소 해석
│ │ ├── financial_metrics.py # DuPont, Altman Z, Piotroski F-Score
│ │ ├── financial_metrics_ext.py # 확장 지표 (Sankey, Waterfall 데이터)
│ │ ├── fmp_client.py # FMP API + Yahoo fallback snapshots
│ │ ├── gemini_service.py # Gemini API 래퍼 (retry, streaming)
│ │ ├── global_macro_quadrant.py # 성장 vs 인플레 Z-score 사분면
│ │ ├── heatmap.py # 섹터 히트맵 데이터
│ │ ├── kpi_history_service.py # 분기 KPI 시계열 (매출성장/마진/ROE/FCF)
│ │ ├── macro_cycle.py # 매크로 사이클 분석 (FRED + World Bank)
│ │ ├── macro_fetcher.py # FRED CSV + OECD + ECOS 매크로 데이터
│ │ ├── market_fetcher.py # yfinance/yahooquery 폴백 체인 (DCF 입력)
│ │ ├── market_overview.py # 시장 개요 데이터
│ │ ├── monte_carlo.py # run_monte_carlo_dcf (numpy, 5000 sims)
│ │ ├── news_aggregator.py # Finviz scrape + Google/Yahoo RSS
│ │ ├── oecd_cycle.py # OECD CLI via DBnomics
│ │ ├── peer_comparison_service.py # 동종업계 밸류에이션 비교
│ │ ├── research_dashboard.py # 리서치 대시보드 (F-Score/DuPont/Sankey/Waterfall/Anomaly)
│ │ ├── risk_metrics.py # VaR, Sharpe, Sortino, MDD, Beta, Correlation
│ │ ├── screener.py # 종목 스크리너 로직
│ │ ├── screenshot_ocr.py # Gemini Vision OCR (포트폴리오 스크린샷)
│ │ ├── sec_parser.py # 10-K 다운로드 + HTML 파싱 + 섹션 추출 + 캐싱
│ │ ├── sector_heatmap.py # 섹터 히트맵 계산
│ │ ├── sensitivity.py # build_sensitivity_matrix, build_tornado_data
│ │ ├── smart_money_service.py # Copper/Gold ratio + RORO 리스크 복합지수
│ │ ├── text_chunker.py # smart_chunk, clean_text_for_llm
│ │ └── yield_fx_service.py # US10Y 스프레드 vs FX (USDJPY/EURUSD/USDKRW)
│ ├── db/ # 데이터베이스 레이어
│ │ ├── unified_repo.py # SQLite/PostgreSQL 통합 인터페이스
│ │ ├── cache.py # 캐시 저장소
│ │ ├── database.py # SQLite 커넥션
│ │ ├── pg_database.py # PostgreSQL 커넥션
│ │ ├── portfolio_repo.py # 포트폴리오 SQLite CRUD
│ │ ├── pg_portfolio_repo.py # 포트폴리오 PostgreSQL CRUD
│ │ ├── pg_cache_repo.py # PostgreSQL 캐시
│ │ ├── dashboard_repo.py # 대시보드 레이아웃 저장
│ │ └── settings_repo.py # 설정 저장소
│ ├── models/
│ │ ├── schemas.py # Pydantic 모델 (요청/응답)
│ │ └── db.py # DB 모델
│ ├── ai/
│ │ ├── llm_router.py # LLM 프로바이더 라우팅
│ │ └── context_builder.py # 컨텍스트 빌더
│ └── utils/
│ ├── safe_float.py # 안전한 숫자 파싱
│ └── ticker_utils.py # 티커/자산유형 유틸리티
├── claude.md # 이 파일 (AI 에이전트 매뉴얼)
├── requirements.txt # Python 의존성
└── README.md
```
---
## 4. Design System — "Terminal Noir"
### 4.1 Tailwind 컬러 토큰 (`tailwind.config.ts`)
```typescript
colors: {
bg: {
primary: "#0A0A0F", // 메인 배경
secondary: "#12121A", // 서브 배경
card: "#1A1A26", // 카드 서피스
hover: "#252536", // 호버 상태
},
accent: {
green: "#00D4AA", // 상승, CTA, 활성 (민트 그린)
red: "#FF4757", // 하락, 경고
yellow: "#FFD93D", // 주의, 하이라이트
blue: "#4DA6FF", // 정보, 링크
},
text: {
primary: "#F3F4F6", // 주 텍스트
secondary: "#9CA3AF", // 보조 텍스트
muted: "#6B7280", // 약한 라벨
},
border: { DEFAULT: "#2A2A3A" },
}
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
mono: ["JetBrains Mono", "monospace"],
}
```
### 4.2 UI 규칙
- **숫자**: 양수 = `text-accent-green` + `+` 접두사, 음수 = `text-accent-red`, 폰트 = `font-mono`
- **카드**: `bg-bg-card border border-border rounded-lg p-5`
- **로딩**: `text-accent-green animate-pulse font-mono "Loading data..."`
- **AI 관련**: `text-accent-blue` 또는 인디고 계열
- **에러**: `border-accent-red/30` 배경 + `text-accent-red` 텍스트
### 4.3 3-Panel 레이아웃
```
┌──────────────────────────────────────────────────────────┐
│ [ATLAS TERMINAL] S&P 500 -1.51% NASDAQ +2.81% ... │ ← TickerBar (h-52px, fixed top)
├───────────┬──────────────────────────┬───────────────────┤
│ │ │ │
│ Sidebar │ Main Content │ AI Copilot │
│ w-260px │ flex-1 │ w-380px │
│ │ p-7 │ │
│ Overview │ │ Ask me anything │
│ Research │ (각 페이지 콘텐츠) │ about {ticker} │
│ Valuation │ │ │
│ Technical │ │ [Send] │
│ Markets │ │ │
│ Earnings │ │ │
│ News │ │ │
│ Portfolio │ │ │
│ Filings │ │ │
│ Settings │ │ │
│ │ │ │
└───────────┴──────────────────────────┴───────────────────┘
```
---
## 5. API Endpoints (전체 목록)
### 5.1 Market Data (`/api/market`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/market/indices` | S&P 500, NASDAQ, KOSPI, BTC |
| GET | `/api/market/overview` | 글로벌 시장 개요 |
| GET | `/api/market/overview/{ticker}` | 자산유형별 개요 (Equity/ETF/Commodity 자동분기) |
| GET | `/api/market/sectors` | 섹터 히트맵 데이터 |
| GET | `/api/market/sector/{ticker}` | 섹터, 산업, 시총, PE, 베타, 52주 |
| GET | `/api/market/health/{ticker}` | DuPont, Altman Z, Red Flags |
| GET | `/api/market/quote/{ticker}` | 현재가, 변동률 (빠른 시세) |
| GET | `/api/market/trend/{ticker}` | 5년 재무 트렌드 |
| GET | `/api/market/peers/{ticker}` | 동종업계 밸류에이션 멀티플 |
| GET | `/api/market/comps` | 비교기업 분석 |
| GET | `/api/market/piotroski/{ticker}` | Piotroski F-Score |
| GET | `/api/market/sankey/{ticker}` | 손익 Sankey 데이터 |
| GET | `/api/market/radar/{ticker}` | 레이더 차트 지표 |
| GET | `/api/market/etf/{ticker}/holdings` | ETF 보유종목 |
| GET | `/api/market/commodity/{ticker}/seasonal` | 원자재 월별 계절성 |
| GET | `/api/market/commodity/{ticker}/correlations` | 원자재 상관관계 |
### 5.2 Financials (`/api/financials`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/financials/{ticker}/statements` | IS + BS + CF 통합 (yfinance → yahooquery 폴백) |
| GET | `/api/financials/{ticker}/highlights` | 핵심 재무 요약 (매출, 마진, ROE, D/E, OCF) |
| GET | `/api/financials/{ticker}/kpi-history` | 분기 KPI 시계열 (매출성장, 마진, ROE, FCF) |
| GET | `/api/financials/{ticker}/ratios` | 밸류에이션·재무 비율 |
### 5.3 Valuation (`/api/valuation`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/valuation/dcf-inputs/{ticker}` | DCF 입력 자동채움 |
| GET | `/api/valuation/smart-defaults/{ticker}` | 스마트 DCF 기본값 |
| POST | `/api/valuation/dcf` | 3-시나리오 DCF |
| POST | `/api/valuation/sensitivity` | WACC × Terminal Growth 매트릭스 |
| POST | `/api/valuation/monte-carlo` | 5000회 시뮬레이션 + 히스토그램 |
| POST | `/api/valuation/tornado` | 변수별 민감도 순위 |
| POST | `/api/valuation/reverse-dcf` | 시장 내재 성장률 (scipy brentq) |
| GET | `/api/valuation/consensus/{ticker}` | 애널리스트 컨센서스 |
### 5.4 Technical (`/api/technical`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/technical/{ticker}/indicators` | RSI, SMA, EMA, MACD, BB, ATR |
| GET | `/api/technical/{ticker}/chart-data` | OHLCV 캔들 데이터 |
| GET | `/api/technical/{ticker}/fibonacci` | 피보나치 되돌림 레벨 |
| GET | `/api/technical/{ticker}/ichimoku` | 일목균형표 클라우드 |
### 5.5 Earnings (`/api/earnings`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/earnings/{ticker}/history` | EPS Beat/Miss 이력 |
| GET | `/api/earnings/{ticker}/calendar` | 다음 실적 발표일 |
| GET | `/api/earnings/{ticker}/quarterly` | 분기별 매출/순이익 |
| GET | `/api/earnings/{ticker}/transcript` | 어닝콜 트랜스크립트 (FMP 키 필요) |
### 5.6 Research (`/api/research`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/research/dashboard/{ticker}` | 퀀트 대시보드 (F-Score/DuPont/Sankey/Waterfall/Anomaly) |
### 5.7 FMP (`/api/fmp`, 선택)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/fmp/key-metrics/{ticker}` | 히스토리컬 key metrics (키 없으면 Yahoo 스냅샷) |
| GET | `/api/fmp/ratios/{ticker}` | 히스토리컬 ratios (키 없으면 Yahoo 스냅샷) |
### 5.8 Macro (`/api/macro`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/macro/quadrant` | 글로벌 성장 vs 인플레 Z-score 사분면 |
| GET | `/api/macro/yield-fx` | US10Y 스프레드 vs FX (usdjpy\|eurusd\|usdkrw) |
| GET | `/api/macro/smart-money` | Copper/Gold ratio + RORO 복합지수 |
| GET | `/api/macro/fred/{series_id}` | FRED 시계열 (공개 CSV) |
| GET | `/api/macro/oecd/mei` | OECD MEI (빈 배열 — API 변경 대비) |
| GET | `/api/macro/oecd/cli` | OECD CLI 스냅샷 (DBnomics) |
| GET | `/api/macro/snapshot` | 매크로 사이클 히트맵 (국가, 자산, 밸류에이션) |
| GET | `/api/macro/korea` | 한국 경제 지표 (ECOS or yfinance 폴백) |
| GET | `/api/macro/economic-calendar` | 경제 캘린더 (스크래핑) |
| GET | `/api/macro/ecos` | ECOS 직접 호출 (`ECOS_API_KEY`) |
| GET | `/api/macro/calendar` | 경제 캘린더 — FMP (`FMP_API_KEY`) |
### 5.9 DART (`/api/dart`, 선택)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/dart/search?q=` | 상장사 이름 검색 (`DART_API_KEY`) |
| GET | `/api/dart/sections/{ticker}` | 최신 사업보고서 → SEC 유사 5섹션 + HTML (`.KS` / `.KQ`) |
### 5.10 EDINET (`/api/edinet`, 선택)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/edinet/links/{ticker}` | EDINET 포털 링크 (키 없이 사용, `7203.T`) |
| GET | `/api/edinet/sections/{ticker}` | 有価証券報告書 섹션 (`EDINET_SUBSCRIPTION_KEY` 없으면 링크만) |
### 5.11 SEC EDGAR (`/api/edgar`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/edgar/sections/{ticker}` | 10-K 섹션별 텍스트 (1A, 3, 7, 8, 9A) |
| GET | `/api/edgar/item7/{ticker}` | Item 7 MD&A 텍스트만 |
| GET | `/api/edgar/compare/{ticker}` | 최신 vs 3년전 Item 7 비교 |
### 5.12 Insider (`/api/insider`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/insider/{ticker}` | 최근 내부자 거래 |
| GET | `/api/insider/{ticker}/holders` | 기관투자자 보유 현황 |
### 5.13 News (`/api/news`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/news/{ticker}` | Finviz(스크랩) + Google RSS + Yahoo Finance RSS |
| GET | `/api/news/{ticker}/sentiment` | 뉴스 감성 분석 |
### 5.14 Screener (`/api/screener`)
| Method | Path | 설명 |
|--------|------|------|
| POST | `/api/screener/search` | 종목 스크리너 (PE, 섹터, 배당 필터) |
| POST | `/api/screener/backtest` | 전략 백테스트 (SMA/RSI/Buy&Hold) |
### 5.15 Markets (`/api/markets`)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/markets/heatmap/{index_name}` | 지수 구성종목 히트맵 (S&P/NASDAQ/KOSPI/FTSE) |
### 5.16 기타
| Prefix | 설명 |
|--------|------|
| `/api/analysis` | Gemini AI 분석 (strategy/risks/mda/forensic/financials) |
| `/api/chat` | AI Copilot (stream/complete/suggested/configure) |
| `/api/crypto` | 암호화폐 시세 |
| `/api/fx` | 환율 |
| `/api/estimates` | 애널리스트 추정치 (consensus/history/growth) |
| `/api/portfolio` | 포트폴리오 CRUD + Risk + OCR + Screenshot |
---
## 6. Frontend Pages (전체 12개)
| 경로 | 파일 | 핵심 기능 |
|------|------|----------|
| `/` | `page.tsx` | **Multi-Asset Overview** — 티커 자동감지 → Equity(섹터/DuPont/Altman Z/KPI/Peer)/ETF(보유종목/섹터비중)/Commodity(계절성/상관) |
| `/research` | `research/page.tsx` | **리서치 그리드** — F-Score 이력, DuPont Tree, Sankey(손익흐름), Waterfall(영업이익), YoY 이상치+Gemini 설명 |
| `/valuation` | `valuation/page.tsx` | **5-Tab**: DCF(3시나리오), Sensitivity Matrix(WACC×TG), Monte Carlo(히스토그램), Tornado, Reverse DCF |
| `/technical` | `technical/page.tsx` | TradingView 캔들(lightweight-charts), RSI/MACD/ATR 카드, 이동평균, Bollinger, Fibonacci, Ichimoku |
| `/markets` | `markets/page.tsx` | 재무제표 테이블(YoY Growth/Margin) + **섹터 히트맵**(S&P/NASDAQ/KOSPI/FTSE) |
| `/macro` | `macro/page.tsx` | **5탭**(FRED/Cycle Heatmap/OECD CLI/Korea/Calendar) + **Quadrant**(성장vs인플레) + **YieldFX** + **SmartMoney**(Copper/Gold+RORO) |
| `/earnings` | `earnings/page.tsx` | 다음 실적일, EPS Beat/Miss 바차트, 분기 매출/순이익 |
| `/news` | `news/page.tsx` | Split-view — 좌측 기사 리스트(340px) + 우측 iframe 원문 보기 |
| `/screener` | `screener/page.tsx` | **종목 스크리너**(PE/섹터/배당 필터) + **전략 백테스트**(SMA/RSI/Buy&Hold, 캔들차트 시각화) |
| `/portfolio` | `portfolio/page.tsx` | 포지션 CRUD + Risk Metrics(VaR/Sharpe/MDD) + OCR 스크린샷 |
| `/filings` | `filings/page.tsx` | **관할권 자동분기** — 티커 접미사로 SEC/DART(`.KS`/`.KQ`)/EDINET(`.T`), 5탭 + AI Summary |
| `/settings` | `settings/page.tsx` | Gemini API Key, SEC Email 설정 |
---
## 7. Ticker State Management
**전역 티커 상태**는 React Context 없이 `localStorage` + `CustomEvent` 패턴으로 관리:
```tsx
// apps/web/src/app/lib/use-ticker.ts
export function useTicker() {
const [ticker, setTicker] = useState(() =>
localStorage.getItem("atlas-ticker") || "MSFT"
);
// 다른 컴포넌트의 변경도 감지
useEffect(() => {
const handler = () => setTicker(localStorage.getItem("atlas-ticker") || "MSFT");
window.addEventListener("ticker-changed", handler);
return () => window.removeEventListener("ticker-changed", handler);
}, []);
const updateTicker = (t: string) => {
localStorage.setItem("atlas-ticker", t.toUpperCase());
window.dispatchEvent(new CustomEvent("ticker-changed"));
};
return { ticker, setTicker: updateTicker };
}
```
**사용법**: 모든 페이지에서 `const { ticker } = useTicker();`로 현재 티커 접근.
TickerBar의 검색창에서 `setTicker()`로 전역 변경.
---
## 8. Key Algorithms
### DCF 10Y 2-Stage (`server/services/dcf_engine.py`)
- Stage 1 (Y1-5): `FCF × (1 + growth)^t`
- Stage 2 (Y6-10): growth linearly fades to terminal growth rate
- Terminal Value at Y10: `FCF₁₀ × (1 + TG) / (WACC - TG)`
- Enterprise Value = sum of discounted FCFs + discounted TV
### Reverse DCF (`server/services/dcf_engine.py`)
- scipy `brentq` root-finding: 현재 시가총액을 설명하는 성장률 역산
- `f(g) = DCF(g) - market_cap = 0` 풀기
### Monte Carlo (`server/services/monte_carlo.py`)
- numpy로 5000회 시뮬레이션
- growth, wacc, margin을 정규분포로 샘플링
- 히스토그램 빈 + P(> current price) 계산
### Sensitivity Matrix (`server/services/sensitivity.py`)
- WACC (행) × Terminal Growth (열) 조합별 DCF 결과 매트릭스
- Tornado: 각 변수를 ±20% 변동시켜 가격 영향 범위 계산, 영향력 순 정렬
### DuPont 3-Factor
`ROE = NPM × Asset Turnover × Equity Multiplier`
### Altman Z-Score
`Z = 1.2(WC/TA) + 1.4(RE/TA) + 3.3(EBIT/TA) + 0.6(MC/TL) + 1.0(Sales/TA)`
### Technical Indicators (`server/services/technical_analysis.py`)
- `ta` 라이브러리 사용: RSI, MACD, Bollinger Bands, Ichimoku Cloud, ADX
- `detect_signals()`: MA 크로스, RSI 과매수/과매도, MACD 시그널
- `compute_fibonacci_levels()`: 52주 고/저 기반 되돌림 레벨
---
## 9. Development Rules (가드레일)
### 코드
- TypeScript strict mode (프론트), Python type hints (백엔드)
- 모든 API 호출 try/except; UI에 기술적 에러 노출 금지
- 캐싱: 재무=TTL 300초, 10-K=영구, 환율=TTL 60초
- `"use client"` — 모든 페이지 최상단에 필수 (App Router + hooks)
### 프론트엔드 API 호출 패턴
```tsx
// Next.js rewrites가 /api/* → localhost:8000/api/* 프록시
// 따라서 상대경로로 호출:
fetch(`/api/market/sector/${ticker}`)
fetch(`/api/valuation/dcf`, { method: "POST", body: JSON.stringify(params) })
```
### Gemini API
- 요청당 최대 25,000자, temperature 0.2~0.4
- 429 → 60초 대기 × 3회 재시도
- 스트리밍: MD&A/Risk 분석은 `stream=True`
### yfinance 주의사항
- `earnings_history` 컬럼명: `epsActual`, `epsEstimate`, `surprisePercent` (camelCase)
- `surprisePercent`는 소수 (0.0759 = 7.59%) → 프론트에서 `× 100` 필요
- 날짜는 DataFrame index에 있음 (컬럼 아님) → `str(idx)[:10]`
- 연간 데이터에 TTM 행 혼재 가능 → `_filter_annual()` 적용
### 서버 실행
```bash
# 백엔드 (포트 8000)
cd atlas-terminal
PYTHONPATH="." python3 -m uvicorn server.main:app --port 8000 --host 0.0.0.0
# 프론트엔드 (포트 3000)
cd atlas-terminal/apps/web
npm run dev
```
### Git
- 커밋: `feat:`, `fix:`, `docs:`, `refactor:` 접두사
- 브랜치: `main`, `dev`, `feat/기능명`
---
## 10. Dependencies
### Python (`requirements.txt`)
```
fastapi>=0.110.0 uvicorn[standard]>=0.29.0
pydantic>=2.7.0 google-generativeai>=0.8.0
anthropic>=0.39.0 openai>=1.50.0
beautifulsoup4>=4.12.0 requests>=2.31.0
pandas>=2.0.0 lxml>=4.9.0
python-dotenv>=1.0.0 yfinance>=0.2.40
yahooquery>=2.2.0 sec-edgar-downloader>=5.0.0
feedparser>=6.0.0 ta>=0.11.0
dart-fss>=0.4.0 numpy>=1.20.0
scipy>=1.10.0 dbnomics>=1.2.0
aiosqlite>=0.20.0 asyncpg>=0.30.0
pillow>=10.0.0 httpx>=0.27.0
pytest>=8.0.0
```
### Node.js (`apps/web/package.json`)
```
next: 14.2.35 react: ^18
lightweight-charts: ^5.1.0
tailwindcss: ^3.4.1 typescript: ^5
@nivo/sankey: ^0.99.0 @nivo/bar: ^0.99.0
recharts: ^2.15.4
```
---
## 11. Environment Variables
```env
GOOGLE_API_KEY= # Gemini API
SEC_EDGAR_EMAIL= # SEC 정책 필수 (10-K 다운로드용)
DATABASE_URL= # PostgreSQL (없으면 SQLite 자동)
NEWS_API_KEY= # 선택
FMP_API_KEY= # Financial Modeling Prep (선택 — 비율·트랜스크립트·캘린더)
ECOS_API_KEY= # 한국은행 ECOS (선택)
DART_API_KEY= # 금융감독원 Open DART (선택 — DART 사업보고서)
EDINET_SUBSCRIPTION_KEY= # 일본 금융청 EDINET API v2 (선택 — 有価証券報告書)
```
---
## 12. 알려진 이슈 및 주의사항
1. **`apps/web/app/` vs `apps/web/src/app/`**: 구 TanStack Start의 `app/` 디렉토리가 `_legacy_tanstack_app`으로 이름변경됨. Next.js는 `src/app/`을 사용. 절대 루트의 `app/` 디렉토리를 만들지 말 것.
2. **Financial 데이터 혼합**: yahooquery는 12M + TTM 데이터를 섞어 반환할 수 있음. `server/routers/financials.py``_filter_annual()` 함수가 TTM 필터링.
3. **CORS**: `server/main.py`에서 `localhost:3000`, `localhost:3001`, `127.0.0.1:3000` 허용 설정됨.
4. **Google Fonts**: `layout.tsx``<head>`에서 Inter + JetBrains Mono 로드. `<link>` 태그 직접 삽입 방식.
---
## 13. 미구현 기능 (TODO)
- [ ] Widget-based 대시보드 (react-grid-layout) — 미구현, 패키지도 미설치
- [ ] Enhanced AI Copilot — 인용/추론 단계 표시
- [ ] Multi-LLM 시스템 (Gemini + Claude + OpenAI provider abstraction) — `ai/llm_router.py` 스캐폴딩만
- [ ] Extended DuPont 5-Factor 분석 — 현재 3-Factor만
- [x] DART 사업보고서 Filings 연동 (`/api/dart/sections/{ticker}`, `dart_filing_service`)
- [x] EDINET 링크 + 선택적 본문 (`/api/edinet/sections|links`, `EDINET_SUBSCRIPTION_KEY`)
- [x] Sankey 차트 (`research/SankeyWidget.tsx` + `@nivo/sankey`)
- [x] Radar 차트 (`/api/market/radar/{ticker}` 엔드포인트)
- [x] 종목 스크리너 + 전략 백테스트 (`/screener` 페이지)
- [x] Multi-Asset Overview — Equity/ETF/Commodity 자동분기
- [x] Macro 페이지 — FRED/Cycle/OECD/Korea/Calendar + Quadrant/YieldFX/SmartMoney
- [x] Research 대시보드 — F-Score/DuPont Tree/Sankey/Waterfall/Anomaly 그리드
- [x] 관할권 자동분기 Filings — SEC/DART/EDINET 티커 접미사 기반
- [x] 포트폴리오 OCR 스크린샷 — `/api/portfolio/screenshot` 엔드포인트 + UI 연결
- [ ] ⌘K 글로벌 커맨드 팔레트
- [ ] Settings 페이지에 FMP/ECOS/DART/EDINET 키 설정 UI 추가
- [ ] GitHub README 자동 업데이트 워크플로우
---
*마지막 수정: 2026-03-26*