analyser_hj3415 3.2.1__py3-none-any.whl → 3.3.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.
@@ -1,6 +1,3 @@
1
- """
2
- Time Series Analysis
3
- """
4
1
  import os
5
2
  import numpy as np
6
3
  import yfinance as yf
@@ -11,16 +8,16 @@ import plotly.graph_objs as go
11
8
  from plotly.offline import plot
12
9
  import matplotlib.pyplot as plt # Matplotlib 수동 임포트
13
10
  from sklearn.preprocessing import MinMaxScaler
14
- from tensorflow.keras.models import Sequential
15
- from tensorflow.keras.layers import LSTM, Dense, Dropout
16
- from tensorflow.keras.callbacks import EarlyStopping
17
- from tensorflow.keras import Input
11
+ from tensorflow.keras.models import Sequential # type: ignore
12
+ from tensorflow.keras.layers import LSTM, Dense, Dropout # type: ignore
13
+ from tensorflow.keras.callbacks import EarlyStopping # type: ignore
14
+ from tensorflow.keras import Input # type: ignore
18
15
  from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
19
16
  from dataclasses import dataclass
20
17
 
21
18
  from utils_hj3415 import tools, setup_logger
22
19
  from db_hj3415 import myredis
23
-
20
+ from analyser_hj3415.analyser import MIs, tsa
24
21
 
25
22
  mylogger = setup_logger(__name__,'WARNING')
26
23
  expire_time = tools.to_int(os.getenv('DEFAULT_EXPIRE_TIME_H', 48)) * 3600
@@ -28,6 +25,20 @@ expire_time = tools.to_int(os.getenv('DEFAULT_EXPIRE_TIME_H', 48)) * 3600
28
25
 
29
26
  @dataclass
30
27
  class LSTMData:
28
+ """
29
+ LSTM 모델에서 사용할 데이터를 저장하는 데이터 클래스.
30
+
31
+ 속성:
32
+ ticker (str): 주식 티커(symbol).
33
+ data_2d (np.ndarray): 원본 종가 데이터를 저장한 2차원 배열.
34
+ train_size (int): 학습 데이터 크기.
35
+ train_data_2d (np.ndarray): 학습 데이터 2차원 배열.
36
+ test_data_2d (np.ndarray): 테스트 데이터 2차원 배열.
37
+ X_train_3d (np.ndarray): 학습 데이터 3차원 배열.
38
+ X_test_3d (np.ndarray): 테스트 데이터 3차원 배열.
39
+ y_train_1d (np.ndarray): 학습 정답 데이터 1차원 배열.
40
+ y_test_1d (np.ndarray): 테스트 정답 데이터 1차원 배열.
41
+ """
31
42
  ticker: str
32
43
 
33
44
  data_2d: np.ndarray
@@ -44,7 +55,16 @@ class LSTMData:
44
55
  @dataclass
45
56
  class LSTMGrade:
46
57
  """
47
- 딥러닝 모델의 학습 결과를 평가하기 위해 사용하는 데이터 클래스
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²).
48
68
  """
49
69
  ticker: str
50
70
  train_mse: float
@@ -56,6 +76,16 @@ class LSTMGrade:
56
76
 
57
77
 
58
78
  class MyLSTM:
79
+ """
80
+ 주가 데이터를 기반으로 LSTM 모델을 생성, 학습 및 예측하는 클래스.
81
+
82
+ 속성:
83
+ future_days (int): 미래 예측할 일 수. 기본값은 30.
84
+ scaler (MinMaxScaler): 데이터 정규화를 위한 MinMaxScaler.
85
+ _ticker (str): 주식 티커(symbol).
86
+ raw_data (pd.DataFrame): 원본 주가 데이터.
87
+ lstm_data (LSTMData): LSTM 학습에 사용할 데이터.
88
+ """
59
89
  # 미래 몇일을 예측할 것인가?
60
90
  future_days = 30
61
91
 
@@ -102,12 +132,11 @@ class MyLSTM:
102
132
 
103
133
  def initializing(self):
104
134
  """
105
- LSTM 분석을 위해 데이터를 준비하는 과정
106
- get_final_predictions(refresh=True)를 시행하기전에 반드시 먼저 실행해줘아 한다.
135
+ LSTM 모델 학습을 위한 데이터를 준비합니다.
107
136
 
108
- Fetches stock price data for the last four years from Yahoo Finance and prepares
109
- it for use in an LSTM model by normalizing, splitting into training and testing datasets,
110
- and reshaping the data.
137
+ Yahoo Finance에서 주가 데이터를 가져와 정규화, 학습 테스트 데이터로 분리,
138
+ LSTM 모델 입력 형식으로 변환합니다. `get_final_predictions` 메서드 실행 전에
139
+ 반드시 호출해야 합니다.
111
140
  """
