feat: 파일 이름 변경, 백테스트 샘플 추가, 디렉토리 패키지화

This commit is contained in:
Ayuriel 2025-03-15 01:24:46 +09:00
parent 07e07dfbcd
commit 679eb4fe0b
19 changed files with 71 additions and 15 deletions

View File

@ -1,2 +1,9 @@
# 실행
streamlit run .\streamlit-quant\app.py --server.port 20000
# pre-
Go to Build Tools for Visual Studio 2017
Select free download under Visual Studio Community 2017. This will download the installer. Run the installer.
Select what you need under workload tab:
a. Under Windows, there are three choices. Only check Desktop development with C++.
b. Under Web & Cloud, there are seven choices. Only check Python development (I believe this is optional, but I have done it).

View File

@ -69,6 +69,19 @@ class QuantCommon:
return price_list
def get_price_list_by_code(self, codes):
engine = self.create_engine()
try:
price_list = pd.read_sql(f"""
select * from kor_price
where 종목코드 in ({codes});
""", con=engine)
finally:
engine.dispose()
return price_list
def get_fs_list(self):
engine = self.create_engine()

View File

@ -0,0 +1 @@
__all__ = ['backtest', 'strategy']

View File

@ -0,0 +1,46 @@
import bt
import matplotlib.pyplot as plt
import pandas as pd
import quantcommon
import streamlit_quant.strategy.multi_factor as multi_factor
qc = quantcommon.QuantCommon()
mf = multi_factor.get_multi_factor_top(qc, 20)
codes = ','.join(mf['종목코드'].array)
price = qc.get_price_list_by_code(codes)
# price = price.set_index(['날짜'])
# price.rename(columns={"날짜": "Date"})
price["Date"] = pd.to_datetime(price["날짜"])
pivot_df = price.pivot(index="Date", columns="종목코드", values="종가")
# print(pivot_df.tail)
strategy = bt.Strategy("Asset_EW", [
bt.algos.SelectAll(), # 모든 데이터 사용
bt.algos.WeighEqually(), # 동일 비중 투자
bt.algos.RunMonthly(), # 매 월말 리밸런싱
bt.algos.Rebalance() # 계산된 비중에 따라 리밸런싱
])
# 가격 데이터 중 시작 시점이 모두 다르므로, dropna() 함수를 통해 NA를 모두 제거하여 시작 시점을 맞춤
pivot_df.dropna(inplace=True)
# 백테스트 생성
backtest = bt.Backtest(strategy, pivot_df)
# 백테스트 실행
result = bt.run(backtest)
# prices: 누적 수익률이 데이터프레임 형태로 나타나며, 시작 시점을 100으로 환산하여 계산
# to_returns: 수익률 계산
# print(result.prices.to_returns())
result.plot(figsize=(10, 6), legend=False)
plt.show()
result.display()

View File

@ -0,0 +1 @@
__all__ = ['multi_factor']

View File

@ -1,5 +1,4 @@
import pandas as pd
import numpy as np
import quantcommon
# DB 연결

View File

@ -4,14 +4,11 @@ import statsmodels.api as sm
from scipy.stats import zscore
import matplotlib.pyplot as plt
import seaborn as sns
import quantcommon
# 멀티 팩터 포트폴리오.
# 퀄리티: 자기자본이익률(ROE), 매출총이익(GPA), 영업활동현금흐름(CFO)
# 밸류: PER, PBR, PSR, PCR, DY
# 모멘텀: 12개월 수익률, K-Ratio
engine = quantcommon.QuantCommon().create_engine()
# 각 섹터별 아웃라이어를 제거한 후 순위와 z-score를 구하는 함수
def col_clean(df, cutoff=0.01, asc=False):
@ -45,8 +42,7 @@ def plot_rank(df):
plt.show()
def get_multi_factor_top(count):
qc = quantcommon.QuantCommon()
def get_multi_factor_top(qc, count):
ticker_list = qc.get_ticker_list()
fs_list = qc.get_fs_list()
value_list = qc.get_value_list()
@ -220,7 +216,7 @@ def get_multi_factor_top(count):
# 기본 테이블(data_bind)과 합침
port_qvm = data_bind.merge(data_bind_final_sum, on='종목코드')
# 최종 z-score의 합(qvm) 기준 순위가 20위 이내인 경우 투자 종목에 해당하니 Y로 표시, 나머진 N
port_qvm['invest'] = np.where(port_qvm['qvm'].rank() <= 20, 'Y', 'N')
port_qvm['invest'] = np.where(port_qvm['qvm'].rank() <= count, 'Y', 'N')
# round()는 DataFrame 객체 내의 요소를 반올림하는 메서드
return port_qvm[port_qvm['invest'] == 'Y'].round(4)
@ -252,11 +248,4 @@ def get_multi_factor_top(count):
# hist_momentum['rank'] = hist_momentum.groupby('variable')['value'].rank(ascending = False)
# plot_rank(hist_momentum)
#
# port_qvm[port_qvm['invest'] == 'Y']['종목코드'].to_excel('model.xlsx', index=False)
if __name__ == '__main__':
top = get_multi_factor_top(20)
# head() 상위 n개 반환. 기본값은 5
print(top.head())
top['종목코드'].to_excel('model.xlsx', index=False)
# port_qvm[port_qvm['invest'] == 'Y']['종목코드'].to_excel('model.xlsx', index=False)