neurostats-API 0.0.14__tar.gz → 0.0.16__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. {neurostats_api-0.0.14/neurostats_API.egg-info → neurostats_api-0.0.16}/PKG-INFO +122 -2
  2. neurostats_api-0.0.14/PKG-INFO → neurostats_api-0.0.16/README.md +116 -12
  3. neurostats_api-0.0.16/neurostats_API/__init__.py +13 -0
  4. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/__init__.py +2 -0
  5. neurostats_api-0.0.16/neurostats_API/fetchers/base.py +154 -0
  6. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/tech.py +34 -7
  7. neurostats_api-0.0.16/neurostats_API/fetchers/tej_finance_report.py +339 -0
  8. neurostats_api-0.0.16/neurostats_API/fetchers/value_invest.py +187 -0
  9. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/utils/__init__.py +2 -1
  10. neurostats_api-0.0.16/neurostats_API/utils/calculate_value.py +26 -0
  11. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/utils/data_process.py +56 -1
  12. neurostats_api-0.0.14/README.md → neurostats_api-0.0.16/neurostats_API.egg-info/PKG-INFO +132 -2
  13. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API.egg-info/SOURCES.txt +5 -1
  14. neurostats_api-0.0.16/neurostats_API.egg-info/requires.txt +6 -0
  15. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/setup.py +7 -1
  16. neurostats_api-0.0.16/test/test_tej.py +26 -0
  17. neurostats_api-0.0.14/neurostats_API/__init__.py +0 -1
  18. neurostats_api-0.0.14/neurostats_API/fetchers/base.py +0 -54
  19. neurostats_api-0.0.14/neurostats_API/fetchers/value_invest.py +0 -170
  20. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/MANIFEST.in +0 -0
  21. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/cli.py +0 -0
  22. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/balance_sheet.py +0 -0
  23. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/cash_flow.py +0 -0
  24. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/finance_overview.py +0 -0
  25. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/institution.py +0 -0
  26. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/margin_trading.py +0 -0
  27. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/month_revenue.py +0 -0
  28. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/fetchers/profit_lose.py +0 -0
  29. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/main.py +0 -0
  30. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/tools/balance_sheet.yaml +0 -0
  31. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/tools/cash_flow_percentage.yaml +0 -0
  32. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/tools/finance_overview_dict.yaml +0 -0
  33. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/tools/profit_lose.yaml +0 -0
  34. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/tools/seasonal_data_field_dict.txt +0 -0
  35. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/utils/datetime.py +0 -0
  36. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/utils/db_client.py +0 -0
  37. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API/utils/fetcher.py +0 -0
  38. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API.egg-info/dependency_links.txt +0 -0
  39. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/neurostats_API.egg-info/top_level.txt +0 -0
  40. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/setup.cfg +0 -0
  41. {neurostats_api-0.0.14 → neurostats_api-0.0.16}/test/test_fetchers.py +0 -0
@@ -1,12 +1,18 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: neurostats_API
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: The service of NeuroStats website
5
5
  Home-page: https://github.com/NeurowattStats/NeuroStats_API.git
6
6
  Author: JasonWang@Neurowatt
7
7
  Author-email: jason@neurowatt.ai
8
8
  Requires-Python: >=3.6
9
9
  Description-Content-Type: text/markdown
10
+ Requires-Dist: numpy>=2.1.0
11
+ Requires-Dist: pandas>=2.2.0
12
+ Requires-Dist: pymongo
13
+ Requires-Dist: pytz
14
+ Requires-Dist: python-dotenv
15
+ Requires-Dist: yfinance
10
16
 
11
17
  # neurostats_API
12
18
 
@@ -83,7 +89,7 @@ pip install neurostats-API
83
89
  ```Python
84
90
  >>> import neurostats_API
85
91
  >>> print(neurostats_API.__version__)
86
- 0.0.14
92
+ 0.0.16
87
93
  ```
