commit 0b894494724edc0f78f143e2afe594322c4822b0 Author: zephyrdark Date: Mon Feb 2 22:35:58 2026 +0900 Add galaxy-po design document Comprehensive design for integrated quant portfolio management app combining make-quant-py and pension management features. Co-Authored-By: Claude Opus 4.5 diff --git a/docs/plans/2026-02-02-galaxy-po-design.md b/docs/plans/2026-02-02-galaxy-po-design.md new file mode 100644 index 0000000..9d26449 --- /dev/null +++ b/docs/plans/2026-02-02-galaxy-po-design.md @@ -0,0 +1,587 @@ +# Galaxy-PO 설계 문서 + +## 1. 개요 + +**프로젝트명:** galaxy-po + +**목적:** 개인 투자 관리 + 퀀트 연구/백테스트 통합 웹 애플리케이션 + +**통합 대상:** +- make-quant-py (콴트 매니저): 멀티 팩터, 슈퍼 퀄리티, 슈퍼 밸류 모멘텀 전략 +- 퇴직연금 관리 시스템: ETF 포트폴리오, 리밸런싱 계산, 수익률 추적 + +--- + +## 2. 기술 스택 + +| 영역 | 기술 | +|------|------| +| Frontend | Next.js 15, React 19, TypeScript, Tailwind CSS, Node.js 24 | +| Backend | FastAPI, SQLAlchemy, Alembic, APScheduler, Python 3.14 | +| Database | PostgreSQL 15 | +| Infrastructure | Docker, Docker Compose | +| Data Sources | KRX, pykrx, DART OpenAPI, 한국투자증권 OpenAPI | + +--- + +## 3. 프로젝트 구조 + +``` +galaxy-po/ +├── backend/ # FastAPI 백엔드 +│ ├── app/ +│ │ ├── api/ # API 라우터 +│ │ │ ├── auth.py # 인증 +│ │ │ ├── portfolio.py # 포트폴리오 관리 +│ │ │ ├── rebalance.py # 리밸런싱 계산 +│ │ │ ├── strategy.py # 퀀트 전략 +│ │ │ ├── backtest.py # 백테스트 +│ │ │ └── market.py # 시세 조회 +│ │ ├── core/ # 핵심 설정 +│ │ ├── models/ # SQLAlchemy 모델 +│ │ ├── schemas/ # Pydantic 스키마 +│ │ ├── services/ # 비즈니스 로직 +│ │ │ ├── data_collector.py +│ │ │ ├── strategy_engine.py +│ │ │ └── backtest_engine.py +│ │ └── main.py +│ ├── jobs/ # 배치 작업 +│ │ ├── scheduler.py +│ │ ├── collectors/ +│ │ │ ├── base.py +│ │ │ ├── stock_collector.py +│ │ │ ├── sector_collector.py +│ │ │ ├── price_collector.py +│ │ │ ├── valuation_collector.py +│ │ │ ├── financial_collector.py +│ │ │ └── etf_collector.py +│ │ └── tasks.py +│ ├── requirements.txt +│ └── Dockerfile +├── frontend/ # Next.js 프론트엔드 +│ ├── src/ +│ │ ├── app/ # App Router (페이지) +│ │ ├── components/ # React 컴포넌트 +│ │ └── lib/ # 유틸리티, API 클라이언트 +│ ├── package.json +│ └── Dockerfile +├── docker-compose.yml +└── docs/ + └── plans/ +``` + +--- + +## 4. 데이터베이스 모델 + +### 4.1 퀀트 데이터 (배치 수집) + +#### stocks (종목 마스터) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| name | VARCHAR | 종목명 | +| market | VARCHAR | 시장구분 (KOSPI/KOSDAQ) | +| close_price | DECIMAL | 종가 | +| market_cap | BIGINT | 시가총액 | +| eps | DECIMAL | EPS | +| forward_eps | DECIMAL | 선행EPS | +| bps | DECIMAL | BPS | +| dividend_per_share | DECIMAL | 주당배당금 | +| stock_type | VARCHAR | 종목구분 (common/spac/preferred/reit) | +| base_date | DATE | 기준일 | + +#### sectors (섹터 분류) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| sector_code | VARCHAR | 섹터코드 (IDX_CD) | +| company_name | VARCHAR | 종목명 | +| sector_name | VARCHAR | 섹터명 | +| base_date | DATE | 기준일 | + +#### valuations (밸류 지표) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| base_date | DATE (PK) | 기준일 | +| per | DECIMAL | PER | +| pbr | DECIMAL | PBR | +| psr | DECIMAL | PSR | +| pcr | DECIMAL | PCR | +| dividend_yield | DECIMAL | 배당수익률 | + +#### prices (가격 데이터) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| date | DATE (PK) | 날짜 | +| open | DECIMAL | 시가 | +| high | DECIMAL | 고가 | +| low | DECIMAL | 저가 | +| close | DECIMAL | 종가 | +| volume | BIGINT | 거래량 | + +#### financials (재무제표) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| base_date | DATE (PK) | 기준일 | +| report_type | VARCHAR (PK) | 공시구분 (annual/quarterly) | +| account | VARCHAR (PK) | 계정명 | +| value | DECIMAL | 값 | + +**account 값 매핑:** +- revenue, gross_profit, operating_income, net_income +- total_assets, total_equity, total_liabilities +- operating_cash_flow, depreciation, interest_expense +- income_tax, cash, current_assets, current_liabilities, non_current_assets + +### 4.2 포트폴리오 관리 + +#### users +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | SERIAL (PK) | ID | +| username | VARCHAR | 사용자명 | +| email | VARCHAR | 이메일 | +| hashed_password | VARCHAR | 해시된 비밀번호 | +| created_at | TIMESTAMP | 생성일 | + +#### portfolios +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | SERIAL (PK) | ID | +| user_id | INTEGER (FK) | 사용자 ID | +| name | VARCHAR | 포트폴리오명 | +| portfolio_type | VARCHAR | 유형 (pension/general) | +| created_at | TIMESTAMP | 생성일 | +| updated_at | TIMESTAMP | 수정일 | + +#### targets (목표 비율) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| portfolio_id | INTEGER (PK, FK) | 포트폴리오 ID | +| ticker | VARCHAR (PK) | 종목코드 | +| target_ratio | DECIMAL | 목표 비율 (%) | + +#### holdings (보유 자산) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| portfolio_id | INTEGER (PK, FK) | 포트폴리오 ID | +| ticker | VARCHAR (PK) | 종목코드 | +| quantity | INTEGER | 보유 수량 | +| avg_price | DECIMAL | 평균 매수가 | + +#### transactions (거래 내역) +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | SERIAL (PK) | ID | +| portfolio_id | INTEGER (FK) | 포트폴리오 ID | +| ticker | VARCHAR | 종목코드 | +| tx_type | VARCHAR | 거래 유형 (buy/sell) | +| quantity | INTEGER | 수량 | +| price | DECIMAL | 가격 | +| executed_at | TIMESTAMP | 체결일시 | +| memo | TEXT | 메모 | + +#### portfolio_snapshots +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | SERIAL (PK) | ID | +| portfolio_id | INTEGER (FK) | 포트폴리오 ID | +| total_value | DECIMAL | 총 평가금액 | +| snapshot_date | DATE | 스냅샷 날짜 | + +#### snapshot_holdings +| 컬럼 | 타입 | 설명 | +|------|------|------| +| snapshot_id | INTEGER (PK, FK) | 스냅샷 ID | +| ticker | VARCHAR (PK) | 종목코드 | +| quantity | INTEGER | 보유 수량 | +| price | DECIMAL | 당시 가격 | +| value | DECIMAL | 평가 금액 | +| current_ratio | DECIMAL | 당시 비율 (%) | + +### 4.3 ETF (퇴직연금용) + +#### etfs +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| name | VARCHAR | ETF명 | +| asset_class | VARCHAR | 자산군 (equity/bond/gold/mixed) | +| market | VARCHAR | 시장 | +| expense_ratio | DECIMAL | 보수율 | + +#### etf_prices +| 컬럼 | 타입 | 설명 | +|------|------|------| +| ticker | VARCHAR (PK) | 종목코드 | +| date | DATE (PK) | 날짜 | +| close | DECIMAL | 종가 | +| nav | DECIMAL | NAV | +| volume | BIGINT | 거래량 | + +### 4.4 배치 작업 관리 + +#### job_logs +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | SERIAL (PK) | ID | +| job_name | VARCHAR | 작업명 | +| status | VARCHAR | 상태 (running/success/failed) | +| started_at | TIMESTAMP | 시작 시간 | +| finished_at | TIMESTAMP | 종료 시간 | +| records_count | INTEGER | 처리 건수 | +| error_msg | TEXT | 에러 메시지 | + +--- + +## 5. API 엔드포인트 + +### 5.1 인증 +| Method | Endpoint | 설명 | +|--------|----------|------| +| POST | /api/auth/login | 로그인 (JWT 발급) | +| POST | /api/auth/logout | 로그아웃 | +| GET | /api/auth/me | 현재 사용자 정보 | + +### 5.2 포트폴리오 +| Method | Endpoint | 설명 | +|--------|----------|------| +| GET | /api/portfolios | 포트폴리오 목록 | +| POST | /api/portfolios | 포트폴리오 생성 | +| GET | /api/portfolios/{id} | 포트폴리오 상세 | +| PUT | /api/portfolios/{id} | 포트폴리오 수정 | +| DELETE | /api/portfolios/{id} | 포트폴리오 삭제 | +| GET | /api/portfolios/{id}/targets | 목표 비율 조회 | +| PUT | /api/portfolios/{id}/targets | 목표 비율 설정 | +| GET | /api/portfolios/{id}/holdings | 보유 자산 조회 | +| PUT | /api/portfolios/{id}/holdings | 보유 자산 수정 | +| GET | /api/portfolios/{id}/transactions | 거래 내역 조회 | +| POST | /api/portfolios/{id}/transactions | 거래 기록 추가 | +| GET | /api/portfolios/{id}/snapshots | 스냅샷 목록 | +| POST | /api/portfolios/{id}/snapshots | 스냅샷 생성 | + +### 5.3 리밸런싱 +| Method | Endpoint | 설명 | +|--------|----------|------| +| GET | /api/portfolios/{id}/rebalance | 리밸런싱 계산 | +| POST | /api/portfolios/{id}/rebalance/simulate | 추가 입금 시뮬레이션 | + +### 5.4 시세 +| Method | Endpoint | 설명 | +|--------|----------|------| +| GET | /api/market/stocks/{ticker} | 종목 정보 | +| GET | /api/market/stocks/{ticker}/price | 현재가 (OpenAPI) | +| GET | /api/market/stocks/{ticker}/prices | 과거 시세 (DB) | +| GET | /api/market/etfs/{ticker} | ETF 정보 | +| GET | /api/market/etfs/{ticker}/price | ETF 현재가 | +| GET | /api/market/search?q= | 종목 검색 | + +### 5.5 퀀트 전략 +| Method | Endpoint | 설명 | +|--------|----------|------| +| POST | /api/strategy/multi-factor | 멀티 팩터 전략 | +| POST | /api/strategy/quality | 슈퍼 퀄리티 전략 | +| POST | /api/strategy/value-momentum | 슈퍼 밸류 모멘텀 전략 | + +### 5.6 백테스트 +| Method | Endpoint | 설명 | +|--------|----------|------| +| POST | /api/backtest | 백테스트 실행 | + +### 5.7 데이터 수집 (관리자) +| Method | Endpoint | 설명 | +|--------|----------|------| +| POST | /api/admin/collect/stocks | 종목 마스터 수집 | +| POST | /api/admin/collect/sectors | 섹터 정보 수집 | +| POST | /api/admin/collect/prices | 가격 데이터 수집 | +| POST | /api/admin/collect/financials | 재무제표 수집 | +| POST | /api/admin/collect/valuations | 밸류 지표 수집 | +| GET | /api/admin/collect/status | 수집 작업 상태 | + +--- + +## 6. 프론트엔드 페이지 + +| 경로 | 설명 | +|------|------| +| / | 대시보드 | +| /login | 로그인 | +| /portfolio | 포트폴리오 목록 | +| /portfolio/[id] | 포트폴리오 상세 | +| /portfolio/[id]/rebalance | 리밸런싱 계산 | +| /portfolio/[id]/history | 스냅샷/수익률 히스토리 | +| /portfolio/new | 새 포트폴리오 생성 | +| /strategy | 퀀트 전략 메인 | +| /strategy/multi-factor | 멀티 팩터 전략 | +| /strategy/quality | 슈퍼 퀄리티 전략 | +| /strategy/value-momentum | 슈퍼 밸류 모멘텀 전략 | +| /backtest | 백테스트 | +| /backtest/result/[id] | 백테스트 결과 | +| /market | 시세 조회 | +| /market/[ticker] | 종목 상세 | +| /admin/data | 데이터 수집 관리 | + +--- + +## 7. 데이터 배치 수집 + +### 7.1 수집 대상 및 소스 + +| 데이터 | 소스 | 수집 주기 | +|--------|------|-----------| +| stocks | KRX (data.krx.co.kr) | 매일 18:00 | +| sectors | WISEindex | 매일 18:00 | +| prices | pykrx / KRX | 매일 18:00 | +| valuations | KRX | 매일 18:00 | +| financials | DART OpenAPI | 분기별 | +| etf_prices | pykrx | 매일 18:00 | + +### 7.2 스케줄러 설정 (APScheduler) + +```python +jobs: + - id: daily_stock_data + func: collect_stocks_and_sectors + trigger: cron, hour=18, minute=0, day_of_week=mon-fri + + - id: daily_prices + func: collect_prices + trigger: cron, hour=18, minute=30, day_of_week=mon-fri + + - id: daily_valuations + func: collect_valuations + trigger: cron, hour=19, minute=0, day_of_week=mon-fri + + - id: quarterly_financials + func: collect_financials + trigger: cron, month=1,4,7,10, day=15 +``` + +--- + +## 8. 퀀트 전략 엔진 + +### 8.1 팩터 계산 + +**밸류 팩터:** +- PER 역수 (1/PER) +- PBR 역수 (1/PBR) +- PSR 역수 (1/PSR) +- PCR 역수 (1/PCR) +- 배당수익률 + +**퀄리티 팩터:** +- ROE = 당기순이익 / 자본 +- GP/A = 매출총이익 / 자산 +- 영업현금흐름 / 자산 +- 부채비율 역수 + +**모멘텀 팩터:** +- 12개월 수익률 +- 6개월 수익률 +- 최근 1개월 제외 11개월 수익률 + +**F-Score (9점 만점):** +- 수익성: ROA, CFO, ΔROA, Accrual (4점) +- 재무건전성: ΔLeverage, ΔLiquidity, Equity (3점) +- 운영효율성: ΔMargin, ΔTurnover (2점) + +### 8.2 전략 실행 흐름 + +1. 유니버스 필터 (시장, 시가총액, 종목구분) +2. 팩터별 z-score 계산 +3. 가중치 적용하여 종합 점수 산출 +4. 순위 정렬 후 상위 N개 반환 + +### 8.3 백테스트 엔진 + +**입력:** +- strategy: 전략 종류 및 파라미터 +- start_date, end_date: 테스트 기간 +- rebalance_period: 리밸런싱 주기 (월별/분기별) +- initial_capital: 초기 자본 + +**출력:** +- total_return: 총 수익률 +- cagr: 연평균 수익률 +- mdd: 최대 낙폭 +- sharpe_ratio: 샤프 비율 +- holdings_history: 기간별 보유 종목 +- equity_curve: 자산 추이 + +--- + +## 9. Docker 구성 + +### 9.1 docker-compose.yml + +```yaml +version: '3.8' + +services: + postgres: + image: postgres:15 + environment: + POSTGRES_USER: galaxy + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: galaxy_po + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + + backend: + build: ./backend + environment: + DATABASE_URL: postgresql://galaxy:${DB_PASSWORD}@postgres:5432/galaxy_po + KIS_APP_KEY: ${KIS_APP_KEY} + KIS_APP_SECRET: ${KIS_APP_SECRET} + JWT_SECRET: ${JWT_SECRET} + ports: + - "8000:8000" + depends_on: + - postgres + + frontend: + build: ./frontend + environment: + NEXT_PUBLIC_API_URL: http://backend:8000 + ports: + - "3000:3000" + depends_on: + - backend + +volumes: + postgres_data: +``` + +### 9.2 Dockerfile (Backend) + +```dockerfile +FROM python:3.14-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +### 9.3 Dockerfile (Frontend) + +```dockerfile +FROM node:24-alpine + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . +RUN npm run build + +CMD ["npm", "start"] +``` + +### 9.4 환경 변수 (.env) + +``` +# Database +DB_PASSWORD=your_secure_password + +# JWT +JWT_SECRET=your_jwt_secret_key + +# 한국투자증권 OpenAPI +KIS_APP_KEY=your_kis_app_key +KIS_APP_SECRET=your_kis_app_secret +KIS_ACCOUNT_NO=your_account_number + +# DART OpenAPI +DART_API_KEY=your_dart_api_key +``` + +--- + +## 10. 구현 순서 + +### Phase 1: 기반 구축 +1. 프로젝트 초기화 (backend/frontend 구조) +2. Docker Compose 설정 +3. PostgreSQL + DB 모델 정의 +4. FastAPI 기본 구조 + 인증 (JWT) +5. Next.js 기본 구조 + 레이아웃 + +### Phase 2: 데이터 수집 +6. 데이터 수집기 구현 (stocks, sectors, prices) +7. 배치 스케줄러 설정 +8. 관리자 데이터 수집 UI + +### Phase 3: 포트폴리오 관리 +9. 포트폴리오 CRUD API +10. 목표 비율 / 보유 자산 관리 +11. 거래 내역 기록 +12. 리밸런싱 계산 로직 +13. 포트폴리오 UI (대시보드, 상세, 리밸런싱) + +### Phase 4: 퀀트 전략 +14. 팩터 계산 로직 (value, quality, momentum) +15. 전략 엔진 (multi-factor, super-quality, value-momentum) +16. 전략 UI + +### Phase 5: 백테스트 +17. 백테스트 엔진 +18. 백테스트 UI + 결과 시각화 + +### Phase 6: 마무리 +19. 스냅샷 / 수익률 추적 +20. ETF 시세 연동 (OpenAPI) +21. 테스트 / 버그 수정 +22. 배포 + +--- + +## 11. 핵심 의존성 + +### backend/requirements.txt +``` +fastapi +uvicorn +sqlalchemy +alembic +psycopg2-binary +pydantic +python-jose[cryptography] +passlib[bcrypt] +apscheduler +pykrx +requests +beautifulsoup4 +pandas +numpy +``` + +### frontend/package.json (dependencies) +```json +{ + "next": "^15", + "react": "^19", + "typescript": "^5", + "tailwindcss": "^4", + "recharts": "^2", + "axios": "^1", + "zustand": "^5" +} +``` + +--- + +**문서 버전:** 1.0 +**작성일:** 2026-02-02