투자/생각
[Python] 포트폴리오 최적화
khc9914
2024. 2. 12. 12:36
이전 게시물에서 구했던 VaR들을 가지고 포트폴리오를 최적화해보자.
위험 대비 수익률을 최대화하기 위해선 모든 종목에서 아래의 수식을 만족해야 한다.
하지만, 이번 최적화에서는 수익은 고려하지 않고, 포트폴리오 VaR를 최소화하는 코드를 만들어보자.
이 수식을 만족하면 포트폴리오 VaR이 최소가 된다.
from scipy.optimize import minimize
from scipy.optimize import basinhopping
해당 라이브러리 기능을 로드
def function(잔고평가액):
CORR_function=np.array(CORR)
Vol_function=np.array(Vol_all.iloc[1,:].transpose()*1.65)
return (잔고평가액*Vol_function) @ CORR_function @ (잔고평가액*Vol_function)
bounds=tuple((0.,투자금액) for i in range(len(Data)))
cons={"type":"eq","fun": lambda x:np.sum(x)-투자금액}
Optimization=minimize(function,초기값,method='SLSQP',constraints=cons,bounds=bounds).x
Optimization_잔고평가액=pd.DataFrame(Optimization,index=range(1,len(Data)+1)).astype('int').iloc[:,0]
최소화를 목표로 하는 함수 설정 ('function(잔고평가액)')
'잔고평가액'은 종목들의 현재 투자 금액이고, 이에 각 종목의 변동성(Vol_function)을 곱하면 VaR가 된다.
따라서, Return에 쓰인 수식은 아래 형식을 나타낸다.
'bounds'는 변수들의 값 범위를 설정하는 것으로 투자 금액이 0 이상, 전체 투자 금액 이하가 되도록 설정했다.
투자금액=Data[['통화','잔고평가액']]
투자금액.loc[투자금액['통화']=='USD','잔고평가액']=Data['잔고평가액'].astype('float')*USDKRW
투자금액=투자금액['잔고평가액'].astype('float').sum()
투자금액_평균=투자금액/len(Data)
초기값=np.repeat(투자금액_평균,len(Data))
'cons'는 함수의 제약조건을 설정하는 것으로 모든 투자 금액의 합이 전체 포트폴리오의 투자 금액이 되도록 했다.
'초기값'은 최솟값을 찾을 때 계산을 시작하는 값이다.
전체 포트폴리오의 투자 금액을 종목 개수로 나누어 동일한 금액만큼 투자하도록 해줬다.
실행 결과 각 종목에 얼마만큼 투자하면 포트폴리오 VaR가 최소가 되는지 도출된다.
이 투자 금액을 적용해서 공헌/한계/증분 VaR을 구하면
투자하는 각 종목의 한계 VaR가 동일해진 것을 볼 수 있다.