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
No description has been provided for this image
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% 투자