이번에는 샤프비율 최적화를 이용해 최소분산포트폴리오의 투자 비중을 구해보자. 최적화를 위한 설정이 동일하거나 비슷하면 목적함수가 달라진다.
샤프비율은 위험 한 단위당 얻을 수 있는 수익의 크기를 의미한다. 앞서 살펴본 최적화는 포트폴리오의 위험을 최소화하는 것인데, 샤프비율은 반대로 최대화해야 한다. scipy.optimize.minimize는 이름 그대로 최소화하는 최적화다. 따라서 목적함수를 ‘’로 작성해 이를 최소화하는 것이 샤프비율을 최대화하는 최적화가 된다.
# 최적화 라이브러리를 임포트한다
from scipy.optimize import minimize
# 목적함수를 선언한다
def obj_sharpe( weights, returns, covmat, rf ):
ret = np.dot( weights, returns )
vol = np.sqrt( np.dot( weights.T, np.dot( covmat, weights ) ) )
return 1 /( ( ret-rf ) / np.sqrt( vol ) )
# 이전과 마찬가지로 종목 개수(n_asset)와 공분산을 준비한다
n_assets = len( tickers )
covmat = cov_daily*250
# 무위험수익률
rf = 0.01
# 초기 투자 비중은 종목 개수만큼 균등하게 정한다
weights = np.ones( [n_assets] ) / n_assets
# 투자 비중의 범위는 0~100%이고 이를 종목 개수만큼 튜플로 만든다
bnds = tuple( ( 0., 1.) for i in range( n_assets ) )
# 앞서 최적화 함수 constraint1(), constraint2()를 정의해 제약식을 만든 방법과 같다
# 제약식은 람다(lambda) 함수로 만든다
cons = ( { 'type': 'eq', 'fun': lambda w: np.sum(w) - 1} )
# minimize( ) 함수에 목적함수, 초기 투자 비중, 투자 비중을 제외한 목적함수에 전달할 나머지 매개변수, 최적화 알고리즘, 범위, 제약조건을 전달한다
res = minimize( obj_sharpe, weights, ( ret_annual, covmat, rf ), method='SLSQP', bounds=bnds, constraints=cons )