analyser_hj3415 2.7.6__py2.py3-none-any.whl → 2.7.8__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- analyser_hj3415/cli.py +5 -8
- analyser_hj3415/eval.py +13 -9
- analyser_hj3415/myprophet.py +144 -0
- analyser_hj3415/workroom/lstm.py +3 -3
- {analyser_hj3415-2.7.6.dist-info → analyser_hj3415-2.7.8.dist-info}/METADATA +7 -1
- {analyser_hj3415-2.7.6.dist-info → analyser_hj3415-2.7.8.dist-info}/RECORD +9 -9
- analyser_hj3415/workroom/myprophet.py +0 -58
- {analyser_hj3415-2.7.6.dist-info → analyser_hj3415-2.7.8.dist-info}/LICENSE +0 -0
- {analyser_hj3415-2.7.6.dist-info → analyser_hj3415-2.7.8.dist-info}/WHEEL +0 -0
- {analyser_hj3415-2.7.6.dist-info → analyser_hj3415-2.7.8.dist-info}/entry_points.txt +0 -0
analyser_hj3415/cli.py
CHANGED
@@ -117,7 +117,7 @@ def analyser_manager():
|
|
117
117
|
for i, code in enumerate(myredis.Corps.list_all_codes()):
|
118
118
|
red.code = code
|
119
119
|
print(f"*** {i} / {red} ***")
|
120
|
-
pprint.pprint(red.get(args.refresh))
|
120
|
+
pprint.pprint(red.get(args.refresh, verbose=False))
|
121
121
|
|
122
122
|
# 원래 저장되었던 기대수익률로 다시 복원
|
123
123
|
eval.Red.expect_earn = ee_orig
|
@@ -140,10 +140,7 @@ def analyser_manager():
|
|
140
140
|
noti.telegram_to('manager', f"오늘의 Red({args.code})를 레디스캐시에 저장했습니다.(유효 12시간)")
|
141
141
|
|
142
142
|
elif args.command == 'ranking':
|
143
|
-
|
144
|
-
result = eval.Red.ranking(expect_earn=args.expect_earn, refresh=True)
|
145
|
-
else:
|
146
|
-
result = eval.Red.ranking(expect_earn=args.expect_earn, refresh=False)
|
143
|
+
result = eval.Red.ranking(expect_earn=args.expect_earn, refresh=args.refresh)
|
147
144
|
print(result)
|
148
145
|
if args.noti:
|
149
146
|
noti.telegram_to('manager', "오늘의 red ranking을 레디스캐시에 저장했습니다.(유효 12시간)")
|
@@ -156,7 +153,7 @@ def analyser_manager():
|
|
156
153
|
for i, code in enumerate(myredis.Corps.list_all_codes()):
|
157
154
|
mil.code = code
|
158
155
|
print(f"*** {i} / {mil} ***")
|
159
|
-
pprint.pprint(mil.get(args.refresh))
|
156
|
+
pprint.pprint(mil.get(args.refresh, verbose=False))
|
160
157
|
else:
|
161
158
|
assert utils.is_6digit(args.code), "code 인자는 6자리 숫자이어야 합니다."
|
162
159
|
mil = eval.Mil(args.code)
|
@@ -173,7 +170,7 @@ def analyser_manager():
|
|
173
170
|
for i, code in enumerate(myredis.Corps.list_all_codes()):
|
174
171
|
blue.code = code
|
175
172
|
print(f"*** {i} / {blue} ***")
|
176
|
-
pprint.pprint(blue.get(args.refresh))
|
173
|
+
pprint.pprint(blue.get(args.refresh, verbose=False))
|
177
174
|
else:
|
178
175
|
assert utils.is_6digit(args.code), "code 인자는 6자리 숫자이어야 합니다."
|
179
176
|
blue = eval.Blue(args.code)
|
@@ -190,7 +187,7 @@ def analyser_manager():
|
|
190
187
|
for i, code in enumerate(myredis.Corps.list_all_codes()):
|
191
188
|
growth.code = code
|
192
189
|
print(f"*** {i} / {growth} ***")
|
193
|
-
pprint.pprint(growth.get(args.refresh))
|
190
|
+
pprint.pprint(growth.get(args.refresh, verbose=False))
|
194
191
|
else:
|
195
192
|
assert utils.is_6digit(args.code), "code 인자는 6자리 숫자이어야 합니다."
|
196
193
|
growth = eval.Growth(args.code)
|
analyser_hj3415/eval.py
CHANGED
@@ -324,7 +324,7 @@ class Red:
|
|
324
324
|
score = score,
|
325
325
|
)
|
326
326
|
|
327
|
-
def get(self, refresh = False) -> RedData:
|
327
|
+
def get(self, refresh = False, verbose = True) -> RedData:
|
328
328
|
"""
|
329
329
|
RedData 형식의 데이터를 계산하여 리턴하고 레디스 캐시에 저장한다.
|
330
330
|
:param refresh:
|
@@ -333,7 +333,8 @@ class Red:
|
|
333
333
|
redis_name = f"{self.code}_red"
|
334
334
|
analyser_logger.info(f"{self} RedData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
335
335
|
expire_time = 3600 * 12
|
336
|
-
|
336
|
+
if verbose:
|
337
|
+
print(f"{self} redisname: '{redis_name}' / expect_earn: {Red.expect_earn} / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
337
338
|
|
338
339
|
def fetch_generate_data(refresh_in: bool) -> dict:
|
339
340
|
return asdict(self._generate_data(refresh_in))
|
@@ -375,7 +376,7 @@ class Red:
|
|
375
376
|
red = Red('005930')
|
376
377
|
for i, code in enumerate(myredis.Corps.list_all_codes()):
|
377
378
|
red.code = code
|
378
|
-
red_score = red.get(refresh=refresh_in).score
|
379
|
+
red_score = red.get(refresh=refresh_in, verbose=False).score
|
379
380
|
if red_score > 0:
|
380
381
|
data[code] = red_score
|
381
382
|
print(f"{i}: {red} - {red_score}")
|
@@ -632,7 +633,7 @@ class Mil:
|
|
632
633
|
date = date_list,
|
633
634
|
)
|
634
635
|
|
635
|
-
def get(self, refresh = False) -> MilData:
|
636
|
+
def get(self, refresh = False, verbose = True) -> MilData:
|
636
637
|
"""
|
637
638
|
MilData 형식의 데이터를 계산하여 리턴하고 레디스 캐시에 저장한다.
|
638
639
|
:param refresh:
|
@@ -640,7 +641,8 @@ class Mil:
|
|
640
641
|
"""
|
641
642
|
redis_name = f"{self.code}_mil"
|
642
643
|
analyser_logger.info(f"{self} MilData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
643
|
-
|
644
|
+
if verbose:
|
645
|
+
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
644
646
|
|
645
647
|
def fetch_generate_data(refresh_in: bool) -> dict:
|
646
648
|
return asdict(self._generate_data(refresh_in))
|
@@ -804,7 +806,7 @@ class Blue:
|
|
804
806
|
date= date_list,
|
805
807
|
)
|
806
808
|
|
807
|
-
def get(self, refresh = False) -> BlueData:
|
809
|
+
def get(self, refresh = False, verbose = True) -> BlueData:
|
808
810
|
"""
|
809
811
|
BlueData 형식의 데이터를 계산하여 리턴하고 레디스 캐시에 저장한다.
|
810
812
|
:param refresh:
|
@@ -812,7 +814,8 @@ class Blue:
|
|
812
814
|
"""
|
813
815
|
redis_name = f"{self.code}_blue"
|
814
816
|
analyser_logger.info(f"{self} BlueData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
815
|
-
|
817
|
+
if verbose:
|
818
|
+
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
816
819
|
|
817
820
|
def fetch_generate_data(refresh_in: bool) -> dict:
|
818
821
|
return asdict(self._generate_data(refresh_in))
|
@@ -903,7 +906,7 @@ class Growth:
|
|
903
906
|
date= date_list,
|
904
907
|
)
|
905
908
|
|
906
|
-
def get(self, refresh = False) -> GrowthData:
|
909
|
+
def get(self, refresh = False, verbose = True) -> GrowthData:
|
907
910
|
"""
|
908
911
|
GrowthData 형식의 데이터를 계산하여 리턴하고 레디스 캐시에 저장한다.
|
909
912
|
:param refresh:
|
@@ -911,7 +914,8 @@ class Growth:
|
|
911
914
|
"""
|
912
915
|
redis_name = f"{self.code}_growth"
|
913
916
|
analyser_logger.info(f"{self} GrowthData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
914
|
-
|
917
|
+
if verbose:
|
918
|
+
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
915
919
|
|
916
920
|
def fetch_generate_data(refresh_in: bool) -> dict:
|
917
921
|
return asdict(self._generate_data(refresh_in))
|
@@ -0,0 +1,144 @@
|
|
1
|
+
import yfinance as yf
|
2
|
+
from datetime import datetime, timedelta
|
3
|
+
import pandas as pd
|
4
|
+
from prophet import Prophet
|
5
|
+
from sklearn.preprocessing import StandardScaler
|
6
|
+
from utils_hj3415 import utils
|
7
|
+
from typing import Optional
|
8
|
+
import plotly.graph_objs as go
|
9
|
+
from plotly.offline import plot
|
10
|
+
import matplotlib.pyplot as plt # Matplotlib 수동 임포트
|
11
|
+
from db_hj3415 import myredis
|
12
|
+
|
13
|
+
class MyProphet:
|
14
|
+
def __init__(self, code: str):
|
15
|
+
assert utils.is_6digit(code), f'Invalid value : {code}'
|
16
|
+
self._code = code
|
17
|
+
self.name = myredis.Corps(code, 'c101').get_name()
|
18
|
+
self.raw_data = self.get_raw_data()
|
19
|
+
|
20
|
+
self.scaler = StandardScaler()
|
21
|
+
self.model = Prophet()
|
22
|
+
|
23
|
+
@property
|
24
|
+
def code(self) -> str:
|
25
|
+
return self._code
|
26
|
+
|
27
|
+
@code.setter
|
28
|
+
def code(self, code: str):
|
29
|
+
assert utils.is_6digit(code), f'Invalid value : {code}'
|
30
|
+
self._code = code
|
31
|
+
self.name = myredis.Corps(code, 'c101').get_name()
|
32
|
+
self.raw_data = self.get_raw_data()
|
33
|
+
|
34
|
+
def get_raw_data(self) -> pd.DataFrame:
|
35
|
+
"""
|
36
|
+
야후에서 해당 종목의 4년간 주가 raw data를 받아온다.
|
37
|
+
:return:
|
38
|
+
"""
|
39
|
+
# 오늘 날짜 가져오기
|
40
|
+
today = datetime.today()
|
41
|
+
|
42
|
+
# 4년 전 날짜 계산 (4년 = 365일 * 4)
|
43
|
+
four_years_ago = today - timedelta(days=365 * 4)
|
44
|
+
|
45
|
+
return yf.download(
|
46
|
+
self.code + '.KS',
|
47
|
+
start=four_years_ago.strftime('%Y-%m-%d'),
|
48
|
+
end=today.strftime('%Y-%m-%d')
|
49
|
+
)
|
50
|
+
|
51
|
+
def preprocessing_for_prophet(self) -> pd.DataFrame:
|
52
|
+
"""
|
53
|
+
Prophet이 사용할 수 있도록 데이터 준비
|
54
|
+
ds는 날짜, y는 주가
|
55
|
+
:return:
|
56
|
+
"""
|
57
|
+
df = self.raw_data[['Close', 'Volume']].reset_index()
|
58
|
+
df.columns = ['ds', 'y', 'volume'] # Prophet의 형식에 맞게 열 이름 변경
|
59
|
+
|
60
|
+
# 추가 변수를 정규화
|
61
|
+
df['volume_scaled'] = self.scaler.fit_transform(df[['volume']])
|
62
|
+
return df
|
63
|
+
|
64
|
+
def make_forecast(self) -> pd.DataFrame:
|
65
|
+
# Prophet을 위한 dataframe 만들기
|
66
|
+
df_for_prophet = self.preprocessing_for_prophet()
|
67
|
+
|
68
|
+
# 정규화된 'volume_scaled' 변수를 외부 변수로 추가
|
69
|
+
self.model.add_regressor('volume_scaled')
|
70
|
+
|
71
|
+
self.model.fit(df_for_prophet)
|
72
|
+
|
73
|
+
# 향후 180일 동안의 주가 예측
|
74
|
+
future = self.model.make_future_dataframe(periods=180)
|
75
|
+
|
76
|
+
# 미래 데이터에 거래량 추가 (평균 거래량을 사용해 정규화)
|
77
|
+
future_volume = pd.DataFrame({'volume': [self.raw_data['Volume'].mean()] * len(future)})
|
78
|
+
future['volume_scaled'] = self.scaler.transform(future_volume[['volume']])
|
79
|
+
|
80
|
+
forecast = self.model.predict(future)
|
81
|
+
return forecast
|
82
|
+
|
83
|
+
def export_to(self, to="str") -> Optional[str]:
|
84
|
+
"""
|
85
|
+
prophet과 plotly로 그래프를 그려서 html을 문자열로 반환
|
86
|
+
:param to: str, png, htmlfile, show
|
87
|
+
:return:
|
88
|
+
"""
|
89
|
+
# 실제 데이터
|
90
|
+
df = self.preprocessing_for_prophet()
|
91
|
+
# 예측 데이터
|
92
|
+
forecast = self.make_forecast()
|
93
|
+
|
94
|
+
# Plotly를 사용한 시각화
|
95
|
+
fig = go.Figure()
|
96
|
+
|
97
|
+
# 실제 데이터
|
98
|
+
fig.add_trace(go.Scatter(x=df['ds'], y=df['y'], mode='markers', name='실제주가'))
|
99
|
+
# 예측 데이터
|
100
|
+
fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines', name='예측치'))
|
101
|
+
|
102
|
+
# 상한/하한 구간
|
103
|
+
fig.add_trace(
|
104
|
+
go.Scatter(x=forecast['ds'], y=forecast['yhat_upper'], fill=None, mode='lines', name='상한'))
|
105
|
+
fig.add_trace(
|
106
|
+
go.Scatter(x=forecast['ds'], y=forecast['yhat_lower'], fill='tonexty', mode='lines', name='하한'))
|
107
|
+
|
108
|
+
fig.update_layout(
|
109
|
+
title=f'{self.code} {self.name} 주가 예측 그래프(prophet)',
|
110
|
+
xaxis_title='일자',
|
111
|
+
yaxis_title='주가(원)',
|
112
|
+
xaxis = dict(
|
113
|
+
tickformat='%Y/%m', # X축을 '연/월' 형식으로 표시
|
114
|
+
),
|
115
|
+
yaxis = dict(
|
116
|
+
tickformat=".0f", # 소수점 없이 원래 숫자 표시
|
117
|
+
)
|
118
|
+
)
|
119
|
+
|
120
|
+
if to == 'str':
|
121
|
+
# 그래프 HTML로 변환 (string 형식으로 저장)
|
122
|
+
graph_html = plot(fig, output_type='div')
|
123
|
+
return graph_html
|
124
|
+
elif to == 'png':
|
125
|
+
# 그래프를 PNG 파일로 저장
|
126
|
+
fig.write_image("plotly_graph.png")
|
127
|
+
elif to == 'htmlfile':
|
128
|
+
# 그래프를 HTML로 저장
|
129
|
+
plot(fig, filename='graph_plotly.html', auto_open=False)
|
130
|
+
return None
|
131
|
+
elif to == 'show':
|
132
|
+
# 예측 결과 출력
|
133
|
+
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
|
134
|
+
# 예측 결과 시각화 (Matplotlib 사용)
|
135
|
+
fig = self.model.plot(forecast)
|
136
|
+
# 추세 및 계절성 시각화
|
137
|
+
fig2 = self.model.plot_components(forecast)
|
138
|
+
plt.show() # 시각화 창 띄우기
|
139
|
+
else:
|
140
|
+
Exception("to 인자가 맞지 않습니다.")
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
|
analyser_hj3415/workroom/lstm.py
CHANGED
@@ -9,11 +9,11 @@ import matplotlib.pyplot as plt
|
|
9
9
|
# 1. 데이터 다운로드 (애플 주식 데이터를 사용)
|
10
10
|
#stock_data = yf.download('AAPL', start='2020-01-01', end='2023-01-01')
|
11
11
|
# 삼성전자 주식 데이터 가져오기 (KOSPI 상장)
|
12
|
-
#stock_data = yf.download('005930.KS', start='2019-01-01', end='2024-10-
|
12
|
+
#stock_data = yf.download('005930.KS', start='2019-01-01', end='2024-10-11')
|
13
13
|
# 크래프톤 주식 데이터 가져오기 (KOSPI 상장)
|
14
|
-
|
14
|
+
stock_data = yf.download('259960.KS', start='2020-01-01', end='2024-10-11')
|
15
15
|
# 하이닉스 주식 데이터 가져오기 (KOSPI 상장)
|
16
|
-
stock_data = yf.download('000660.KS', start='2019-01-01', end='2024-10-
|
16
|
+
#stock_data = yf.download('000660.KS', start='2019-01-01', end='2024-10-11')
|
17
17
|
|
18
18
|
|
19
19
|
# 2. 필요한 열만 선택 (종가만 사용)
|
@@ -1,12 +1,18 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: analyser_hj3415
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.8
|
4
4
|
Summary: Stock analyser and database processing programs
|
5
5
|
Author-email: Hyungjin Kim <hj3415@gmail.com>
|
6
6
|
Description-Content-Type: text/markdown
|
7
7
|
Classifier: License :: OSI Approved :: MIT License
|
8
8
|
Requires-Dist: utils-hj3415>=2.9.2
|
9
9
|
Requires-Dist: db-hj3415>=4.0.3
|
10
|
+
Requires-Dist: scikit-learn>=1.5.2
|
11
|
+
Requires-Dist: plotly>=5.24.1
|
12
|
+
Requires-Dist: yfinance>=0.2.44
|
13
|
+
Requires-Dist: prophet>=1.1.6
|
14
|
+
Requires-Dist: kaleido>=0.2.1
|
15
|
+
Requires-Dist: matplotlib>=3.9.2
|
10
16
|
Project-URL: Home, https://www.hyungjin.kr
|
11
17
|
|
12
18
|
### analyser-hj3415
|
@@ -1,16 +1,16 @@
|
|
1
1
|
analyser_hj3415/.DS_Store,sha256=qr9-0FPn5CFKe6kEu8_dWCNhzQ0sN7bwQgffKsaJEEo,6148
|
2
2
|
analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
analyser_hj3415/cli.py,sha256=
|
4
|
-
analyser_hj3415/eval.py,sha256=
|
3
|
+
analyser_hj3415/cli.py,sha256=7ys-b9H_tJAbLLi_XpjmEvDiyNHddpg9F1FNAACfWnE,11005
|
4
|
+
analyser_hj3415/eval.py,sha256=4F0GIknCogAhv_iTq8auLrmwW20u8kH0HY0fP4SaVa4,39099
|
5
|
+
analyser_hj3415/myprophet.py,sha256=N_eUzAmrbEuqJBJ9OqbnMrHC3_kc3JXGq6pND5o4yuE,5096
|
5
6
|
analyser_hj3415/workroom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
analyser_hj3415/workroom/lstm.py,sha256=
|
7
|
-
analyser_hj3415/workroom/myprophet.py,sha256=xGbs4_cCeSNAX62H6rG-bUz6_rUOyO6787WAjLexMkw,1855
|
7
|
+
analyser_hj3415/workroom/lstm.py,sha256=gF7i1NqPOhNysvkSQcC_mkOmvLk96jPxoqajZ-FFD8I,4078
|
8
8
|
analyser_hj3415/workroom/mysklearn.py,sha256=wJXKz5MqqTzADdG2mqRMMzc_G9RzwYjj5_j4gyOopxQ,2030
|
9
9
|
analyser_hj3415/workroom/mysklearn2.py,sha256=1lIy6EWEQHkOzDS-av8U0zQH6DuCLKWMI73dnJx5KRs,1495
|
10
10
|
analyser_hj3415/workroom/score.py,sha256=P6nHBJYmyhigGtT4qna4BmNtvt4B93b7SKyzdstJK24,17376
|
11
11
|
analyser_hj3415/workroom/trash.py,sha256=zF-W0piqkGr66UP6-iybo9EXh2gO0RP6R1FnIpsGkl8,12262
|
12
|
-
analyser_hj3415-2.7.
|
13
|
-
analyser_hj3415-2.7.
|
14
|
-
analyser_hj3415-2.7.
|
15
|
-
analyser_hj3415-2.7.
|
16
|
-
analyser_hj3415-2.7.
|
12
|
+
analyser_hj3415-2.7.8.dist-info/entry_points.txt,sha256=ZfjPnJuH8SzvhE9vftIPMBIofsc65IAWYOhqOC_L5ck,65
|
13
|
+
analyser_hj3415-2.7.8.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
|
14
|
+
analyser_hj3415-2.7.8.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
15
|
+
analyser_hj3415-2.7.8.dist-info/METADATA,sha256=Ru0TFe19ItTPkffO_39zz7vuX0b78V7EZoiO4f1wCEM,6607
|
16
|
+
analyser_hj3415-2.7.8.dist-info/RECORD,,
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# prophet 사용 공부
|
2
|
-
|
3
|
-
import yfinance as yf
|
4
|
-
import pandas as pd
|
5
|
-
from prophet import Prophet
|
6
|
-
import matplotlib.pyplot as plt # Matplotlib 수동 임포트
|
7
|
-
|
8
|
-
|
9
|
-
# 애플 주식 데이터를 다운로드
|
10
|
-
#stock_data = yf.download('AAPL', start='2020-01-01', end='2024-10-09')
|
11
|
-
# 삼성전자 주식 데이터 가져오기 (KOSPI 상장)
|
12
|
-
#stock_data = yf.download('005930.KS', start='2020-01-01', end='2024-08-01')
|
13
|
-
# 크래프톤 주식 데이터 가져오기 (KOSPI 상장)
|
14
|
-
#stock_data = yf.download('259960.KS', start='2020-01-01', end='2024-10-08')
|
15
|
-
# 하이닉스 주식 데이터 가져오기 (KOSPI 상장)
|
16
|
-
stock_data = yf.download('000660.KS', start='2020-01-01', end='2024-10-08')
|
17
|
-
|
18
|
-
|
19
|
-
# Prophet이 사용할 수 있도록 데이터 준비
|
20
|
-
df = stock_data[['Close', 'Volume']].reset_index()
|
21
|
-
df.columns = ['ds', 'y', 'volume'] # Prophet의 형식에 맞게 열 이름 변경
|
22
|
-
|
23
|
-
from sklearn.preprocessing import StandardScaler
|
24
|
-
|
25
|
-
# 추가 변수를 정규화
|
26
|
-
scaler = StandardScaler()
|
27
|
-
df['volume_scaled'] = scaler.fit_transform(df[['volume']])
|
28
|
-
|
29
|
-
# Prophet 모델 생성 및 학습
|
30
|
-
model = Prophet()
|
31
|
-
|
32
|
-
# 정규화된 'volume_scaled' 변수를 외부 변수로 추가
|
33
|
-
model.add_regressor('volume_scaled')
|
34
|
-
|
35
|
-
model.fit(df)
|
36
|
-
|
37
|
-
# 향후 180일 동안의 주가 예측
|
38
|
-
future = model.make_future_dataframe(periods=180)
|
39
|
-
|
40
|
-
# 미래 데이터에 거래량 추가 (평균 거래량을 사용해 정규화)
|
41
|
-
future_volume = pd.DataFrame({'volume': [stock_data['Volume'].mean()] * len(future)})
|
42
|
-
future['volume_scaled'] = scaler.transform(future_volume[['volume']])
|
43
|
-
|
44
|
-
|
45
|
-
forecast = model.predict(future)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# 예측 결과 출력
|
50
|
-
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
|
51
|
-
|
52
|
-
# 예측 결과 시각화 (Matplotlib 사용)
|
53
|
-
fig = model.plot(forecast)
|
54
|
-
|
55
|
-
# 추세 및 계절성 시각화
|
56
|
-
fig2 = model.plot_components(forecast)
|
57
|
-
|
58
|
-
plt.show() # 시각화 창 띄우기
|
File without changes
|
File without changes
|
File without changes
|