ZuseongZIN

feature add: portfoliio optimization , 투자 전략 구현

......@@ -5,19 +5,37 @@ import FinanceDataReader as fdr
from scipy.optimize import minimize
import json
#소숫점 표현
pd.options.display.float_format = '{:.3f}'.format
np.set_printoptions(precision=3, suppress=True)
class c_Models:
#Input 값으로, 자산 list, 사용자 포트폴리오 비중, 시작일, 마지막일
def __init__(self, assets, assets_w, start, end):
self.result = None
self.graph = None
stocks = pd.read_csv('stockcodename.csv', index_col=0)
symbol = ''
self.asset_name = assets[:]
for k in range(len(assets)):
for i in enumerate(stocks.Name):
if i[1] == assets[k]:
assets[k] = (stocks.iloc[i[0]].Symbol)
break
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 len(data) == 0 :
data = tmp
else:
data = pd.concat([data,tmp], axis=1)
data.columns = self.asset_name
if data.isnull().values.any() == True: #불러온 data에 오류가 있다면
return "No Data",''
......@@ -39,9 +57,9 @@ class c_Models:
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
result = dict(zip(self.asset_name, np.round(gmv.x,3)))
return result
#Max Sharp ratio : risk free rate은 0.8%로 지정했고,
def ms_opt(self):
......@@ -51,7 +69,8 @@ class c_Models:
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
result = dict(zip(self.asset_name, np.round(maxsharp.x,3)))
return result
def rp_opt(self):
def RC(cov, w):
......@@ -80,5 +99,5 @@ class c_Models:
bd = ((0,1),) * n_assets
rp = minimize(RP_objective, w0, constraints=constraints, bounds = bd, method='SLSQP')
return rp.x #, RC(self.cov, rp.x)
result = dict(zip(self.asset_name, np.round(rp.x,3)))
return result #, RC(self.cov, rp.x)
\ No newline at end of file
......
......@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
......@@ -66,6 +66,180 @@
"stocks = fdr.StockListing('KOSPI') # 코스피\n",
"stocks.to_csv(\"stockcodename.csv\",mode='w', encoding='utf-8-sig')"
]
},
{
"cell_type": "code",
"execution_count": 123,
"metadata": {},
"outputs": [],
"source": [
"import datetime\n",
"import pandas as pd\n",
"import numpy as np\n",
"import FinanceDataReader as fdr\n",
"from scipy.optimize import minimize\n",
"import json\n",
"\n",
"#소숫점 표현\n",
"pd.options.display.float_format = '{:.3f}'.format\n",
"np.set_printoptions(precision=3, suppress=True)\n",
"\n",
"class c_Models:\n",
" #Input 값으로, 자산 list, 사용자 포트폴리오 비중, 시작일, 마지막일\n",
" def __init__(self, assets, assets_w, start, end):\n",
" self.result = None\n",
" self.graph = None\n",
" \n",
" stocks = pd.read_csv('stockcodename.csv', index_col=0)\n",
" symbol = ''\n",
" self.asset_name = assets[:]\n",
" for k in range(len(assets)):\n",
" for i in enumerate(stocks.Name):\n",
" if i[1] == assets[k]:\n",
" assets[k] = (stocks.iloc[i[0]].Symbol)\n",
" break\n",
"\n",
" data = pd.DataFrame()\n",
" # 전체 자산 data들을 가지고 온 후, 정리함\n",
" \n",
" for asset in assets: #total_list:\n",
" tmp = fdr.DataReader(asset,start,end).Close\n",
" if len(data) == 0 :\n",
" data = tmp\n",
" else:\n",
" data = pd.concat([data,tmp], axis=1)\n",
" \n",
" data.columns = self.asset_name\n",
" \n",
" if data.isnull().values.any() == True: #불러온 data에 오류가 있다면\n",
" return \"No Data\",''\n",
"\n",
" else:\n",
" data = data.resample('M').mean() #일별 데이터를 월별 데이터로 만들어줌\n",
" data = data.pct_change() #월별 주가 데이터를 이용해 수익률 데이터로 변환\n",
" data.dropna(inplace=True) #결측치 제외(첫 row)\n",
"\n",
" self.data = data\n",
" self.assets_w = assets_w\n",
" self.mu = data.mean() * 12\n",
" self.cov = data.cov() * 12\n",
"\n",
" #GMV 최적화 : 제약 조건은 비중합=1, 공매도 불가능\n",
" def gmv_opt(self):\n",
" n_assets = len(self.data.columns)\n",
" w0 = np.ones(n_assets) / n_assets\n",
" fun = lambda w: np.dot(w.T, np.dot(self.cov, w))\n",
" constraints = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})\n",
" bd = ((0,1),) * n_assets\n",
" #cov = data.cov() * 12\n",
" gmv = minimize(fun, w0, method = 'SLSQP', constraints=constraints, bounds=bd)\n",
" result = dict(zip(self.asset_name, np.round(gmv.x,3)))\n",
" return result\n",
" \n",
" #Max Sharp ratio : risk free rate은 0.8%로 지정했고, \n",
" def ms_opt(self):\n",
" n_assets = len(self.data.columns)\n",
" w0 = np.ones(n_assets) / n_assets\n",
" fun = lambda w: -(np.dot(w.T, self.mu) - 0.008) / np.sqrt(np.dot(w.T, np.dot(self.cov, w)))\n",
" bd = ((0,1),) * n_assets \n",
" constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})\n",
" maxsharp = minimize(fun, w0, method ='SLSQP', constraints=constraints, bounds=bd)\n",
" result = dict(zip(self.asset_name, np.round(maxsharp.x,3)))\n",
" return result\n",
" \n",
" def rp_opt(self):\n",
" def RC(cov, w):\n",
" pfo_std = np.sqrt(np.dot(w.T, np.dot(self.cov, w)))\n",
" mrc = 1/pfo_std * (np.dot(self.cov, w))\n",
" rc = mrc * w\n",
" rc = rc / rc.sum()\n",
" return rc\n",
" \n",
" \n",
" def RP_objective(x):\n",
" pfo_std = np.sqrt(np.dot(x.T, np.dot(self.cov, x)))\n",
" mrc = 1/pfo_std * (np.dot(self.cov, x))\n",
" rc = mrc * x\n",
" rc = rc / rc.sum()\n",
"\n",
" a = np.reshape(rc, (len(rc),1))\n",
" differs = a - a.T\n",
" objective = np.sum(np.square(differs))\n",
"\n",
" return objective \n",
" \n",
" n_assets = len(self.data.columns)\n",
" w0 = np.ones(n_assets) / n_assets\n",
" constraints = [{'type':'eq', 'fun': lambda x: np.sum(x) -1}]\n",
" bd = ((0,1),) * n_assets\n",
"\n",
" rp = minimize(RP_objective, w0, constraints=constraints, bounds = bd, method='SLSQP')\n",
" result = dict(zip(self.asset_name, np.round(rp.x,3)))\n",
" return result #, RC(self.cov, rp.x)"
]
},
{
"cell_type": "code",
"execution_count": 122,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'삼성전자': 0.727, 'LG전자': 0.0, '카카오': 0.273}"
]
},
"execution_count": 122,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#gmv 포트폴리오 -> 해당 종목을 각각 몇 퍼센트로 투자해야 위험이 제일 적은가\n",
"c_Models(['삼성전자','LG전자','카카오'],[0,0,0],'2015-01-01','2021-04-01').gmv_opt()"
]
},
{
"cell_type": "code",
"execution_count": 124,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'삼성전자': 0.674, 'LG전자': 0.0, '카카오': 0.326}"
]
},
"execution_count": 124,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#maxsharp ratio -> 위험대비 수익률이 제일 좋은 포트폴리오 비중 , 즉 가성비가 좋다\n",
"c_Models(['삼성전자','LG전자','카카오'],[0,0,0],'2015-01-01','2021-04-01').ms_opt()"
]
},
{
"cell_type": "code",
"execution_count": 125,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'삼성전자': 0.443, 'LG전자': 0.238, '카카오': 0.319}"
]
},
"execution_count": 125,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#risk parity -> 포트폴리오에 대한 자산 위험 비중을 동일하게 조정, 즉 삼전,lg,카카오의 포트폴리오 위험 기여도를 0.33으로 하게 만드는 비중\n",
"c_Models(['삼성전자','LG전자','카카오'],[0,0,0],'2015-01-01','2021-04-01').rp_opt()"
]
}
],
"metadata": {
......