본문 바로가기
코딩 공부/python

파이썬으로 효율적 투자선 그리기와 최적의 포트폴리오 찾기

by Camel_coding_food 2022. 2. 28.
반응형

 

이번에는 효율적인 투자선을 그리고, 그 투자선 위의 가장 효율적인 포트폴리오를 찾아보겠습니다.

 


일단 효율적인 투자선이 무엇인지 알아보겠습니다.

 

 

위 사진에 보이는 곡선이 '효율적 투자선'입니다.

 

그래프의 x, y축은 각각 리스크와 기대 수익률입니다.

 

이 이론을 창립하신 분은 노벨상을 받았을 정도로 복잡한 이론이지만,

간단히 말하자면

저 효율적 투자선에 가까이에 있는 포트폴리오일수록 리스크 대비 수익률이 좋다는 이론입니다.

 

이런 방식으로 각 포트폴리오의 리스크와 기대 수익률을 구할 수 있습니다.

계산하기 어렵습니다.

 

'파이썬 증권데이터분석' 책을 참고하여 파이썬을 이용해

정해진 4개의 기업으로 구성된 20000개의 랜덤 자산비율 포트폴리오를 이용하여

최적의 포트폴리오를 그중에서 찾아보겠습니다.

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import MarketDB2

mk = MarketDB2.MarketDB()
#제가 안올린 파트에서 만든 MarketDB2 모듈의 MarketDB 함수입니다. 위에서 설치해줍니다. 

stock = ['005930','000660','005380','035420']
#저는 삼성전자 SK하이닉스, 현대차, 네이버를 포트폴리오에 적용하겠습니다.
#stock이라는 리스트에 종목을 저장합니다.

df = pd.DataFrame()
#판다스의 데이터프레임 읽기를 이용합니다.

for s in stock:
    df[s] = mk.getDailyPrice(s, '2020-02-10','2022-02-25')['close']
    #제가 만든 모듈 속 함수를 이용하여 s에 할당된 종목의 지정일 동안의 주가 움직임을 가져옵니다.

daily_ret=df.pct_change()
#판다스 속의 함수를 이용해 4일간(지정일) 종목별 변동성을 구해줍니다.

annual_ret=daily_ret.mean() * 252
#4일간 변동성의 평균을 내어 주식 개장일 252일을 곱하여 1년 변동률을 구한다.
#반드시 이 변동률이 맞지는 않는다.

daily_cov=daily_ret.cov()
#변동률의 공분산으로 일간 리스크를 구한다.

annual_cov=daily_cov * 252
#연간 리스크를 구한다.

port_ret = []
port_risk = []
port_weights = []
sharpe_ratio =[]
#각 정보를 저장한 리스트를 생성해놓는다.

# 몬테카를로 시뮬레이션 코드 시작.
for _ in range(20000):
# _ 는 반복되지 않을 for문을 사용할 때 써준다. 포트폴리오 개수는 20000개로 지정한다.
    weights = np.random.random(len(stock))
    #numpy 속의 함수를 이용하여 포트폴리오에 포함되는 기업의 개수와 동일한 개수의
    #랜덤한 숫자를 만든다.
    
    weights /= np.sum(weights)
    #각 종목의 비중을 더했을때 1이 되도록 비중을 분배한다.
    
    returns = np.dot(weights, annual_ret)
    #램덤한 종목별 비중에 아까 구한 연간수익률을 곱하여 전체 수익률을 구한다.
    
    risk = np.sqrt(np.dot(weights.T, np.dot(annual_cov,weights)))
    #포트폴리오 리스크를 구한다. 
    #np.dot은 numpy 모듈속 dot 함수를 이용하는 것으로, .T은 정보를 전치행렬로 만들어주는 기능이며,
    #dot함수를 이용하여 행렬 계산을 해준다.
    
    port_ret.append(returns)
    port_risk.append(risk)
    port_weights.append(weights)
    sharpe_ratio.append(returns/risk)
    #리스트에 지금까지 구한 모든 정보를 추가한다.

portfolio = {'Returns': port_ret, 'Risk': port_risk, 'Sharpe':sharpe_ratio}
#포트폴리오 형식을 만든다.

for i, s  in enumerate(stock):
#enumerate는 종목의 각 코드의 인덱스 번호를 붙입니다.
    portfolio[s] = [weight[i] for weight in port_weights]

df = pd.DataFrame(portfolio)
df = df[['Returns','Risk', 'Sharpe'] + [s for s in stock]]
#df 데이터프레임을 지정한다.

 

블로그에 있는 코드를 Ctrl C + V 하다보면

unexpected indent 오류가 발생하는 경우가 있습니다.

 

처음 마주하면 엄청 당황스럽습니다.

 

VScode 자체의 오류인지는 모르겠으나

보통 저런 오류가 발생했을때는

코드상의 모든 엔터키를 없애면 해결되는 경우가 많습니다.

 

 

저 코드를 모두 완성하고나면

portfolio, anual_cov, daily_cov 등 지정한 변수를 입력해 값을 출력할 수 있는데,

아까 랜덤 포트폴리오를 2만개로 설정하셨다면

portfolio는 실험삼아 출력하지 않으시길 바랍니다.

 

portfolio 함수에 어떤 내용이 들어가는지 궁금하시다면 

 

for _ in range() 의 괄호 안에 적당히 작은 숫자를 입력하고 테스트해보길 추천합니다.

 

여기까지하고 출력해보면 

 

 

이런식으로 나옵니다.

 

다음번에는 구한 포트폴리오를 모두 그래프 상에 옮겨보겠습니다.

 

 

반응형

댓글