Compare commits
4 Commits
4f559443c0
...
8ae20546cd
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ae20546cd | |||
| 0d6b14ca42 | |||
| f713c7b917 | |||
| 4459164fd6 |
28
example/13-2-1-calculate-beta.py
Normal file
28
example/13-2-1-calculate-beta.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import yfinance as yf
|
||||||
|
import pandas as pd
|
||||||
|
import statsmodels.api as sm
|
||||||
|
|
||||||
|
KOSPI_CODE = '^KS11'
|
||||||
|
KIIUM = '039490.KS'
|
||||||
|
# KOSPI 코드(^KS11), 전통적인 고베타주인 증권주 중 키움증권(039490.KS)
|
||||||
|
tickers = [KOSPI_CODE, KIIUM]
|
||||||
|
|
||||||
|
all_data = {}
|
||||||
|
for ticker in tickers:
|
||||||
|
all_data[ticker] = yf.download(ticker, start="2020-01-01", end="2024-12-31")
|
||||||
|
|
||||||
|
# print(all_data)
|
||||||
|
# for tic, data in all_data.items():
|
||||||
|
# print(f"{tic}: {type(data)} -> {type(data['Close'])}")
|
||||||
|
# print(data['Close'])
|
||||||
|
|
||||||
|
# 종가(Close)에 해당하는 열만 선택해서 데이터프레임으로 가공
|
||||||
|
prices = pd.DataFrame({tic: data['Close'].squeeze() for tic, data in all_data.items()})
|
||||||
|
# 수익률 계산(pct_change), NA 데이터 삭제(dropna)
|
||||||
|
ret = prices.pct_change().dropna()
|
||||||
|
|
||||||
|
ret['intercept'] = 1
|
||||||
|
reg = sm.OLS(ret[[KIIUM]], ret[[KOSPI_CODE, 'intercept']]).fit()
|
||||||
|
|
||||||
|
print(reg.summary())
|
||||||
|
print(reg.params)
|
||||||
@ -2,6 +2,7 @@ import pandas as pd
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import quantcommon
|
import quantcommon
|
||||||
|
|
||||||
|
# strategy/value 에서 구현
|
||||||
|
|
||||||
#가치주 포트폴리오. PER, PBR이 낮은 회사 20개
|
#가치주 포트폴리오. PER, PBR이 낮은 회사 20개
|
||||||
# DB 연결
|
# DB 연결
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from urllib.parse import quote_plus
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
import pymysql
|
import pymysql
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
@ -26,3 +27,30 @@ class QuantCommon:
|
|||||||
port=self.port,
|
port=self.port,
|
||||||
db=self.db,
|
db=self.db,
|
||||||
charset='utf8')
|
charset='utf8')
|
||||||
|
|
||||||
|
def get_ticker_list(self):
|
||||||
|
engine = self.create_engine()
|
||||||
|
|
||||||
|
try:
|
||||||
|
ticker_list = pd.read_sql("""
|
||||||
|
select * from kor_ticker
|
||||||
|
where 기준일 = (select max(기준일) from kor_ticker)
|
||||||
|
and 종목구분 = '보통주';
|
||||||
|
""", con=engine)
|
||||||
|
finally:
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
|
return ticker_list
|
||||||
|
|
||||||
|
def get_value_list(self):
|
||||||
|
engine = self.create_engine()
|
||||||
|
|
||||||
|
try:
|
||||||
|
value_list = pd.read_sql("""
|
||||||
|
select * from kor_value
|
||||||
|
where 기준일 = (select max(기준일) from kor_value);
|
||||||
|
""", con=engine)
|
||||||
|
finally:
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
|
return value_list
|
||||||
36
streamlit-quant/strategy/all-value.py
Normal file
36
streamlit-quant/strategy/all-value.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import seaborn as sns
|
||||||
|
|
||||||
|
import quantcommon as qc
|
||||||
|
|
||||||
|
#가치주 포트폴리오. PER, PBR, PCR, PSR, DY
|
||||||
|
def get_all_value_top(count):
|
||||||
|
ticker_list = qc.QuantCommon().get_ticker_list()
|
||||||
|
value_list = qc.QuantCommon().get_value_list()
|
||||||
|
|
||||||
|
# 가치 지표가 0이하인 경우 nan으로 변경
|
||||||
|
value_list.loc[value_list['값'] <= 0, '값'] = np.nan
|
||||||
|
# 가치지표 테이블을 가로로 긴 형태로 변경
|
||||||
|
value_pivot = value_list.pivot(index='종목코드', columns='지표', values='값')
|
||||||
|
# 티커 테이블과 가치 지표 테이블을 합침
|
||||||
|
data_bind = ticker_list[['종목코드', '종목명']].merge(value_pivot,
|
||||||
|
how='left',
|
||||||
|
on='종목코드')
|
||||||
|
value_list_copy = data_bind.copy()
|
||||||
|
# DY(배당수익률)만 높을수록 좋은 지표라서 역수
|
||||||
|
value_list_copy['DY'] = 1 / value_list_copy['DY']
|
||||||
|
value_list_copy = value_list_copy[['PER', 'PBR', 'PCR', 'PSR', 'DY']]
|
||||||
|
value_rank_all = value_list_copy.rank(axis=0)
|
||||||
|
mask = np.triu(value_rank_all.corr())
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(10, 6))
|
||||||
|
sns.heatmap(value_rank_all.corr(),annot=True,mask=mask, annot_kws={"size": 16}, vmin=0, vmax=1, center=0.5,cmap='coolwarm',square=True)
|
||||||
|
ax.invert_yaxis()
|
||||||
|
# plt.show()
|
||||||
|
value_sum_all = value_rank_all.sum(axis=1, skipna=False).rank()
|
||||||
|
|
||||||
|
return data_bind.loc[value_sum_all <= count]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(get_all_value_top(20))
|
||||||
25
streamlit-quant/strategy/value.py
Normal file
25
streamlit-quant/strategy/value.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
import quantcommon as qc
|
||||||
|
|
||||||
|
#가치주 포트폴리오. PER, PBR이 낮은 회사 20개
|
||||||
|
def get_value_top(count):
|
||||||
|
ticker_list = qc.QuantCommon().get_ticker_list()
|
||||||
|
value_list = qc.QuantCommon().get_value_list()
|
||||||
|
|
||||||
|
# 가치 지표가 0이하인 경우 nan으로 변경
|
||||||
|
value_list.loc[value_list['값'] <= 0, '값'] = np.nan
|
||||||
|
# 가치지표 테이블을 가로로 긴 형태로 변경
|
||||||
|
value_pivot = value_list.pivot(index='종목코드', columns='지표', values='값')
|
||||||
|
# 티커 테이블과 가치 지표 테이블을 합침
|
||||||
|
data_bind = ticker_list[['종목코드', '종목명']].merge(value_pivot,
|
||||||
|
how='left',
|
||||||
|
on='종목코드')
|
||||||
|
# rank() 함수로 PER, PBR 열의 순위를 구함. axis=0을 입력하여 순위는 열 방향으로 구함.(PER, PBR 각각 순위)
|
||||||
|
value_rank = data_bind[['PER', 'PBR']].rank(axis = 0)
|
||||||
|
# axis=1을 통해서 위에서 구한 순위 랭크를 합침. 합친 것을 다시 rank()
|
||||||
|
value_sum = value_rank.sum(axis = 1, skipna = False).rank()
|
||||||
|
return data_bind.loc[value_sum <= count, ['종목코드', '종목명', 'PER', 'PBR']]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(get_value_top(20))
|
||||||
Loading…
x
Reference in New Issue
Block a user