portfolio-rebalancer
포트폴리오 리밸런싱 제안 — 보유 종목 비중 분석, 목표 비중 대비 차이 계산, 매수/매도 추천
개요
현재 보유 종목과 비중을 분석하고, 목표 비중과의 차이를 계산하여 리밸런싱 제안을 제공합니다. 한국/미국 주식 모두 지원.
데이터 소스
- 한국 주식: pykrx (종가, PER, PBR 등)
- 미국 주식: yfinance (종가, 시가총액 등)
- 시황: invest-memo 스킬의 데이터 활용
포트폴리오 관리
상태 파일
~/.hermes/data/portfolio.json
{
"name": "주인님 포트폴리오",
"updated": "2026-04-12",
"target_allocation": {
"미국 주식": 60,
"한국 주식": 25,
"현금": 15
},
"holdings": [
{
"name": "애플",
"ticker": "AAPL",
"market": "US",
"shares": 10,
"avg_cost": 170.00,
"target_weight": 15,
"notes": "Big Tech 코어"
},
{
"name": "삼성전자",
"ticker": "005930",
"market": "KR",
"shares": 20,
"avg_cost": 70000,
"target_weight": 10,
"notes": "반도체 대표"
}
]
}
실행 단계
1. 현재 가격 조회
기본: yfinance 통일 (권장)
import yfinance as yf미국 주식
aapl = yf.Ticker("AAPL")
price = aapl.history(period="1d")['Close'].iloc[-1]한국 주식 (.KS 접미사 사용 — pykrx 대안)
samsung = yf.Ticker("005930.KS")
price = samsung.history(period="1d")['Close'].iloc[-1]환율
krw = yf.Ticker("KRW=X")
fx_rate = krw.history(period="1d")['Close'].iloc[-1]
pykrx 사용 (선택, Python 3.10+ 권장)
from pykrx import stock
price = stock.get_market_price("005930") # 종가
⚠️ pykrx는 matplotlib 의존성 충돌 가능성이 있음. 문제 발생 시 yfinance .KS 티커로 우회하세요.
2. 현재 비중 계산
- 각 종목: (보유 수량 × 현재가) = 평가금액
- 총 평가금액 기준 비중 계산
- USD/KRW 환율 적용 (yfinance: KRW=X)
3. 목표 대비 차이 분석
- 현재 비중 vs 목표 비중 차이(Δ) 계산
- Δ > +2%: 과대 비중 (매도 권장)
- Δ < -2%: 과소 비중 (매수 권장)
- -2% ≤ Δ ≤ +2%: 적정 범위
4. 리밸런싱 제안 생성
📊 포트폴리오 리밸런싱 제안💰 총 평가금액: ₩XX,XXX,XXX
💵 환율: 1 USD = ₩X,XXX
현재 비중 vs 목표 비중:
━━━━━━━━━━━━━━━━━━━━
애플 (AAPL): 현재 18% → 목표 15% (▲3% 과대)
삼성전자 (005930): 현재 7% → 목표 10% (▼3% 과소)
현금: 현재 20% → 목표 15% (▲5% 과대)
🔧 리밸런싱 액션:
- 📉 애플 일부 매도 — 약 $X,XXX 매도 권장
- 📈 삼성전자 추가 매수 — 약 ₩X,XXX,XXX 매수 권장
- 💵 현금 비중 조정 — 과대 비중은 자연 조정 가능
⚠️ 시황 참고: (invest-memo 최신 데이터 기반 1-2문장)
5. Notion에 기록 (선택)
주인님이 요청하면 포트폴리오 상태를 Notion에 기록. notion 스킬의 API 패턴 사용.
사용 예시
텔레그램에서
- "포트폴리오 현황" → 현재 비중 + 평가금액
- "리밸런싱 제안해줘" → 분석 + 액션 아이템
- "삼성전자 10주 추가 매수" → portfolio.json 업데이트
- "포트폴리오에 NVDA 5주 추가해줘" → 새 종목 추가
크론에서
- 매주 월요일 09:00 자동 리밸런싱 체크 (선택)
Notion API 패턴
import os, json, subprocess
TK_PATH = os.environ.get("NOTION_TOKEN_PATH", os.path.expanduser("~/.hermes/secrets/notion_idea_token.txt"))
with open(TK_PATH) as f:
tk = f.read().strip()
관련 스킬
- stock-market-tracker (시장 데이터)
- invest-memo (시황)
- notion (Notion API)
환경 이슈 대응
pandas/yfinance import 실패 시
venv의 pandas가 손상된 경우 yfinance를 import할 수 없음. 아래 우회 방법 사용:
import json, subprocessdef fetch_price(ticker):
"""yfinance 없이 Yahoo Finance v8 API로 가격 직접 조회"""
url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}?range=5d&interval=1d"
r = subprocess.run(
f'curl -sL "{url}" -H "User-Agent: Mozilla/5.0"',
shell=True, capture_output=True, text=True, timeout=15
)
if r.returncode == 0 and r.stdout:
data = json.loads(r.stdout)
closes = data["chart"]["result"][0]["indicators"]["quote"][0]["close"]
closes = [c for c in closes if c is not None]
if closes:
return closes[-1]
return None
사용: fetch_price("AAPL"), fetch_price("005930.KS"), fetch_price("KRW=X")
pykrx matplotlib 충돌 시
- Python 3.9에서 pykrx 사용 불가 → yfinance
.KS티커로 우회 - 필요시
pip install --force-reinstall pykrx시도
주의사항
- 투자 조언이 아닌 정보 제공 목적
- pykrx는 장시간(15:30~16:00) 데이터 지연 가능
- 환율은 실시간이 아닐 수 있음
- 주말/공휴일에는 최근 영업일 종가 기준
- portfolio.json은 주인님 명시적 요청 시에만 수정
- yfinance venv 충돌 시 위 fetch_price() 함수로 우회