MultiFactor 0.1.7__tar.gz → 0.2.1__tar.gz

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.
Files changed (26) hide show
  1. {multifactor-0.1.7 → multifactor-0.2.1}/PKG-INFO +1 -1
  2. {multifactor-0.1.7 → multifactor-0.2.1}/pyproject.toml +1 -1
  3. multifactor-0.2.1/src/MultiFactor/__init__.py +8 -0
  4. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/core.py +168 -168
  5. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/momentum.py +82 -82
  6. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/momentum_one.py +74 -74
  7. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/quality.py +35 -35
  8. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/quality_one.py +20 -20
  9. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/score.py +54 -54
  10. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/score_adj_weight.py +57 -57
  11. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/stockinfo.py +41 -41
  12. multifactor-0.2.1/src/MultiFactor/us_core.py +108 -0
  13. multifactor-0.2.1/src/MultiFactor/us_momentum.py +78 -0
  14. multifactor-0.2.1/src/MultiFactor/us_quality.py +42 -0
  15. multifactor-0.2.1/src/MultiFactor/us_stockinfo.py +49 -0
  16. multifactor-0.2.1/src/MultiFactor/us_value.py +39 -0
  17. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/value.py +33 -33
  18. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor/value_one.py +22 -22
  19. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor.egg-info/PKG-INFO +1 -1
  20. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor.egg-info/SOURCES.txt +5 -0
  21. multifactor-0.1.7/src/MultiFactor/__init__.py +0 -7
  22. {multifactor-0.1.7 → multifactor-0.2.1}/README.md +0 -0
  23. {multifactor-0.1.7 → multifactor-0.2.1}/setup.cfg +0 -0
  24. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor.egg-info/dependency_links.txt +0 -0
  25. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor.egg-info/requires.txt +0 -0
  26. {multifactor-0.1.7 → multifactor-0.2.1}/src/MultiFactor.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MultiFactor
3
- Version: 0.1.7
3
+ Version: 0.2.1
4
4
  Summary: 멀티팩터 기반 주식 데이터 수집 패키지
5
5
  Author-email: HANHO <hanhoman@gmail.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  # 1. PyPI에 등록될 배포 이름 (pip install MultiFactor)
7
7
  name = "MultiFactor"
8
- version = "0.1.7"
8
+ version = "0.2.1"
9
9
  authors = [
10
10
  { name="HANHO", email="hanhoman@gmail.com" },
11
11
  ]
