In [1]:
import numpy as np
import pandas as pd
import yfinance as yf
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.optimize import minimize
tickers = ["457480.KS", "227560.KS", "453850.KS"]
# (Optional) 컬럼 확인용 다운로드
for ticker in tickers:
ticker_data = yf.download(ticker, start="2024-06-23", end="2025-06-23")
print(f"Columns for {ticker}: {ticker_data.columns}")
# 1) 전체 데이터 다운로드 (조정 종가 사용)
data = yf.download(tickers, period='1y', auto_adjust=True)['Close']
data.columns = tickers # 컬럼 이름 정리
# 2) 수익률 계산
returns = data.pct_change().dropna()
mu_daily = returns.mean()
cov_daily = returns.cov()
# 확인용 출력
print("평균 수익률:")
print(mu_daily)
print("\n공분산 행렬:")
print(cov_daily)
C:\Users\D105-053\AppData\Local\Temp\ipykernel_1132\700770831.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True ticker_data = yf.download(ticker, start="2024-06-23", end="2025-06-23") [*********************100%***********************] 1 of 1 completed C:\Users\D105-053\AppData\Local\Temp\ipykernel_1132\700770831.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True ticker_data = yf.download(ticker, start="2024-06-23", end="2025-06-23")
Columns for 457480.KS: MultiIndex([( 'Close', '457480.KS'),
( 'High', '457480.KS'),
( 'Low', '457480.KS'),
( 'Open', '457480.KS'),
('Volume', '457480.KS')],
names=['Price', 'Ticker'])
[*********************100%***********************] 1 of 1 completed C:\Users\D105-053\AppData\Local\Temp\ipykernel_1132\700770831.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True ticker_data = yf.download(ticker, start="2024-06-23", end="2025-06-23")
Columns for 227560.KS: MultiIndex([( 'Close', '227560.KS'),
( 'High', '227560.KS'),
( 'Low', '227560.KS'),
( 'Open', '227560.KS'),
('Volume', '227560.KS')],
names=['Price', 'Ticker'])
[*********************100%***********************] 1 of 1 completed
Columns for 453850.KS: MultiIndex([( 'Close', '453850.KS'),
( 'High', '453850.KS'),
( 'Low', '453850.KS'),
( 'Open', '453850.KS'),
('Volume', '453850.KS')],
names=['Price', 'Ticker'])
[*********************100%***********************] 3 of 3 completed
평균 수익률:
457480.KS 0.001268
227560.KS -0.000165
453850.KS 0.002117
dtype: float64
공분산 행렬:
457480.KS 227560.KS 453850.KS
457480.KS 0.000161 -0.000003 0.000073
227560.KS -0.000003 0.000091 -0.000004
453850.KS 0.000073 -0.000004 0.001525
In [3]:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
In [21]:
import numpy as np
from scipy.optimize import minimize
tickers = ["457480.KS", "227560.KS", "453850.KS"]
num_assets = len(tickers)
# 예시 수익률(mu)와 공분산 행렬(cov)
mu = np.array([ 0.001268, -0.000165, 0.002117]) # 기대 수익률
cov = np.array([
[ 0.000161, -0.000003, 0.000073],
[-0.000003, 0.000091, -0.000004],
[0.000073, -0.000004, 0.001525]
])
risk_free_rate=0.0419/252
def negative_sharpe(weights, mu, cov, risk_free_rate):
"""
샤프 비율의 음수를 반환 (최대화를 위해 minimize에서 사용)
"""
port_return = np.dot(weights, mu)
port_volatility = np.sqrt(np.dot(weights.T, np.dot(cov, weights)))
# 0으로 나누기 방지
if port_volatility == 0:
return np.inf
sharpe_ratio = (port_return - risk_free_rate) / port_volatility
return -sharpe_ratio
# 초기 가중치
initial_weights = np.array(num_assets * [1. / num_assets])
# 제약조건: 가중치 합계 = 1
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
# 경계: 각 자산의 비중은 0~1
bounds = tuple((0, 1) for _ in range(num_assets))
# minimize
result = minimize(negative_sharpe,
initial_weights,
args=(mu, cov, risk_free_rate), # 무위험 수익률
method='SLSQP',
bounds=bounds,
constraints=constraints)
# 결과 출력
if result.success:
print("최적 포트폴리오 가중치:", result.x)
else:
print("최적화 실패:", result.message)
최적 포트폴리오 가중치: [8.68746550e-01 3.44776291e-17 1.31253450e-01]
In [ ]:
#첫 번째 자산 (457480.KS)에 약 86.9% 투자
#두 번째 자산 (227560.KS)에 거의 0% 투자 (3.4e-17는 사실상 0)
#세 번째 자산 (453850.KS)에 약 13.1% 투자