112
141
  def get_raw_data() -> pd.DataFrame:
113
142
  """
@@ -198,34 +227,24 @@ class MyLSTM:
198
227
  y_train_1d=y_train_1d,
199
228
  y_test_1d=y_test_1d,
200
229
  )
230
+
231
+ self.scaler = MinMaxScaler(feature_range=(0, 1))
232
+
201
233
  self.raw_data = get_raw_data()
202
234
  self.lstm_data = preprocessing_for_lstm()
203
235
 
204
236
  def ensemble_training(self, num) -> Tuple[list, LSTMGrade]:
205
237
  """
206
- Represents the implementation for training, predicting, and evaluating an LSTM-based deep learning model.
207
- Defines functions for LSTM model training, prediction, grading results, and ensemble model training.
238
+ 앙상블 LSTM 모델을 훈련하고, 예측 결과를 생성 평가합니다.
208
239
 
209
- Methods defined:
210
- - model_training: Constructs and trains the LSTM model with specified layers and configurations.
211
- - prediction: Uses a trained model to perform predictions, restores normalization, and returns results.
212
- - grading: Analyzes the training and testing predictions, computes evaluation metrics, and returns grading details.
213
- - ensemble_training: Trains multiple LSTM models to create ensemble predictions and future forecasts.
240
+ 매개변수:
241
+ num (int): 앙상블에 포함할 모델의 수.
214
242
 
215
- ensemble_training:
216
- Trains multiple LSTM models iteratively and forms ensemble predictions for training, testing datasets,
217
- and future trend forecasting. Evaluates the models collectively using grading metrics.
243
+ 반환값:
244
+ Tuple[list, LSTMGrade]: 미래 예측 리스트와 학습 결과 평가 데이터.
218
245
 
219
- Arguments:
220
- num: int
221
- The number of ensemble LSTM models to train.
222
-
223
- Returns:
224
- Tuple[list, LSTMGrade]
225
- A list of predicted scaled values for future forecasts and the performance grading object.
226
-
227
- Raises:
228
- Does not explicitly raise errors but logs warnings for possible issues during training or prediction.
246
+ 예외:
247
+ IndexError: 모델 훈련을 위한 데이터가 부족한 경우 경고 로그를 출력합니다.
229
248
  """
230
249
  def model_training() -> Sequential:
231
250
  # LSTM 모델 생성 - 유닛과 드롭아웃의 수는 테스트로 최적화 됨.
@@ -377,25 +396,18 @@ class MyLSTM:
377
396
 
378
397
  def get_final_predictions(self, refresh: bool, num=5) -> Tuple[dict, LSTMGrade]:
379
398
  """
380
- Fetch and process predictions for future data.
399
+ LSTM 모델을 사용하여 미래 주가를 예측하고 평가 데이터를 반환합니다.
381
400
 
382
- This function fetches predictions from a Redis cache or calculates predictions if the data is
383
- not found or if a refresh is requested. Predictions are determined using an ensemble training
384
- method which averages predictions to forecast future trends. Additionally, the function checks
385
- and caches whether the predicted data demonstrates an increasing trend over time.
401
+ 매개변수:
402
+ refresh (bool): 데이터 새로고침 여부.
403
+ num (int): 앙상블 모델의 수. 기본값은 5.
386
404
 
387
- Args:
388
- refresh (bool): If True, forces recalculation and cache refresh of predictions.
389
- num (int): Number of times to repeat ensemble training for more consistent predictions.
390
- Defaults to 5.
405
+ 반환값:
406
+ Tuple[dict, LSTMGrade]: 날짜별 예측 주가와 모델 평가 데이터.
391
407
 