@@ -0,0 +1,8 @@
1
+ # src/MultiFactor/__init__.py
2
+
3
+ # 같은 폴더의 core.py/us_core.py에서 클래스를 가져옵니다.
4
+ from .core import MultiFactor
5
+ from .us_core import MultiFactorUS
6
+
7
+ # 패키지를 import할 때 노출할 항목을 명시합니다.
8
+ __all__ = ['MultiFactor', 'MultiFactorUS']
@@ -1,168 +1,168 @@
1
- #!pip install finance-datareader
2
-
3
- import FinanceDataReader as fdr
4
-
5
- import pandas as pd
6
- import numpy as np
7
-
8
- import time
9
-
10
- from . import stockinfo as sinfo
11
-
12
- from . import momentum as mom
13
- from . import value as val
14
- from . import quality as qual
15
-
16
- from . import momentum_one as mom1
17
- from . import value_one as val1
18
- from . import quality_one as qual1
19
-
20
- from . import score as sc
21
- from . import score_adj_weight as scw
22
-
23
-
24
-
25
- class MultiFactor:
26
- def __init__(self, N: int):
27
- """
28
- 멀티팩터 : 분석 대상 종목수 (시가총액 상위 N개)
29
- """
30
- self.N = N
31
-
32
-
33
- def get_stockinfo(self, dtype='dataframe') -> pd.DataFrame:
34
-
35
- df = sinfo.get_stockinfo(self.N)
36
-
37
- if dtype=='dic':
38
- # 종목 정보 사전 저장
39
- stock_list = dict(zip(df['Code'], df['Name']))
40
- return stock_list
41
-
42
- else:
43
- return df
44
-
45
-
46
-
47
- def get_momentum(self, stock_list) -> pd.DataFrame:
48
- """
49
- 모멘텀
50
- """
51
- data_mom = mom.get_momentum(stock_list)
52
- return data_mom
53
-
54
-
55
- def get_momentum_one(self, scode) -> pd.DataFrame:
56
- """
57
- 모멘텀 1개 종목
58
- """
59
- return mom1.get_momentum_one(scode)
60
-
61
- def get_value(self, stock_list) -> pd.DataFrame:
62
- """
63
- 밸류
64
- """
65
- data_val = val.get_value(stock_list)
66
- return data_val
67
-
68
- def get_value_one(self, scode) -> pd.DataFrame:
69
- """
70
- 밸류 1개 종목
71
- """
72
- return val1.get_value_one(scode)
73
-
74
- def get_quality(self, stock_list) -> pd.DataFrame:
75
- """
76
- 퀄리티
77
- """
78
- data_fin = qual.get_quality(stock_list)
79
- return data_fin
80
-
81
- def get_quality_one(self, scode) -> pd.DataFrame:
82
- """
83
- 퀄리티 1개 종목
84
- """
85
- return qual1.get_quality_one(scode)
86
-
87
-
88
-
89
- def get_score(self) -> pd.DataFrame:
90
- """
91
- 스코어 마스터 자동계산
92
- """
93
- print("(1/5) 종목코드 생성")
94
- stock_list = self.get_stockinfo(dtype='dic')
95
-
96
- print("\n(2/5) 모멘텀 지표 생성")
97
- data_mom = self.get_momentum(stock_list)
98
-
99
- print("\n(3/5) 밸류 지표 생성")
100
- data_val = self.get_value(stock_list)
101
-
102
- print("\n(4/5) 퀄리티 지표 생성")
103
- data_fin = self.get_quality(stock_list)
104
-
105
- print("\n(5/5) 멀티팩터 마스터 생성")
106
- data_mast = sc.get_score(data_mom, data_val, data_fin)
107
-
108
- data_mast.reset_index(drop=True, inplace=True)
109
-
110
- return data_mast
111
-
112
-
113
- def get_score_by_data(self, data_mom, data_val, data_fin) -> pd.DataFrame:
114
- """
115
- 스코어 마스터 : 직접 데이터 입력
116
- """
117
- data_mast = sc.get_score(data_mom, data_val, data_fin)
118
- data_mast.reset_index(drop=True, inplace=True)
119
- return data_mast
120
-
121
-
122
- def get_score_adj_weight(self, data_mast, weight='균등') -> pd.DataFrame:
123
- """
124
- 스코어 마스터를 받아서, 가중치 주기
125
- weight : 균등(기본), 가치성장, 추세성장, 역발생
126
- """
127
- data_mast = scw.get_score_adj_weight(data_mast, weight)
128
- data_mast.reset_index(drop=True, inplace=True)
129
- return data_mast
130
-
131
-
132
- def get_Ngroup(self, data_mast, Ngroup=10) -> pd.DataFrame:
133
- """
134
- 지정한 그룹수(Ngroup)에 따라 종목명만 출력
135
- Ngroup : 2부터 100 사이값 & data_mast보다 건수 적음
136
- """
137
- Ngroup = int(Ngroup)
138
- if Ngroup > 1 and Ngroup <= 100 and Ngroup < len(data_mast):
139
-
140
- # 1. 종합순위를 기준으로 오름차순 정렬
141
- data_mast = data_mast.sort_values(by='종합순위')
142
-
143
- # 2. 정렬된 데이터프레임을 Ngroup 개수만큼 분할
144
- chunks = np.array_split(data_mast, Ngroup)
145
-
146
- # 3. 각 그룹별로 번호와 종목명 출력
147
- for i, chunk in enumerate(chunks, 1):
148
- stock_list = ", ".join(chunk['sname'].astype(str).tolist())
149
- print(f"{i} : {stock_list}")
150
-
151
- else:
152
- print("Ngroup를 다시 입력하세요 : 2부터 100 사이값으로, 멀티팩터 데이터보다 건수가 적어야 합니다")
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
1
+ #!pip install finance-datareader
2
+
3
+ import FinanceDataReader as fdr
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+
8
+ import time
9
+
10
+ from . import stockinfo as sinfo
11
+
12
+ from . import momentum as mom
13
+ from . import value as val
14
+ from . import quality as qual
15
+
16
+ from . import momentum_one as mom1
17
+ from . import value_one as val1
18
+ from . import quality_one as qual1
19
+
20
+ from . import score as sc
21
+ from . import score_adj_weight as scw
22
+
23
+
24
+
25
+ class MultiFactor:
26
+ def __init__(self, N: int):
27
+ """
28
+ 멀티팩터 : 분석 대상 종목수 (시가총액 상위 N개)
29
+ """
30
+ self.N = N
31
+
32
+
33
+ def get_stockinfo(self, dtype='dataframe') -> pd.DataFrame:
34
+
35
+ df = sinfo.get_stockinfo(self.N)
36
+
37
+ if dtype=='dic':
38
+ # 종목 정보 사전 저장
39
+ stock_list = dict(zip(df['Code'], df['Name']))
40
+ return stock_list
41
+
42
+ else:
43
+ return df
44
+
45
+
46
+
47
+ def get_momentum(self, stock_list) -> pd.DataFrame:
48
+ """
49
+ 모멘텀
50
+ """
51
+ data_mom = mom.get_momentum(stock_list)
52
+ return data_mom
53
+
54
+
55
+ def get_momentum_one(self, scode) -> pd.DataFrame:
56
+ """
57
+ 모멘텀 1개 종목
58
+ """
59
+ return mom1.get_momentum_one(scode)
60
+
61
+ def get_value(self, stock_list) -> pd.DataFrame:
62
+ """
63
+ 밸류
64
+ """
65
+ data_val = val.get_value(stock_list)
66
+ return data_val
67
+
68
+ def get_value_one(self, scode) -> pd.DataFrame:
69
+ """
70
+ 밸류 1개 종목
71
+ """
72
+ return val1.get_value_one(scode)
73
+
74
+ def get_quality(self, stock_list) -> pd.DataFrame:
75
+ """
76
+ 퀄리티
77
+ """
78
+ data_fin = qual.get_quality(stock_list)
79
+ return data_fin
80
+
81
+ def get_quality_one(self, scode) -> pd.DataFrame:
82
+ """
83
+ 퀄리티 1개 종목
84
+ """
85
+ return qual1.get_quality_one(scode)
86
+
87
+
88
+
89
+ def get_score(self) -> pd.DataFrame:
90
+ """
91
+ 스코어 마스터 자동계산
92
+ """
93
+ print("(1/5) 종목코드 생성")
94
+ stock_list = self.get_stockinfo(dtype='dic')
95
+
96
+ print("\n(2/5) 모멘텀 지표 생성")
97
+ data_mom = self.get_momentum(stock_list)
98
+
99
+ print("\n(3/5) 밸류 지표 생성")
100
+ data_val = self.get_value(stock_list)
101
+
102
+ print("\n(4/5) 퀄리티 지표 생성")
103
+ data_fin = self.get_quality(stock_list)
104
+
105
+ print("\n(5/5) 멀티팩터 마스터 생성")
106
+ data_mast = sc.get_score(data_mom, data_val, data_fin)
107
+
108
+ data_mast.reset_index(drop=True, inplace=True)
109
+
110
+ return data_mast
111
+
112
+
113
+ def get_score_by_data(self, data_mom, data_val, data_fin) -> pd.DataFrame:
114
+ """
115
+ 스코어 마스터 : 직접 데이터 입력
116
+ """
117
+ data_mast = sc.get_score(data_mom, data_val, data_fin)
118
+ data_mast.reset_index(drop=True, inplace=True)
119
+ return data_mast
120
+
121
+
122
+ def get_score_adj_weight(self, data_mast, weight='균등') -> pd.DataFrame:
123
+ """
124
+ 스코어 마스터를 받아서, 가중치 주기
125
+ weight : 균등(기본), 가치성장, 추세성장, 역발생
126
+ """
127
+ data_mast = scw.get_score_adj_weight(data_mast, weight)
128
+ data_mast.reset_index(drop=True, inplace=True)
129
+ return data_mast
130
+
131
+
132
+ def get_Ngroup(self, data_mast, Ngroup=10) -> pd.DataFrame:
133
+ """
134
+ 지정한 그룹수(Ngroup)에 따라 종목명만 출력
135
+ Ngroup : 2부터 100 사이값 & data_mast보다 건수 적음
136
+ """
137
+ Ngroup = int(Ngroup)
138
+ if Ngroup > 1 and Ngroup <= 100 and Ngroup < len(data_mast):
139
+
140
+ # 1. 종합순위를 기준으로 오름차순 정렬
141
+ data_mast = data_mast.sort_values(by='종합순위')
142
+
143
+ # 2. 정렬된 데이터프레임을 Ngroup 개수만큼 분할
144
+ chunks = np.array_split(data_mast, Ngroup)
145
+
146
+ # 3. 각 그룹별로 번호와 종목명 출력
147
+ for i, chunk in enumerate(chunks, 1):
148
+ stock_list = ", ".join(chunk['sname'].astype(str).tolist())
149
+ print(f"{i} : {stock_list}")
150
+
151
+ else:
152
+ print("Ngroup를 다시 입력하세요 : 2부터 100 사이값으로, 멀티팩터 데이터보다 건수가 적어야 합니다")
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
@@ -1,83 +1,83 @@
1
- import FinanceDataReader as fdr
2
-
3
- import pandas as pd
4
- import numpy as np
5
-
6
- from datetime import date
7
-
8
- def get_momentum(stock_list):
9
-
10
- # 날짜 : SD 작년 1/2, ED는 오늘
11
- ED = date.today().strftime('%Y%m%d') # 오늘
12
-
13
- last_year = date.today().year - 1
14
- SD = date(last_year, 1, 2).strftime('%Y%m%d') # 작년 1월2일
15
-
16
-
17
- def get_momentum_one(scode, SD, ED):
18
- """
19
- 주가 모멘텀과 거래량 모멘텀 계산
20
-
21
- 매개변수:
22
- scode : 종목 코드 (예: '005930')
23
- SD : 주가데이터 추출시작일 (예: '20250102')
24
- ED : 주가데이터 추출종료일 (예: '20250131')
25
-
26
- 반환값:
27
- avg : 주가 모멘텀 지표 (기간별 수익률 평균)
28
- vol : 거래량 모멘텀 지표
29
- """
30
-
31
- # 1. 주가 및 거래량 데이터 수집 (여기는 에러나면 멈춰서 확인해야 하므로 try-except 제거)
32
- df = fdr.DataReader(scode, SD, ED)
33
-
34
- # 2. 주가 모멘텀 지표 생성
35
- # 단기 (1일, 1주, 1개월) - 데이터가 너무 없으면 에러가 나는 게 맞으므로 그대로 둠
36
- mom_1d = ( df.iloc[-1]['Close'] / df.iloc[-2]['Close'] - 1 ) * 100 # 전일
37
- mom_1w = ( df.iloc[-1]['Close'] / df.iloc[-5]['Close'] - 1 ) * 100 # 주간
38
- mom_1m = ( df.iloc[-1]['Close'] / df.iloc[-20]['Close'] - 1 ) * 100 # 월간
39
-
40
- # 3개월간 (데이터 부족 시 NaN 처리)
41
- try:
42
- mom_3m = ( df.iloc[-1]['Close'] / df.iloc[-60]['Close'] - 1 ) * 100
43
- except:
44
- mom_3m = np.nan
45
-
46
- # 연간 (데이터 부족 시 NaN 처리)
47
- try:
48
- mom_1y = ( df.iloc[-1]['Close'] / df.iloc[-240]['Close'] - 1 ) * 100
49
- except:
50
- mom_1y = np.nan
51
-
52
- # 3. 기간별 수익률의 평균 계산 (NaN을 제외하고 평균 산출)
53
- avg = np.nanmean([mom_1d, mom_1w, mom_1m, mom_3m, mom_1y])
54
-
55
- # 4. 거래량 모멘텀 지표 생성
56
- try:
57
- vol_short = df['Volume'].rolling(window=5).mean().iloc[-1] # 최근 5일
58
- vol_long = df['Volume'].rolling(window=20).mean().iloc[-1] # 최근 20일
59
- vol = ( vol_short / vol_long - 1) * 100
60
- except:
61
- vol = np.nan
62
-
63
- return avg, vol
64
-
65
-
66
- # 모멘텀 지표 계산 후 result에 적재
67
- result = []
68
- for scode, sname in stock_list.items():
69
- try:
70
- mom, vol = get_momentum_one(scode, SD, ED) # 주가 데이터 수집일(SD, ED) ★★★
71
- result.append( [ scode, sname, mom, vol ] )
72
-
73
- except:
74
- print("추출오류 : ", sname) # 에러 종목코드 출력
75
- result.append([scode, sname, None, None])
76
-
77
- # 모멘텀 지표 결과(result)는 데이터프레임(data_mom)으로 저장
78
- data_mom = pd.DataFrame(result, columns=['scode', 'sname', 'mom_price', 'mom_vol'])
79
-
80
- # 추출 오류 종목 제외 (최근 상장 종목)
81
- data_mom = data_mom.dropna().reset_index(drop=True)
82
-
1
+ import FinanceDataReader as fdr
2
+
3
+ import pandas as pd
4
+ import numpy as np
5
+
6
+ from datetime import date
7
+
8
+ def get_momentum(stock_list):
9
+
10
+ # 날짜 : SD 작년 1/2, ED는 오늘
11
+ ED = date.today().strftime('%Y%m%d') # 오늘
12
+
13
+ last_year = date.today().year - 1
14
+ SD = date(last_year, 1, 2).strftime('%Y%m%d') # 작년 1월2일
15
+
16
+
17
+ def get_momentum_one(scode, SD, ED):
18
+ """
19
+ 주가 모멘텀과 거래량 모멘텀 계산
20
+
21
+ 매개변수:
22
+ scode : 종목 코드 (예: '005930')
23
+ SD : 주가데이터 추출시작일 (예: '20250102')
24
+ ED : 주가데이터 추출종료일 (예: '20250131')
25
+
26
+ 반환값:
27
+ avg : 주가 모멘텀 지표 (기간별 수익률 평균)
28
+ vol : 거래량 모멘텀 지표
29
+ """
30
+
31
+ # 1. 주가 및 거래량 데이터 수집 (여기는 에러나면 멈춰서 확인해야 하므로 try-except 제거)
32
+ df = fdr.DataReader(scode, SD, ED)
33
+
34
+ # 2. 주가 모멘텀 지표 생성
35
+ # 단기 (1일, 1주, 1개월) - 데이터가 너무 없으면 에러가 나는 게 맞으므로 그대로 둠
36
+ mom_1d = ( df.iloc[-1]['Close'] / df.iloc[-2]['Close'] - 1 ) * 100 # 전일
37
+ mom_1w = ( df.iloc[-1]['Close'] / df.iloc[-5]['Close'] - 1 ) * 100 # 주간
38
+ mom_1m = ( df.iloc[-1]['Close'] / df.iloc[-20]['Close'] - 1 ) * 100 # 월간
39
+
40
+ # 3개월간 (데이터 부족 시 NaN 처리)
41
+ try:
42
+ mom_3m = ( df.iloc[-1]['Close'] / df.iloc[-60]['Close'] - 1 ) * 100
43
+ except:
44
+ mom_3m = np.nan
45
+
46
+ # 연간 (데이터 부족 시 NaN 처리)
47
+ try:
48
+ mom_1y = ( df.iloc[-1]['Close'] / df.iloc[-240]['Close'] - 1 ) * 100
49
+ except:
50
+ mom_1y = np.nan
51
+
52
+ # 3. 기간별 수익률의 평균 계산 (NaN을 제외하고 평균 산출)
53
+ avg = np.nanmean([mom_1d, mom_1w, mom_1m, mom_3m, mom_1y])
54
+
55
+ # 4. 거래량 모멘텀 지표 생성
56
+ try:
57
+ vol_short = df['Volume'].rolling(window=5).mean().iloc[-1] # 최근 5일
58
+ vol_long = df['Volume'].rolling(window=20).mean().iloc[-1] # 최근 20일
59
+ vol = ( vol_short / vol_long - 1) * 100
60
+ except:
61
+ vol = np.nan
62
+
63
+ return avg, vol
64
+
65
+
66
+ # 모멘텀 지표 계산 후 result에 적재
67
+ result = []
68
+ for scode, sname in stock_list.items():
69
+ try:
70
+ mom, vol = get_momentum_one(scode, SD, ED) # 주가 데이터 수집일(SD, ED) ★★★
71
+ result.append( [ scode, sname, mom, vol ] )
72
+
73
+ except:
74
+ print("추출오류 : ", sname) # 에러 종목코드 출력
75
+ result.append([scode, sname, None, None])
76
+
77
+ # 모멘텀 지표 결과(result)는 데이터프레임(data_mom)으로 저장
78
+ data_mom = pd.DataFrame(result, columns=['scode', 'sname', 'mom_price', 'mom_vol'])
79
+
80
+ # 추출 오류 종목 제외 (최근 상장 종목)
81
+ data_mom = data_mom.dropna().reset_index(drop=True)
82
+
83
83
  return data_mom