analyser_hj3415 4.5.3__py3-none-any.whl → 4.6.0__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/analyser/eval/blue.py +11 -10
- analyser_hj3415/analyser/tsa/common.py +96 -16
- analyser_hj3415/analyser/tsa/lstm.py +2 -38
- analyser_hj3415/analyser/tsa/myprophet.py +5 -33
- {analyser_hj3415-4.5.3.dist-info → analyser_hj3415-4.6.0.dist-info}/METADATA +4 -3
- {analyser_hj3415-4.5.3.dist-info → analyser_hj3415-4.6.0.dist-info}/RECORD +8 -8
- {analyser_hj3415-4.5.3.dist-info → analyser_hj3415-4.6.0.dist-info}/WHEEL +1 -1
- {analyser_hj3415-4.5.3.dist-info → analyser_hj3415-4.6.0.dist-info}/entry_points.txt +0 -0
@@ -139,16 +139,17 @@ class Blue:
|
|
139
139
|
except ZeroDivisionError:
|
140
140
|
mylogger.info(f'유동자산: {유동자산value} + 추정영업현금흐름: {추정영업현금흐름value} / 유동부채: {유동부채value}')
|
141
141
|
계산된유동비율 = float('inf')
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
142
|
+
|
143
|
+
mylogger.debug(f'{self} 계산된 유동비율 : {계산된유동비율}')
|
144
|
+
|
145
|
+
try:
|
146
|
+
date, *_ = Tools.date_set(유동자산date, 유동부채date, 추정영업현금흐름date)
|
147
|
+
except ValueError:
|
148
|
+
# 날짜 데이터가 없는경우
|
149
|
+
date = ''
|
150
|
+
|
151
|
+
mylogger.warning(f'{self} 유동비율 이상(100 이하 또는 nan) : {유동비율value} -> 재계산 : {계산된유동비율}')
|
152
|
+
return date, 계산된유동비율
|
152
153
|
else:
|
153
154
|
return 유동비율date, 유동비율value
|
154
155
|
|
@@ -1,11 +1,26 @@
|
|
1
1
|
import numpy as np
|
2
|
-
from dataclasses import dataclass, field
|
3
|
-
from typing import Optional
|
4
2
|
import pandas as pd
|
5
|
-
from
|
3
|
+
from dataclasses_json import config
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
from typing import Optional, List
|
6
|
+
from dataclasses_json import dataclass_json
|
7
|
+
from datetime import date
|
8
|
+
from dataclasses_json import config
|
9
|
+
from dataclasses import dataclass, field
|
10
|
+
from dataclasses_json import dataclass_json
|
6
11
|
|
7
12
|
|
8
13
|
def is_up_by_OLS(data: dict) -> bool:
|
14
|
+
"""
|
15
|
+
주어진 데이터의 값들을 날짜 순으로 정렬한 후, 최소제곱법(OLS)을 이용해 선형 회귀 기울기를 계산합니다.
|
16
|
+
데이터가 비어있거나 계산에 필요한 데이터 포인트(1개 이하)가 있는 경우에는 추세를 판단할 수 없으므로 False를 반환합니다.
|
17
|
+
|
18
|
+
Parameters:
|
19
|
+
data (dict): 날짜(문자열)를 키로, 해당 날짜의 값(숫자)을 값으로 하는 딕셔너리.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
bool: 계산된 기울기가 양수이면 True (우상향 추세), 그렇지 않으면 False.
|
23
|
+
"""
|
9
24
|
if not data:
|
10
25
|
# 데이터가 비어있으면 추세를 판단할 수 없음
|
11
26
|
return False
|
@@ -36,25 +51,90 @@ def is_up_by_OLS(data: dict) -> bool:
|
|
36
51
|
# 4) 기울기가 양수면 "우상향 추세"로 판별
|
37
52
|
return slope > 0
|
38
53
|
|
54
|
+
|
55
|
+
@dataclass
|
56
|
+
class LSTMGrade:
|
57
|
+
"""
|
58
|
+
LSTM 모델 학습 결과를 평가하기 위한 데이터 클래스.
|
59
|
+
|
60
|
+
속성:
|
61
|
+
ticker (str): 주식 티커(symbol).
|
62
|
+
train_mse (float): 학습 데이터에 대한 평균 제곱 오차(MSE).
|
63
|
+
train_mae (float): 학습 데이터에 대한 평균 절대 오차(MAE).
|
64
|
+
train_r2 (float): 학습 데이터에 대한 결정 계수(R²).
|
65
|
+
test_mse (float): 테스트 데이터에 대한 평균 제곱 오차(MSE).
|
66
|
+
test_mae (float): 테스트 데이터에 대한 평균 절대 오차(MAE).
|
67
|
+
test_r2 (float): 테스트 데이터에 대한 결정 계수(R²).
|
68
|
+
"""
|
69
|
+
ticker: str
|
70
|
+
train_mse: float
|
71
|
+
train_mae: float
|
72
|
+
train_r2: float
|
73
|
+
test_mse: float
|
74
|
+
test_mae: float
|
75
|
+
test_r2: float
|
76
|
+
|
77
|
+
|
78
|
+
# ⓐ 단일 Timestamp ↔ ISO-8601 문자열
|
79
|
+
ts_enc = lambda ts: ts.isoformat()
|
80
|
+
ts_dec = lambda s: pd.Timestamp(s)
|
81
|
+
|
82
|
+
# ⓑ Timestamp 리스트 ↔ 문자열 리스트
|
83
|
+
list_enc = lambda seq: [ts.isoformat() for ts in seq]
|
84
|
+
list_dec = lambda seq: [pd.Timestamp(s) for s in seq]
|
85
|
+
|
86
|
+
|
87
|
+
@dataclass_json
|
88
|
+
@dataclass
|
89
|
+
class ChartPoint:
|
90
|
+
"""prices 리스트의 각 원소(x, y)를 표현"""
|
91
|
+
x: pd.Timestamp = field(metadata=config(encoder=ts_enc, decoder=ts_dec))
|
92
|
+
y: Optional[float] = None
|
93
|
+
|
94
|
+
|
95
|
+
@dataclass_json
|
39
96
|
@dataclass
|
40
|
-
class
|
41
|
-
|
97
|
+
class ProphetChartData:
|
98
|
+
ticker: str
|
99
|
+
|
100
|
+
labels: List[pd.Timestamp] = field(metadata=config(encoder=list_enc, decoder=list_dec))
|
101
|
+
prices: List[ChartPoint]
|
102
|
+
yhats: List[ChartPoint]
|
103
|
+
yhat_uppers: List[ChartPoint]
|
104
|
+
yhat_lowers: List[ChartPoint]
|
42
105
|
|
43
|
-
|
44
|
-
# 꼭 부모의 __init__을 호출해야 함
|
45
|
-
super().__init__(*args, **kwargs)
|
106
|
+
is_prophet_up: bool
|
46
107
|
|
47
|
-
def _serialize(self, value, attr, obj, **kwargs):
|
48
|
-
return value.isoformat() if isinstance(value, pd.Timestamp) else None
|
49
108
|
|
50
|
-
|
51
|
-
|
109
|
+
# ISO-8601(YYYY-MM-DD) 포맷으로 직렬화·역직렬화
|
110
|
+
date_enc = lambda d: d.isoformat()
|
111
|
+
date_dec = lambda s: date.fromisoformat(s)
|
52
112
|
|
113
|
+
|
114
|
+
@dataclass_json
|
53
115
|
@dataclass
|
54
|
-
class
|
55
|
-
|
56
|
-
|
57
|
-
|
116
|
+
class LSTMChartData:
|
117
|
+
ticker: str
|
118
|
+
|
119
|
+
labels: List[pd.Timestamp] = field(metadata=config(encoder=list_enc, decoder=list_dec))
|
120
|
+
prices: List[ChartPoint]
|
121
|
+
future_prices: List[ChartPoint]
|
122
|
+
grade: LSTMGrade
|
123
|
+
num: int
|
124
|
+
is_lstm_up: bool
|
125
|
+
|
126
|
+
|
127
|
+
@dataclass_json
|
128
|
+
@dataclass
|
129
|
+
class ProphetLatestData:
|
130
|
+
ticker: str
|
58
131
|
|
132
|
+
date: date = field(metadata=config(encoder=date_enc, decoder=date_dec))
|
59
133
|
|
134
|
+
price: float
|
135
|
+
yhat: float
|
136
|
+
yhat_upper: float
|
137
|
+
yhat_lower: float
|
60
138
|
|
139
|
+
trading_action: str = ''
|
140
|
+
score: int | None = None
|
@@ -10,14 +10,13 @@ from tensorflow.keras.layers import LSTM, Dense, Dropout # type: ignore
|
|
10
10
|
from tensorflow.keras.callbacks import EarlyStopping # type: ignore
|
11
11
|
from tensorflow.keras import Input # type: ignore
|
12
12
|
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
|
13
|
-
from dataclasses import dataclass
|
14
|
-
from marshmallow import fields
|
13
|
+
from dataclasses import dataclass
|
15
14
|
|
16
15
|
from utils_hj3415 import tools, setup_logger
|
17
16
|
from db_hj3415 import myredis
|
18
17
|
from db_hj3415.mymongo.flask import Favorites
|
19
18
|
from analyser_hj3415.analyser import MIs, tsa
|
20
|
-
from analyser_hj3415.analyser.tsa.common import
|
19
|
+
from analyser_hj3415.analyser.tsa.common import LSTMChartData, LSTMGrade
|
21
20
|
|
22
21
|
mylogger = setup_logger(__name__,'WARNING')
|
23
22
|
|
@@ -51,41 +50,6 @@ class LSTMData:
|
|
51
50
|
y_test_1d: np.ndarray
|
52
51
|
|
53
52
|
|
54
|
-
@dataclass
|
55
|
-
class LSTMGrade:
|
56
|
-
"""
|
57
|
-
LSTM 모델 학습 결과를 평가하기 위한 데이터 클래스.
|
58
|
-
|
59
|
-
속성:
|
60
|
-
ticker (str): 주식 티커(symbol).
|
61
|
-
train_mse (float): 학습 데이터에 대한 평균 제곱 오차(MSE).
|
62
|
-
train_mae (float): 학습 데이터에 대한 평균 절대 오차(MAE).
|
63
|
-
train_r2 (float): 학습 데이터에 대한 결정 계수(R²).
|
64
|
-
test_mse (float): 테스트 데이터에 대한 평균 제곱 오차(MSE).
|
65
|
-
test_mae (float): 테스트 데이터에 대한 평균 절대 오차(MAE).
|
66
|
-
test_r2 (float): 테스트 데이터에 대한 결정 계수(R²).
|
67
|
-
"""
|
68
|
-
ticker: str
|
69
|
-
train_mse: float
|
70
|
-
train_mae: float
|
71
|
-
train_r2: float
|
72
|
-
test_mse: float
|
73
|
-
test_mae: float
|
74
|
-
test_r2: float
|
75
|
-
|
76
|
-
|
77
|
-
@dataclass
|
78
|
-
class LSTMChartData:
|
79
|
-
ticker: str
|
80
|
-
|
81
|
-
labels: List[pd.Timestamp] = field(metadata={"marshmallow_field": fields.List(PandasTimestampField())})
|
82
|
-
prices: List[ChartPoint]
|
83
|
-
future_prices: List[ChartPoint]
|
84
|
-
grade: LSTMGrade
|
85
|
-
num: int
|
86
|
-
is_lstm_up: bool
|
87
|
-
|
88
|
-
|
89
53
|
class MyLSTM:
|
90
54
|
"""
|
91
55
|
주가 데이터를 기반으로 LSTM 모델을 생성, 학습 및 예측하는 클래스.
|
@@ -7,44 +7,16 @@ import yfinance as yf
|
|
7
7
|
import pandas as pd
|
8
8
|
from prophet import Prophet
|
9
9
|
from sklearn.preprocessing import StandardScaler
|
10
|
-
from dataclasses import dataclass, field
|
11
|
-
from marshmallow import fields
|
12
10
|
|
13
11
|
from utils_hj3415 import tools, setup_logger
|
14
12
|
from db_hj3415 import myredis
|
15
13
|
|
16
14
|
from analyser_hj3415.analyser import eval, MIs, tsa
|
17
|
-
from analyser_hj3415.analyser.tsa.common import
|
15
|
+
from analyser_hj3415.analyser.tsa.common import ProphetChartData, ProphetLatestData
|
18
16
|
|
19
17
|
|
20
18
|
mylogger = setup_logger(__name__,'WARNING')
|
21
19
|
|
22
|
-
@dataclass
|
23
|
-
class ProphetLatestData:
|
24
|
-
ticker: str
|
25
|
-
|
26
|
-
date: datetime.date = field(metadata={"marshmallow_field": fields.Date()})
|
27
|
-
price: float
|
28
|
-
yhat: float
|
29
|
-
yhat_upper: float
|
30
|
-
yhat_lower: float
|
31
|
-
|
32
|
-
trading_action: str = ''
|
33
|
-
score: int = None
|
34
|
-
|
35
|
-
|
36
|
-
@dataclass
|
37
|
-
class ProphetChartData:
|
38
|
-
ticker: str
|
39
|
-
|
40
|
-
labels: List[pd.Timestamp] = field(metadata={"marshmallow_field": fields.List(PandasTimestampField())})
|
41
|
-
prices: List[ChartPoint]
|
42
|
-
yhats: List[ChartPoint]
|
43
|
-
yhat_uppers: List[ChartPoint]
|
44
|
-
yhat_lowers: List[ChartPoint]
|
45
|
-
|
46
|
-
is_prophet_up: bool
|
47
|
-
|
48
20
|
|
49
21
|
class MyProphet:
|
50
22
|
|
@@ -123,15 +95,15 @@ class MyProphet:
|
|
123
95
|
return data
|
124
96
|
else:
|
125
97
|
# 다운로드 자체는 성공했지만, 빈 데이터가 반환될 경우
|
126
|
-
print(f"[{attempt}/{max_retries}] 다운로드 결과가 비어 있습니다. 재시도합니다...")
|
98
|
+
print(f"[{attempt}/{max_retries}] {self.ticker} 다운로드 결과가 비어 있습니다. 재시도합니다...")
|
127
99
|
except Exception as e:
|
128
100
|
# 예외 발생 시, 재시도
|
129
|
-
print(f"[{attempt}/{max_retries}] 다운로드 실패: {e}. 재시도합니다...")
|
101
|
+
print(f"[{attempt}/{max_retries}] {self.ticker} 다운로드 실패: {e}. 재시도합니다...")
|
130
102
|
|
131
103
|
# 재시도 전 대기
|
132
104
|
time.sleep(delay_sec)
|
133
105
|
|
134
|
-
mylogger.error(f"주가 데이터를 다운로드하지 못했습니다 (최대 {max_retries}회 시도 실패).")
|
106
|
+
mylogger.error(f"{self.ticker} 주가 데이터를 다운로드하지 못했습니다 (최대 {max_retries}회 시도 실패).")
|
135
107
|
return pd.DataFrame()
|
136
108
|
|
137
109
|
def preprocessing_for_prophet() -> pd.DataFrame:
|
@@ -197,7 +169,7 @@ class MyProphet:
|
|
197
169
|
try:
|
198
170
|
self.df_real = preprocessing_for_prophet()
|
199
171
|
self.df_forecast = make_forecast()
|
200
|
-
except ValueError as e:
|
172
|
+
except (ValueError, KeyError) as e:
|
201
173
|
mylogger.error(f"{self.ticker} : 빈 데이터프레임...{e}")
|
202
174
|
self.df_real = pd.DataFrame()
|
203
175
|
self.df_forecast = pd.DataFrame()
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: analyser_hj3415
|
3
|
-
Version: 4.
|
3
|
+
Version: 4.6.0
|
4
4
|
Summary: Stock analyser and database processing programs
|
5
5
|
Requires-Python: >=3.6
|
6
6
|
Description-Content-Type: text/markdown
|
@@ -12,7 +12,8 @@ Requires-Dist: yfinance>=0.2.54
|
|
12
12
|
Requires-Dist: prophet>=1.1.6
|
13
13
|
Requires-Dist: kaleido>=0.2.1
|
14
14
|
Requires-Dist: matplotlib>=3.9.2
|
15
|
-
Requires-Dist:
|
15
|
+
Requires-Dist: dataclasses_json>=0.6.7
|
16
|
+
Requires-Dist: pandas>=2.2.3
|
16
17
|
Requires-Dist: tensorflow-macos>=2.16.2; platform_machine == 'arm64' and sys_platform == 'darwin'
|
17
18
|
Requires-Dist: tensorflow-metal>=0.5.0; platform_machine == 'arm64' and sys_platform == 'darwin'
|
18
19
|
Requires-Dist: tensorflow>=2.18.0; platform_machine != 'arm64' or sys_platform != 'darwin'
|
@@ -3,16 +3,16 @@ analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
analyser_hj3415/cli.py,sha256=drfh0cqZ0LUHUJMJeyXcv1QTD7VYJMr58gcY4WHsVk4,11956
|
4
4
|
analyser_hj3415/analyser/__init__.py,sha256=N0XyBfWJNpDS_6JYziKETWePO_jtFB1m7E8Qbwt1w0Q,1096
|
5
5
|
analyser_hj3415/analyser/eval/__init__.py,sha256=IP1d0Q3nOCAD3zK1qxrC685MkJQfUh-qaXc7xptTxk8,80
|
6
|
-
analyser_hj3415/analyser/eval/blue.py,sha256
|
6
|
+
analyser_hj3415/analyser/eval/blue.py,sha256=-t_9Tm2n8tfrPRDIDT9YU7EQLaFqPa89_7JS8wqVcfA,10593
|
7
7
|
analyser_hj3415/analyser/eval/common.py,sha256=sNXapoofShA43ww_SLjXmIjkrAr1AhAcezdaN_X_3Us,11443
|
8
8
|
analyser_hj3415/analyser/eval/growth.py,sha256=LunZcZvhly_2PWUZBbd0gW9ZImWYT5sAu_iixVLxGuc,6226
|
9
9
|
analyser_hj3415/analyser/eval/mil.py,sha256=6_1SuWqG1fsuZUKuaABhSqNsYCgj5np35auWhnE5wdk,15289
|
10
10
|
analyser_hj3415/analyser/eval/red.py,sha256=YXk7QX1No9mzGJlWnwfJ2aTUTbSS_LnPUL4PKzx0Aws,12051
|
11
11
|
analyser_hj3415/analyser/tsa/__init__.py,sha256=7j-WshikzsDGGo_wuFoMPNmYfY-bLSEMd6o1MKSQKLI,150
|
12
|
-
analyser_hj3415/analyser/tsa/common.py,sha256=
|
13
|
-
analyser_hj3415/analyser/tsa/lstm.py,sha256=
|
14
|
-
analyser_hj3415/analyser/tsa/myprophet.py,sha256=
|
15
|
-
analyser_hj3415-4.
|
16
|
-
analyser_hj3415-4.
|
17
|
-
analyser_hj3415-4.
|
18
|
-
analyser_hj3415-4.
|
12
|
+
analyser_hj3415/analyser/tsa/common.py,sha256=NxssIm7z1V3W-Vt8B89eT_bUa4YJRTeUbfyBZdXns90,4180
|
13
|
+
analyser_hj3415/analyser/tsa/lstm.py,sha256=l0P79Zm1X3PMbyX6d449j8V5pI1yiQfYdtQZr06khw4,28819
|
14
|
+
analyser_hj3415/analyser/tsa/myprophet.py,sha256=INwn7tM6i9WCZkGb9uQm_Q4mmPRvZn06kW1__vnzloA,18445
|
15
|
+
analyser_hj3415-4.6.0.dist-info/entry_points.txt,sha256=ZfjPnJuH8SzvhE9vftIPMBIofsc65IAWYOhqOC_L5ck,65
|
16
|
+
analyser_hj3415-4.6.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
17
|
+
analyser_hj3415-4.6.0.dist-info/METADATA,sha256=Nhgb9gPJUr2dKBGW9aREyuZF-ym7ht2jMoNmvG7sNJ0,6844
|
18
|
+
analyser_hj3415-4.6.0.dist-info/RECORD,,
|
File without changes
|