392
- Returns:
393
- Tuple[dict, LSTMGrade]: A tuple containing a dictionary of future date-price pairs and the
394
- evaluation grade of the LSTM prediction model.
395
-
396
- Raises:
397
- AssertionError: Raised if the lengths of 'future_dates' and 'final_future_predictions' do
398
- not match during the data preparation.
408
+ 로그:
409
+ - 캐시 데이터 검색 데이터 생성 과정 출력.
410
+ - 예측 값의 증가 추세를 분석하여 캐시에 저장.
399
411
  """
400
412
  print("**** Start get_final_predictions... ****")
401
413
  redis_name = f'{self.ticker}_mylstm_predictions'
@@ -416,36 +428,8 @@ class MyLSTM:
416
428
  redis_name = f'{self.ticker}_is_lstm_up'
417
429
  print(f"redisname: '{redis_name}' / expire_time : {expire_time / 3600}h")
418
430
 
419
-
420
- if not future_data_in:
421
- # 데이터가 비어있으면 추세를 판단할 수 없음
422
- return False
423
-
424
- # 1) 날짜(키) 기준 오름차순 정렬
425
- sorted_dates = sorted(future_data_in.keys())
426
- values = [future_data_in[d] for d in sorted_dates]
427
-
428
- # 2) x 축을 0,1,2... 형태로 부여 (날짜 간격을 동일하게 가정)
429
- x = np.arange(len(values), dtype=float)
430
- y = np.array(values, dtype=float)
431
-
432
- # 3) 선형 회귀(최소제곱법)로 기울기(slope) 계산
433
- x_mean = np.mean(x)
434
- y_mean = np.mean(y)
435
-
436
- # 분자: sum((xi - x_mean) * (yi - y_mean))
437
- numerator = np.sum((x - x_mean) * (y - y_mean))
438
- # 분모: sum((xi - x_mean)^2)
439
- denominator = np.sum((x - x_mean) ** 2)
440
-
441
- if denominator == 0:
442
- # 데이터가 1개 이하인 경우 등
443
- return False
444
-
445
- slope = numerator / denominator
446
-
447
- # 4) 기울기가 양수면 "우상향 추세"로 판별
448
- is_up = slope > 0
431
+ is_up = tsa.common.is_up_by_OLS(future_data_in)
432
+ mylogger.debug(f"is_up: {is_up}")
449
433
  myredis.Base.set_value(redis_name, is_up, expire_time)
450
434
 
451
435
  def fetch_final_predictions(num_in) -> tuple:
@@ -472,6 +456,7 @@ class MyLSTM:
472
456
  data[future_dates[i].strftime("%Y-%m-%d")] = final_future_predictions[i][0]
473
457
  return data
474
458
 
459
+ self.initializing()
475
460
  # 앙상블 트레이닝 시행
476
461
  future_predictions_2d, lstm_grade = self.ensemble_training(num=num_in)
477
462
  mylogger.debug(f'future_predictions_2d[:5] : {future_predictions_2d[:5]}')
@@ -492,32 +477,21 @@ class MyLSTM:
492
477
 
493
478
  return future_data, lstm_grade
494
479
 
495
- def export(self, refresh=False, to="str", num=5) -> Optional[str]:
480
+ def export(self, refresh=False, to="html", num=5) -> Optional[str]:
496
481
  """
497
- Prepares and exports stock price trend graphs based on past and predicted data.
498
- The graphs include markers for actual prices along with a line-plot for forecasted prices.
499
- The function offers multiple export formats: an HTML string, a PNG file, or an HTML file.
500
-
501
- Parameters
502
- ----------
503
- refresh : bool, optional
504
- Specifies whether to refresh dataset before preparing future data. Defaults to False.
505
- to : str, optional
506
- Determines the export format of the graph. Valid choices are
507
- 'str', 'png', or 'htmlfile'. Defaults to 'str'.
508
- num : int, optional
509
- Specifies the number of future days to include in prediction. Defaults to 5.
510
-
511
- Returns
512
- -------
513
- Optional[str]
514
- A string representation of the graph in HTML format if `to` is set to 'str'.
515
- Returns None if `to` is set to either 'png' or 'htmlfile'.
516
-
517
- Raises
518
- ------
519
- Exception
520
- Raised if the `to` parameter does not match the allowed values: 'str', 'png', or 'htmlfile'.
482
+ 과거 예측된 주가 데이터를 기반으로 시각화를 생성하고 저장합니다.
483
+
484
+ 매개변수:
485
+ refresh (bool): 데이터 새로고침 여부. 기본값은 False.
486
+ to (str): 그래프 출력 형식 ('hrml', 'png', 'file'). 기본값은 'html'.
487
+ num (int): 예측 모델 수. 기본값은 5.
488
+
489
+ 반환값:
490
+ Optional[str]: HTML 형식의 그래프 문자열(`to='html'`인 경우).
491
+ None: PNG 또는 HTML 파일로 저장된 경우.
492
+
493
+ 예외:
494
+ Exception: 잘못된 `to` 값이 주어졌을 발생.
521
495
  """
522
496
  def prepare_past_data(past_days) -> tuple:
523
497
  # 데이터 준비
@@ -599,7 +573,7 @@ class MyLSTM:
599
573
  showlegend=False,
600
574
  )
601
575
 
602
- if to == 'str':
576
+ if to == 'html':
603
577
  # 그래프 HTML로 변환 (string 형식으로 저장)
604
578
  graph_html = plot(fig, output_type='div')
605
579
  return graph_html
@@ -607,7 +581,7 @@ class MyLSTM:
607
581
  # 그래프를 PNG 파일로 저장
608
582
  fig.write_image(f"myLSTM_{self.ticker}.png")
609
583
  return None
610
- elif to == 'htmlfile':
584
+ elif to == 'file':
611
585
  # 그래프를 HTML로 저장
612
586
  plot(fig, filename=f'myLSTM_{self.ticker}.html', auto_open=False)
613
587
  return None
@@ -616,24 +590,13 @@ class MyLSTM:
616
590
 
617
591
  def visualization(self, refresh=True):
618
592
  """