88
94
 
89
95
  ### 得到最新一期的評價資料與歷年評價
@@ -667,7 +673,121 @@ fetcher.query()
667
673
 
668
674
  請注意`range`, `last_range`, `52week_range`這三個項目型態為字串,其餘為float
669
675
 
676
+
677
+ ## TEJ 相關
678
+ ### 會計師簽證財務資料
679
+ ```Python
680
+ from neurostats_API import FinanceReportFetcher
681
+
682
+ mongo_uri = <MongoDB 的 URI>
683
+ db_name = 'company' # 連接的DB名稱
684
+ collection_name = "TWN/AINVFQ1" # 連接的collection對象
685
+
686
+ fetcher = FinanceReportFetcher(
687
+ mongo_uri = mongo_uri,
688
+ db_name = db_name,
689
+ collection_name = collection_name
690
+ )
691
+
692
+ data = fetcher.get(
693
+ ticker = "2330" # 任意的股票代碼
694
+ fetch_mode = fetcher.FetchMode.QOQ_NOCAL # 取得模式
695
+ start_date = "2005-01-01",
696
+ end_date = "2024-12-31",
697
+ report_type = "Q",
698
+ indexes = []
699
+ ) # -> pd.DataFrame or Dict[pd.DataFrame]
700
+ ```
701
+ - `ticker`: 股票代碼
702
+
703
+ - `fetch_mode` : 取得模式,為`fetcher.YOY_NOCAL` 或 `fetcher.QOQ_NOCAL`
704
+ - `YOY_NOCAL`: 以end_date為準,取得與end_date同季的歷年資料,時間範圍以start_date為起始
705
+ > 例如`start_date = "2020-07-01"`, `end_date = "2024-01-01"`,會回傳2020~2024的第一季資料
706
+
707
+ - `QOQ_NOCAL`: 時間範圍內的每季資料
708
+
709
+ - `QOQ`: 時間範圍內每季的每個index的數值以及QoQ
710
+
711
+ - `YoY`: 以end_date為準,取得與end_date同季的歷年資料以及成長率,時間範圍以start_date為起始
712
+
713
+ - `start_date`: 開始日期,不設定時預設為`2005-01-01`
714
+
715
+ - `end_date`: 結束日期,不設定時預設為資料庫最新資料的日期
716
+
717
+ - `report_type`: 選擇哪種報告,預設為`Q`
718
+ - `A`: 當年累計
719
+ - `Q`: 當季數值
720
+ - `TTM`: 移動四季 (包括當季在內,往前累計四個季度)
721
+
722
+ - `indexes`: 選擇的column,需要以TEJ提供的欄位名稱為準,不提供時或提供`[]`會回傳全部column
723
+ - 範例輸入: `['bp41', 'bp51']`
724
+
725
+ [TEJ資料集連結](https://tquant.tejwin.com/%E8%B3%87%E6%96%99%E9%9B%86/)
726
+ 請看 `會計師簽證財務資料`
727
+
728
+ #### 回傳資料
729
+ ##### `YOY_NOCAL` 與 `QOQ_NOCAL`
730
+ 為回傳`pd.DataFrame`,column名稱為<年份>Q<季>, row名稱為指定財報項目
731
+ ```Python
732
+ # fetch_mode = fetcher.FetchMode.QOQ_NOCAL
733
+ 2024Q3 2024Q2 2024Q1
734
+ bp41 7.082005e+07 6.394707e+07 5.761001e+07
735
+ bp51 3.111298e+09 3.145373e+09 3.091985e+09
736
+
737
+ # fetch_mode = fetcher.FetchMode.YOY_NOCAL
738
+ 2024Q3 2023Q3 2022Q3
739
+ bp41 7.082005e+07 5.377231e+07 6.201822e+07
740
+ bp51 3.111298e+09 3.173919e+09 2.453840e+09
741
+ ```
742
+
743
+ ##### `YOY` 與 `QOQ`
744
+ 回傳為`Dict[pd.DataFrame]`, key 為指定的index, DataFrame中則是該index歷年的數值與成長率
745
+ ```Python
746
+ # fetch_mode = fetcher.FetchMode.QOQ
747
+ {
748
+ 'bp41':
749
+ 2024Q3 2024Q2 2024Q1
750
+ value 7.082005e+07 6.394707e+07 5.761001e+07
751
+ growth 1.074791e-01 1.099994e-01 5.532101e-03,
752
+ 'bp51':
753
+ 2024Q3 2024Q2 2024Q1
754
+ value 3.111298e+09 3.145373e+09 3.091985e+09
755
+ growth -1.083335e-02 1.726663e-02 -4.159542e-03
756
+ }
757
+
758
+ # fetch_mode = fetcher.FetchMode.YOY
759
+ {
760
+ 'bp41':
761
+ 2024Q3 2023Q3 2022Q3
762
+ value 7.082005e+07 5.377231e+07 6.201822e+07
763
+ YoY_1 NaN NaN 4.130744e-01
764
+ YoY_3 1.729171e-01 9.556684e-02 1.883274e-01
765
+ YoY_5 1.389090e-01 1.215242e-01 1.642914e-01
766
+ YoY_10 1.255138e-01 1.356297e-01 1.559702e-01,
767
+ 'bp51':
768
+ 2024Q3 2023Q3 2022Q3
769
+ value 3.111298e+09 3.173919e+09 2.453840e+09
770
+ YoY_1 NaN NaN 3.179539e-01
771
+ YoY_3 1.866752e-01 2.766851e-01 2.638677e-01
772
+ YoY_5 2.068132e-01 2.479698e-01 1.815106e-01
773
+ YoY_10 1.420500e-01 1.586797e-01 1.551364e-01
774
+ }
775
+ ```
776
+
777
+
670
778
  ## 版本紀錄
779
+ ## 0.0.16
780
+ - 處理ValueFetcher的error #issue76
781
+
782
+ - tej_fetcher新增 QOQ, YOY功能
783
+
784
+ ## 0.0.15
785
+ - TechFetcher中新增指數條件
786
+
787
+ - 新增tej_fetcher索取TEJ相關的資料
788
+
789
+ - package新增depensnecy,可以安裝需要的相關package
790
+
671
791
  ## 0.0.14
672
792
  - 修改部分財報資料錯誤的乘以1000的問題
673
793
 
@@ -1,13 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: neurostats_API
3
- Version: 0.0.14
4
- Summary: The service of NeuroStats website
5
- Home-page: https://github.com/NeurowattStats/NeuroStats_API.git
6
- Author: JasonWang@Neurowatt
7
- Author-email: jason@neurowatt.ai
8
- Requires-Python: >=3.6
9
- Description-Content-Type: text/markdown
10
-
11
1
  # neurostats_API
12
2
 
13
3
  - [檔案架構](#檔案架構)
@@ -83,7 +73,7 @@ pip install neurostats-API
83
73
  ```Python
84
74
  >>> import neurostats_API
85
75
  >>> print(neurostats_API.__version__)
86
- 0.0.14
76
+ 0.0.16
87
77
  ```
88
78
 
89
79
  ### 得到最新一期的評價資料與歷年評價
@@ -667,7 +657,121 @@ fetcher.query()
667
657
 
668
658
  請注意`range`, `last_range`, `52week_range`這三個項目型態為字串,其餘為float
669
659
 
660
+
661
+ ## TEJ 相關
662
+ ### 會計師簽證財務資料
663
+ ```Python
664
+ from neurostats_API import FinanceReportFetcher
665
+
666
+ mongo_uri = <MongoDB 的 URI>
667
+ db_name = 'company' # 連接的DB名稱
668
+ collection_name = "TWN/AINVFQ1" # 連接的collection對象
669
+
670
+ fetcher = FinanceReportFetcher(
671
+ mongo_uri = mongo_uri,
672
+ db_name = db_name,
673
+ collection_name = collection_name
674
+ )
675
+
676
+ data = fetcher.get(
677
+ ticker = "2330" # 任意的股票代碼
678
+ fetch_mode = fetcher.FetchMode.QOQ_NOCAL # 取得模式
679
+ start_date = "2005-01-01",
680
+ end_date = "2024-12-31",
681
+ report_type = "Q",
682
+ indexes = []
683
+ ) # -> pd.DataFrame or Dict[pd.DataFrame]
684
+ ```
685
+ - `ticker`: 股票代碼
686
+
687
+ - `fetch_mode` : 取得模式,為`fetcher.YOY_NOCAL` 或 `fetcher.QOQ_NOCAL`
688
+ - `YOY_NOCAL`: 以end_date為準,取得與end_date同季的歷年資料,時間範圍以start_date為起始
689
+ > 例如`start_date = "2020-07-01"`, `end_date = "2024-01-01"`,會回傳2020~2024的第一季資料
690
+
691
+ - `QOQ_NOCAL`: 時間範圍內的每季資料
692
+
693
+ - `QOQ`: 時間範圍內每季的每個index的數值以及QoQ
694
+
695
+ - `YoY`: 以end_date為準,取得與end_date同季的歷年資料以及成長率,時間範圍以start_date為起始
696
+
697
+ - `start_date`: 開始日期,不設定時預設為`2005-01-01`
698
+
699
+ - `end_date`: 結束日期,不設定時預設為資料庫最新資料的日期
700
+
701
+ - `report_type`: 選擇哪種報告,預設為`Q`
702
+ - `A`: 當年累計
703
+ - `Q`: 當季數值
704
+ - `TTM`: 移動四季 (包括當季在內,往前累計四個季度)
705
+
706
+ - `indexes`: 選擇的column,需要以TEJ提供的欄位名稱為準,不提供時或提供`[]`會回傳全部column
707
+ - 範例輸入: `['bp41', 'bp51']`
708
+
709
+ [TEJ資料集連結](https://tquant.tejwin.com/%E8%B3%87%E6%96%99%E9%9B%86/)
710
+ 請看 `會計師簽證財務資料`
711
+
712
+ #### 回傳資料
713
+ ##### `YOY_NOCAL` 與 `QOQ_NOCAL`
714
+ 為回傳`pd.DataFrame`,column名稱為<年份>Q<季>, row名稱為指定財報項目
715
+ ```Python
716
+ # fetch_mode = fetcher.FetchMode.QOQ_NOCAL
717
+ 2024Q3 2024Q2 2024Q1
718
+ bp41 7.082005e+07 6.394707e+07 5.761001e+07
719
+ bp51 3.111298e+09 3.145373e+09 3.091985e+09
720
+
721
+ # fetch_mode = fetcher.FetchMode.YOY_NOCAL
722
+ 2024Q3 2023Q3 2022Q3
723
+ bp41 7.082005e+07 5.377231e+07 6.201822e+07
724
+ bp51 3.111298e+09 3.173919e+09 2.453840e+09
725
+ ```
726
+
727
+ ##### `YOY` 與 `QOQ`
728
+ 回傳為`Dict[pd.DataFrame]`, key 為指定的index, DataFrame中則是該index歷年的數值與成長率
729
+ ```Python
730
+ # fetch_mode = fetcher.FetchMode.QOQ
731
+ {
732
+ 'bp41':
733
+ 2024Q3 2024Q2 2024Q1
734
+ value 7.082005e+07 6.394707e+07 5.761001e+07
735
+ growth 1.074791e-01 1.099994e-01 5.532101e-03,
736
+ 'bp51':
737
+ 2024Q3 2024Q2 2024Q1
738
+ value 3.111298e+09 3.145373e+09 3.091985e+09
739
+ growth -1.083335e-02 1.726663e-02 -4.159542e-03
740
+ }
741
+
742
+ # fetch_mode = fetcher.FetchMode.YOY
743
+ {
744
+ 'bp41':
745
+ 2024Q3 2023Q3 2022Q3
746
+ value 7.082005e+07 5.377231e+07 6.201822e+07
747
+ YoY_1 NaN NaN 4.130744e-01
748
+ YoY_3 1.729171e-01 9.556684e-02 1.883274e-01
749
+ YoY_5 1.389090e-01 1.215242e-01 1.642914e-01
750
+ YoY_10 1.255138e-01 1.356297e-01 1.559702e-01,
751
+ 'bp51':
752
+ 2024Q3 2023Q3 2022Q3
753
+ value 3.111298e+09 3.173919e+09 2.453840e+09
754
+ YoY_1 NaN NaN 3.179539e-01
755
+ YoY_3 1.866752e-01 2.766851e-01 2.638677e-01
756
+ YoY_5 2.068132e-01 2.479698e-01 1.815106e-01
757
+ YoY_10 1.420500e-01 1.586797e-01 1.551364e-01
758
+ }
759
+ ```
760
+
761
+
670
762
  ## 版本紀錄
763
+ ## 0.0.16
764
+ - 處理ValueFetcher的error #issue76
765
+
766
+ - tej_fetcher新增 QOQ, YOY功能
767
+
768
+ ## 0.0.15
769
+ - TechFetcher中新增指數條件
770
+
771
+ - 新增tej_fetcher索取TEJ相關的資料
772
+
773
+ - package新增depensnecy,可以安裝需要的相關package
774
+
671
775
  ## 0.0.14
672
776
  - 修改部分財報資料錯誤的乘以1000的問題
673
777
 
@@ -693,4 +797,4 @@ fetcher.query()
693
797
  - 處理銀行公司在finanace_overview會報錯誤的問題(未完全解決,因銀行公司財報有許多名稱不同,目前都會顯示為None)
694
798
 
695
799
  ### 0.0.9
696
- - 更新指標的資料型態: 單位為日, %, 倍轉為字串
800
+ - 更新指標的資料型態: 單位為日, %, 倍轉為字串
@@ -0,0 +1,13 @@
1
+ __version__='0.0.16'
2
+
3
+ from .fetchers import (
4
+ BalanceSheetFetcher,
5
+ CashFlowFetcher,
6
+ FinanceOverviewFetcher,
7
+ FinanceReportFetcher,
8
+ InstitutionFetcher,
9
+ MarginTradingFetcher,
10
+ MonthRevenueFetcher,
11
+ TechFetcher,
12
+ ProfitLoseFetcher
13
+ )
@@ -2,6 +2,8 @@ from .base import StatsDateTime, StatsFetcher
2
2
  from .balance_sheet import BalanceSheetFetcher
3
3
  from .cash_flow import CashFlowFetcher
4
4
  from .finance_overview import FinanceOverviewFetcher
5
+ from .tej_finance_report import FinanceReportFetcher
6
+ from .tech import TechFetcher
5
7
  from .institution import InstitutionFetcher
6
8
  from .margin_trading import MarginTradingFetcher
7
9
  from .month_revenue import MonthRevenueFetcher
@@ -0,0 +1,154 @@
1
+ import abc
2
+ from pymongo import MongoClient
3
+ import pandas as pd
4
+ import json
5
+ import pytz
6
+ from datetime import datetime, timedelta, date
7
+ from ..utils import StatsDateTime, StatsProcessor, YoY_Calculator
8
+ import yaml
9
+
10
+
11
+ class StatsFetcher:
12
+
13
+ def __init__(self, ticker, db_client):
14
+ self.ticker = ticker
15
+ self.db = db_client["company"] # Replace with your database name
16
+ self.collection = self.db["twse_stats"]
17
+
18
+ self.timezone = pytz.timezone("Asia/Taipei")
19
+
20
+ self.target_metric_dict = {
21
+ 'value': ['value'],
22
+ 'value_and_percentage': ['value', 'percentage'],
23
+ 'percentage': ['percentage'],
24
+ 'grand_total': ['grand_total'],
25
+ 'grand_total_values': ['grand_total', 'grand_total_percentage'],
26
+ 'grand_total_percentage': ['grand_total_percentage'],
27
+ 'growth': [f'YoY_{i}' for i in [1, 3, 5, 10]],
28
+ 'grand_total_growth': [f"YoY_{i}" for i in [1, 3, 5, 10]]
29
+ }
30
+
31
+ def prepare_query(self):
32
+ return [
33
+ {
34
+ "$match": {
35
+ "ticker": self.ticker,
36
+ }
37
+ },
38
+ ]
39
+
40
+ def collect_data(self, start_date, end_date):
41
+ pipeline = self.prepare_query()
42
+
43
+ fetched_data = list(self.collection.aggregate(pipeline))
44
+
45
+ return fetched_data[0]
46
+
47
+ def str_to_datetime(self, date_str):
48
+ year, month, day = [int(num) for num in date_str.split("-")]
49
+
50
+ date = datetime.strptime(date_str, "%Y-%m-%d")
51
+ date = self.timezone.localize(date)
52
+
53
+ season = (month - 1) // 3 + 1
54
+
55
+ return StatsDateTime(date, year, month, day, season)
56
+
57
+
58
+ class BaseTEJFetcher(abc.ABC):
59
+
60
+ def __init__(self):
61
+ self.client = None
62
+ self.db = None
63
+ self.collection = None
64
+
65
+ @abc.abstractmethod
66
+ def get(self):
67
+ pass
68
+
69
+ def get_latest_data_time(self, ticker):
70
+ latest_data = self.collection.find_one({"ticker": ticker}, {"last_update": 1, "_id": 0})
71
+
72
+ try:
73
+ latest_date = latest_data['last_update']["latest_data_date"]
74
+ except Exception as e:
75
+ latest_date = None
76
+
77
+ return latest_date
78
+
79
+ def cal_YoY(self, data_dict: dict, start_year: int, end_year: int, season: int):
80
+ year_shifts = [1, 3, 5, 10]
81
+ return_dict = {}
82
+ for year in range(start_year, end_year + 1):
83
+ year_data = data_dict[f"{year}Q{season}"]
84
+ year_keys = list(year_data.keys())
85
+ for key in year_keys:
86
+ if (key in 'season'):
87
+ continue
88
+
89
+ if (isinstance(year_data[key], (int, float))):
90
+ temp_dict = {"value": year_data[key]}
91
+
92
+ for shift in year_shifts:
93
+ this_value = year_data[key]
94
+ try:
95
+ past_year = str(year - shift)
96
+ last_value = data_dict[f"{past_year}Q{season}"][key]
97
+ temp_dict[f"YoY_{shift}"] = YoY_Calculator.cal_growth(this_value, last_value, delta=shift)
98
+ except Exception as e:
99
+ temp_dict[f"YoY_{shift}"] = None
100
+
101
+ year_data[key] = temp_dict
102
+
103
+ else:
104
+ year_data.pop(key)
105
+
106
+ return_dict[f"{year}Q{season}"] = year_data
107
+
108
+ return return_dict
109
+
110
+ def cal_QoQ(self, data_dict):
111
+ return_dict = {}
112
+ for i, time_index in enumerate(data_dict.keys()):
113
+ year, season = time_index.split("Q")
114
+ year = int(year)
115
+ season = int(season)
116
+ if (season == 1):
117
+ last_year = year - 1
118
+ last_season = 4
119
+ else:
120
+ last_year = year
121
+ last_season = season - 1
122
+
123
+ this_data = data_dict[time_index]
124
+ this_keys = list(this_data.keys())
125
+ for key in this_keys:
126
+ if (key in 'season'):
127
+ continue
128
+
129
+ this_value = this_data[key]
130
+
131
+ if (isinstance(this_value, (int, float))):
132
+ temp_dict = {"value": this_value}
133
+
134
+ try:
135
+ last_value = data_dict[f"{last_year}Q{last_season}"][key]['value']
136
+
137
+ temp_dict['growth'] = YoY_Calculator.cal_growth(this_value, last_value, delta=1)
138
+ except Exception as e:
139
+ temp_dict['growth'] = None
140
+
141
+ this_data[key] = temp_dict
142
+
143
+ else:
144
+ this_data.pop(key)
145
+ return_dict[time_index] = this_data
146
+ return return_dict
147
+
148
+ def get_dict_of_df(self, data_dict):
149
+ """
150
+ dict[dict] -> dict[df]
151
+ """
152
+ for key in data_dict.keys():
153
+ data_dict[key] = pd.DataFrame.from_dict(data_dict[key])
154
+ return data_dict
@@ -1,9 +1,16 @@
1
1
  from .base import StatsFetcher
2
2
  import pandas as pd
3
+ import yfinance as yf
3
4
 
4
5
  class TechFetcher(StatsFetcher):
5
6
 
6
7
  def __init__(self, ticker:str, db_client):
8
+
9
+ """
10
+ The Capitalization-Weighted Index includes the following tickers:
11
+ ['GSPC', 'IXIC', 'DJI', 'TWII']
12
+ """
13
+
7
14
  super().__init__(ticker, db_client)
8
15
  self.full_ohlcv = self._get_ohlcv()
9
16
  self.basic_indexes = ['SMA5', 'SMA20', 'SMA60', 'EMA5', 'EMA20',
@@ -40,16 +47,36 @@ class TechFetcher(StatsFetcher):
40
47
  )
41
48
 
42
49
  def _get_ohlcv(self):
43
- query = {'ticker': self.ticker}
44
- ticker_full = list(self.collection.find(query))
50
+
51
+ if self.ticker in ['GSPC', 'IXIC', 'DJI', 'TWII']:
52
+
53
+ full_tick = f'^{self.ticker}'
54
+ yf_ticker = yf.Ticker(full_tick)
55
+ origin_df = yf_ticker.history(period="10y")
56
+ origin_df = origin_df.reset_index()
57
+ origin_df["Date"] = pd.to_datetime(origin_df["Date"]).dt.date
58
+ df = origin_df.rename(
59
+ columns={
60
+ "Date": "date",
61
+ "Open": "open",
62
+ "High": "high",
63
+ "Low": "low",
64
+ "Close": "close",
65
+ "Volume": "volume"
66
+ }
67
+ )
68
+ else:
69
+
70
+ query = {'ticker': self.ticker}
71
+ ticker_full = list(self.collection.find(query))
45
72
 
46
- if not ticker_full:
47
- raise ValueError(f"No data found for ticker: {self.ticker}")
73
+ if not ticker_full:
74
+ raise ValueError(f"No data found for ticker: {self.ticker}")
48
75
 
49
- if 'daily_data' not in ticker_full[0] or ticker_full[0]['daily_data'] is None:
50
- raise KeyError("Missing 'daily_data' in the retrieved data")
76
+ if 'daily_data' not in ticker_full[0] or ticker_full[0]['daily_data'] is None:
77
+ raise KeyError("Missing 'daily_data' in the retrieved data")
51
78
 
52
- df = pd.DataFrame(ticker_full[0]['daily_data'])
79
+ df = pd.DataFrame(ticker_full[0]['daily_data'])
53
80
 
54
81
  selected_cols = ['date','open','high','low','close','volume']
55
82