optimizer.py 3.09 KB
import datetime
import pandas as pd
import numpy as np
import FinanceDataReader as fdr
from scipy.optimize import minimize
import json

class c_Models:
    #Input 값으로, 자산 list, 사용자 포트폴리오 비중, 시작일, 마지막일
    def __init__(self, assets, assets_w, start, end):
        self.result = None
        self.graph = None

        data = pd.DataFrame()
        # 전체 자산 data들을 가지고 온 후, 정리함
        for asset in assets: #total_list:
            tmp = fdr.DataReader(asset,start,end).Close
            tmp.rename(columns={'Close': asset}, inplace=True)
            data = pd.concat([data, tmp], axis=1)
        
        if data.isnull().values.any() == True: #불러온 data에 오류가 있다면
            return "No Data",''

        else:
            data = data.resample('M').mean() #일별 데이터를 월별 데이터로 만들어줌
            data = data.pct_change() #월별 주가 데이터를 이용해 수익률 데이터로 변환
            data.dropna(inplace=True) #결측치 제외(첫 row)

            self.data = data
            self.assets_w = assets_w
            self.mu = data.mean() * 12
            self.cov = data.cov() * 12

    #GMV 최적화 : 제약 조건은 비중합=1, 공매도 불가능
    def gmv_opt(self):
        n_assets = len(self.data.columns)
        w0 = np.ones(n_assets) / n_assets
        fun = lambda w: np.dot(w.T, np.dot(self.cov, w))
        constraints = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})
        bd = ((0,1),) * n_assets
        #cov = data.cov() * 12
        
        gmv = minimize(fun, w0, method = 'SLSQP', constraints=constraints, bounds=bd)
        return gmv.x
    
    #Max Sharp ratio : risk free rate은 0.8%로 지정했고, 
    def ms_opt(self):
        n_assets = len(self.data.columns)
        w0 = np.ones(n_assets) / n_assets
        fun = lambda w: -(np.dot(w.T, self.mu) - 0.008) / np.sqrt(np.dot(w.T, np.dot(self.cov, w)))
        bd = ((0,1),) * n_assets     
        constraints = ({'type': 'eq', 'fun': lambda x:  np.sum(x) - 1})
        maxsharp = minimize(fun, w0, method ='SLSQP', constraints=constraints, bounds=bd)
        return maxsharp.x
    
    def rp_opt(self):
        def RC(cov, w):
            pfo_std = np.sqrt(np.dot(w.T, np.dot(self.cov, w)))
            mrc = 1/pfo_std * (np.dot(self.cov, w))
            rc = mrc * w
            rc = rc / rc.sum()
            return rc
        
        
        def RP_objective(x):
            pfo_std = np.sqrt(np.dot(x.T, np.dot(self.cov, x)))
            mrc = 1/pfo_std * (np.dot(self.cov, x))
            rc = mrc * x
            rc = rc / rc.sum()

            a = np.reshape(rc, (len(rc),1))
            differs = a - a.T
            objective = np.sum(np.square(differs))

            return objective    
        
        n_assets = len(self.data.columns)
        w0 = np.ones(n_assets) / n_assets
        constraints = [{'type':'eq', 'fun': lambda x: np.sum(x) -1}]
        bd = ((0,1),) * n_assets

        rp = minimize(RP_objective, w0,  constraints=constraints, bounds = bd, method='SLSQP')

        return rp.x     #, RC(self.cov, rp.x)