본문 바로가기
딥러닝 어쩌구/연구일지&디버깅

Portfolio Optimization - PyPortfolioOpt (1)

by 포숑은 맛있어 2021. 7. 30.
반응형

https://github.com/robertmartin8/PyPortfolioOpt/commits?author=robertmartin8   git

https://pyportfolioopt.readthedocs.io/en/latest/  official document

 

Efficient Frontier?

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gdpresent&logNo=220890967416        

Harry Markowitz의 이론인데, 1952년도 논문이라 되게 오래 되었다. 금융쪽 비전공자인 나도 포트폴리오 이론이니, CAPM이나 CAL같은건 어디서 주워들어봤으니까 완전 기초중의 기초일 것 같다. 저 분야에서 바이블인가?

 

 

뜬금없이 이걸 셋업하게된 계기는 최근에 arxiv sanity에 top recent 1주 기준으로 흥미롭고 따끈한 논문이 나왔기 때문이다.

http://arxiv.org/pdf/2107.11371v1.pdf

요즘 transformer 뇌절이 가득한 아카이브에 Portfolio optimization problem이 뜨는건 처음 봤다! 인도 주식에 적용했다고.

뭔가 나같은 인간들이 울면서 서베이하러 왔다가 주식얘기보고 신나서 클릭한게 틀림없다.

암튼 이 논문에서 Markowitz의 mean-variance portfolio를 비교언급하고 있어서, 본 논문을 보기 전에 고전을 좀 알고 봐야할것같아서 빠르게 서베이 해봤음.

이 논문은 PCA 쓴 것 같은데. ML 카테고리에 들어가있고 역시나 코드 공개는 안한걸로 보여서 기초라도 한번 돌려보고 가려고 함. 필요하면 구현해야지

 

 

중간에 모듈 없다는 에러 뜬건 

pip install cvxpy

pip install cvxopt

해서 해결. 뭐 solver 모듈 없는 에러같음.

 

 

파일을 읽고, 포트폴리오를 구성한 후에 투자금액에 맞춰서 (데이터의 가장 최근 주가 기준) 몇주를 사야하는지 계산하는 코드이다.

 

max_sharpe()를 통해 얻은 weights를 확인하면, 텍스트파일에 있는 몇 주식을 가지고 효율적인 포트폴리오를 구성한다.

저게 tangent portfolio를 구성하는건데 각 주식 비중들. 무위험이자율은 기본으로 2%로 되어있다.

L2 Regularization을 constraint로 추가.

 

여기선 종목 몇개만 뽑아서 했는데, 종목 많이 합치면 optimization problem 풀 수 있긴 한건가...? 으으;;

몇가지 아이디어가 있으니 집가서 적용해봐야겠다.

 

import pandas as pd
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns

from pypfopt import objective_functions


def print_orderdict(dict, postfix='%', space=8, title='', line=5):
    print(title)
    idx = 0
    for i in dict:
        idx += 1
        if postfix=='%':
            num = str(round(dict[i]*100, 2))
        else:
            num = str(dict[i])
        print(i.ljust(6), (num+postfix).rjust(space), end=" | ")
        if idx % line == 0:
            print()

# Read in price data
df = pd.read_csv("tests/resources/stock_prices.csv", parse_dates=True, index_col="date")

# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

ef = EfficientFrontier(mu, S)
ef.add_objective(objective_functions.L2_reg, gamma=0.1)
w = ef.max_sharpe()

print("Portfolio Optimization")
print("Based on Efficient Frontier with L2 regulzariztion")
#print(ef.clean_weights())

print_orderdict(ef.clean_weights(), title="** Optimal Weights **")

############ post-processing
print()
from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices


money = 20000.0
latest_prices = get_latest_prices(df)
da = DiscreteAllocation(w, latest_prices, total_portfolio_value=money)
allocation, leftover = da.lp_portfolio()

buy = 0
for k  in allocation:
    buy += latest_prices[k] * allocation[k]
print("Total Asset: ", money)
print("Total buy: ", buy, ", leftover:", money - buy)
print_orderdict(allocation, 
                postfix=" stk",
                title="** Optimal Weights **")

 

실행하면 대충 이렇다.

귀찮아서 안붙였는데 Total Asset같은 저 숫자들은 달러 기준이다.

반응형

댓글