619
- Visualizes actual and predicted stock prices, allowing for an evaluation of the
620
- predictions made using a Long Short-Term Memory (LSTM) model. The visualization
621
- includes plots for both future predicted prices and historical price comparisons
622
- for improved insights.
623
-
624
- Parameters
625
- ----------
626
- refresh : bool, optional
627
- Indicates whether to refresh and retrieve the latest predictions before
628
- visualizing. Defaults to True.
629
-
630
- Raises
631
- ------
632
- None
633
-
634
- Returns
635
- -------
636
- None
593
+ 실제 주가와 예측 주가를 시각화합니다.
594
+
595
+ 매개변수:
596
+ refresh (bool): 예측 데이터를 새로고침할지 여부. 기본값은 True.
597
+
598
+ 반환값:
599
+ None: 시각화를 출력합니다.
637
600
  """
638
601
  self.initializing()
639
602
  future_data, _ = self.get_final_predictions(refresh=refresh)
@@ -670,18 +633,22 @@ class MyLSTM:
670
633
 
671
634
  def is_lstm_up(self) -> bool:
672
635
  """
673
- Determines whether the LSTM model is active or not.
636
+ LSTM 모델의 추세가 상승인지 여부를 확인합니다.
674
637
 
675
- This method checks the status of an LSTM model by querying a Redis
676
- value identified by a specific code indicating LSTM activity.
677
-
678
- Returns:
679
- bool: True if the LSTM model is active (up), False otherwise.
638
+ 반환값:
639
+ bool: 추세가 상승 상태(True) 또는 추세가 하락 상태(False).
680
640
  """
681
641
  return myredis.Base.get_value(f'{self.ticker}_is_lstm_up')
682
642
 
683
643
 
684
644
  class CorpLSTM(MyLSTM):
645
+ """
646
+ 특정 기업 코드를 기반으로 주가를 예측하는 LSTM 클래스.
647
+
648
+ 속성:
649
+ code (str): 기업 코드.
650
+ name (str): 기업명.
651
+ """
685
652
  def __init__(self, code: str):
686
653
  assert tools.is_6digit(code), f'Invalid value : {code}'
687
654
  self._code = code
@@ -701,11 +668,16 @@ class CorpLSTM(MyLSTM):
701
668
 
702
669
 
703
670
  class MILSTM(MyLSTM):
671
+ """
672
+ 특정 MI 타입에 따라 주가를 예측하는 LSTM 클래스.
673
+
674
+ 속성:
675
+ mi_type (str): MI 타입.
676
+ """
704
677
  def __init__(self, mi_type: str):
705
- from analyser_hj3415.analyser.tsa import MIs
706
- assert mi_type in MIs.keys(), f"Invalid MI type ({MIs.keys()})"
678
+ assert mi_type in MIs._fields, f"Invalid MI type ({MIs._fields})"
707
679
  self._mi_type = mi_type
708
- super().__init__(ticker=MIs[mi_type])
680
+ super().__init__(ticker=getattr(MIs, mi_type))
709
681
 
710
682
  @property
711
683
  def mi_type(self) -> str:
@@ -713,8 +685,7 @@ class MILSTM(MyLSTM):
713
685
 
714
686
  @mi_type.setter
715
687
  def mi_type(self, mi_type: str):
716
- from analyser_hj3415.analyser.tsa import MIs
717
- assert mi_type in MIs.keys(), f"Invalid MI type ({MIs.keys()})"
688
+ assert mi_type in MIs._fields, f"Invalid MI type ({MIs._fields})"
718
689
  self._mi_type = mi_type
719
- self.ticker = MIs[mi_type]
690
+ self.ticker = getattr(MIs, mi_type)
720
691