Toggle navigation
Toggle navigation
This project
Loading...
Sign in
박하늘
/
stock_chatbot
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
ZuseongZIN
2021-06-02 23:08:23 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
8f964b4e79aaf83df1c22d8b39520eeb014eef6b
8f964b4e
1 parent
66578ae2
feature add: portfoliio optimization , 투자 전략 구현
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
202 additions
and
9 deletions
pyfiles/optimizer.py
pyfiles/workspace.ipynb
pyfiles/optimizer.py
View file @
8f964b4
...
...
@@ -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
r
p
.
x
#, RC(self.cov, rp.x)
result
=
dict
(
zip
(
self
.
asset_name
,
np
.
round
(
rp
.
x
,
3
)))
return
r
esult
#, RC(self.cov, rp.x)
\ No newline at end of file
...
...
pyfiles/workspace.ipynb
View file @
8f964b4
...
...
@@ -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"
:
{
...
...
Please
register
or
login
to post a comment