analyser_hj3415 2.6.0__tar.gz → 2.6.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (22) hide show
  1. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/PKG-INFO +2 -2
  2. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/cli.py +32 -10
  3. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/myredis.py +80 -111
  4. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/pyproject.toml +2 -2
  5. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.DS_Store +0 -0
  6. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.gitattributes +0 -0
  7. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.gitignore +0 -0
  8. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/.gitignore +0 -0
  9. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/analyser-hj3415.iml +0 -0
  10. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  11. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/misc.xml +0 -0
  12. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/modules.xml +0 -0
  13. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/.idea/vcs.xml +0 -0
  14. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/LICENSE +0 -0
  15. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/README.md +0 -0
  16. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/.DS_Store +0 -0
  17. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/__init__.py +0 -0
  18. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/analysers/eval.py +0 -0
  19. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/analysers/report.py +0 -0
  20. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/analysers/score.py +0 -0
  21. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/tools.py +0 -0
  22. {analyser_hj3415-2.6.0 → analyser_hj3415-2.6.1}/analyser_hj3415/trash.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: analyser_hj3415
3
- Version: 2.6.0
3
+ Version: 2.6.1
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.7.0
9
- Requires-Dist: db-hj3415>=3.7.2
9
+ Requires-Dist: db-hj3415>=3.7.3
10
10
  Project-URL: Home, https://www.hyungjin.kr
11
11
 
12
12
  ### analyser-hj3415
@@ -35,7 +35,7 @@ class AnalyserSettingsManager(SettingsManager):
35
35
 
36
36
  def analyser_manager():
37
37
  settings_manager = AnalyserSettingsManager(SETTINGS_FILE)
38
- expect_earn = settings_manager.get_value('EXPECT_EARN')
38
+ expect_earn_from_setting = settings_manager.get_value('EXPECT_EARN')
39
39
 
40
40
  parser = argparse.ArgumentParser(description="Analyser Commands")
41
41
  type_subparsers = parser.add_subparsers(dest='type', help='분석 타입')
@@ -45,11 +45,15 @@ def analyser_manager():
45
45
  red_subparser = red_parser.add_subparsers(dest='command', help='red 관련된 명령')
46
46
  # red - ranking 파서
47
47
  ranking_parser = red_subparser.add_parser('ranking', help='red 랭킹 책정 및 레디스 저장')
48
- ranking_parser.add_argument('--noti', action='store_true', help='작업 완료 메시지 전송 여부')
49
- # mil - score 파서
48
+ ranking_parser.add_argument('-e', '--expect_earn', type=float, help='기대수익률 (실수 입력)')
49
+ ranking_parser.add_argument('-r', '--refresh', action='store_true', help='래디스 캐시를 사용하지 않고 강제로 재계산 할지')
50
+ ranking_parser.add_argument('-n', '--noti', action='store_true', help='작업 완료 후 메시지 전송 여부')
51
+ # red - score 파서
50
52
  score_parser = red_subparser.add_parser('score', help='red score 책정 및 레디스 저장')
51
53
  score_parser.add_argument('code', type=str, help='종목코드 or all')
52
- score_parser.add_argument('--noti', action='store_true', help='작업 완료 메시지 전송 여부')
54
+ score_parser.add_argument('-e', '--expect_earn', type=float, help='기대수익률 (실수 입력)')
55
+ score_parser.add_argument('-r', '--refresh', action='store_true', help='래디스 캐시를 사용하지 않고 강제로 재계산 할지')
56
+ score_parser.add_argument('-n', '--noti', action='store_true', help='작업 완료 후 메시지 전송 여부')
53
57
 
54
58
  # mil 명령어 서브파서
55
59
  mil_parser = type_subparsers.add_parser('mil', help='millennial 타입')
@@ -57,7 +61,9 @@ def analyser_manager():
57
61
  # mil - score 파서
58
62
  score_parser = mil_subparser.add_parser('score', help='mil score 책정 및 레디스 저장')
59
63
  score_parser.add_argument('code', type=str, help='종목코드 or all')
60
- score_parser.add_argument('--noti', action='store_true', help='작업 완료 메시지 전송 여부')
64
+ score_parser.add_argument('-e', '--expect_earn', type=float, help='기대수익률 (실수 입력)')
65
+ score_parser.add_argument('-r', '--refresh', action='store_true', help='래디스 캐시를 사용하지 않고 강제로 재계산 할지')
66
+ score_parser.add_argument('-n', '--noti', action='store_true', help='작업 완료 후 메시지 전송 여부')
61
67
 
62
68
  # setting 명령어 서브파서
63
69
  setting_parser = type_subparsers.add_parser('setting', help='Set and Get settings')
@@ -76,31 +82,47 @@ def analyser_manager():
76
82
 
77
83
  if args.type == 'red':
78
84
  if args.command == 'score':
85
+ # 기대 수익률과 refresh 값 처리
86
+ expect_earn = args.expect_earn if args.expect_earn is not None else expect_earn_from_setting
87
+ refresh = args.refresh if args.refresh else False
88
+
89
+ # print(expect_earn, refresh)
79
90
  if args.code == 'all':
80
91
  print("**** red_n_score all code ****")
81
92
  for i, code in enumerate(myredis.Corps.list_all_codes()):
82
93
  print(f'{i} / {code}')
83
- red_n_score(code, expect_earn)
94
+ red_n_score(code, expect_earn, refresh)
84
95
  else:
85
96
  assert utils.is_6digit(args.code), "code 인자는 6자리 숫자이어야 합니다."
86
- print(args.code, red_n_score(args.code, expect_earn))
97
+ print(args.code, red_n_score(args.code, expect_earn, refresh))
87
98
  if args.noti:
88
99
  noti.telegram_to('manager', f"오늘의 red and score({args.code})를 레디스캐시에 저장했습니다.(유효 12시간)")
100
+
89
101
  elif args.command == 'ranking':
90
- result = red_ranking(expect_earn)
102
+ # 기대 수익률과 refresh 값 처리
103
+ expect_earn = args.expect_earn if args.expect_earn is not None else expect_earn_from_setting
104
+ refresh = args.refresh if args.refresh else False
105
+
106
+ # red_ranking 함수 호출
107
+ result = red_ranking(expect_earn, refresh)
91
108
  print(result)
92
109
  if args.noti:
93
110
  noti.telegram_to('manager', "오늘의 red ranking을 레디스캐시에 저장했습니다.(유효 12시간)")
111
+
94
112
  elif args.type == 'mil':
95
113
  if args.command == 'score':
114
+ # 기대 수익률과 refresh 값 처리
115
+ expect_earn = args.expect_earn if args.expect_earn is not None else expect_earn_from_setting
116
+ refresh = args.refresh if args.refresh else False
117
+
96
118
  if args.code == 'all':
97
119
  print("**** mil_n_score all code ****")
98
120
  for i, code in enumerate(myredis.Corps.list_all_codes()):
99
121
  print(f'{i} / {code}')
100
- mil_n_score(code, expect_earn)
122
+ mil_n_score(code, expect_earn, refresh)
101
123
  else:
102
124
  assert utils.is_6digit(args.code), "code 인자는 6자리 숫자이어야 합니다."
103
- print(args.code, mil_n_score(args.code, expect_earn))
125
+ print(args.code, mil_n_score(args.code, expect_earn, refresh))
104
126
  if args.noti:
105
127
  noti.telegram_to('manager', f"오늘의 mil and score({args.code})를 레디스캐시에 저장했습니다.(유효 12시간)")
106
128
  elif args.type == 'setting':
@@ -1,83 +1,77 @@
1
1
  from analyser_hj3415.analysers import eval, score
2
- from db_hj3415.myredis import Base
3
- import json
2
+ from typing import Dict, Tuple
4
3
  from collections import OrderedDict
5
4
  from db_hj3415 import myredis as db_myredis
6
-
5
+ from utils_hj3415 import utils
7
6
 
8
7
  page = '.analyser'
8
+ myredis_base = db_myredis.Base()
9
9
 
10
+ def get_redis_expect_earn(redis_name:str) -> float:
11
+ redis_name_e = f'{redis_name}_expect_earn'
12
+ byte_expect_earn = db_myredis.Base.redis_client.get(redis_name_e)
13
+ if byte_expect_earn is not None:
14
+ e = float(byte_expect_earn.decode('utf-8'))
15
+ else:
16
+ e = float('nan')
17
+ return e
10
18
 
11
- def red_ranking(expect_earn: float) -> OrderedDict:
19
+ def red_ranking(expect_earn: float, refresh=False) -> Tuple[OrderedDict, str]:
12
20
  """
13
21
  redis를 사용하며 red score를 계산해서 0이상의 값을 가지는 종목을 순서대로 저장하여 반환한다.
22
+ :param expect_earn: 기대수익률(일반적으로 0.06 - 0.10)
23
+ :param refresh: 캐시를 사용하지 않고 강제로 다시 계산
14
24
  :return: OrderedDict([('023590', 101),
15
- ('009970', 99),
16
- ('010060', 91),...])
25
+ ('010060', 91),...]), 레디스이름
17
26
  """
27
+
28
+ print("**** Start red_ranking... ****")
18
29
  redis_name = 'red_ranking'
30
+ redis_name_e = f'{redis_name}_expect_earn'
31
+ if get_redis_expect_earn(redis_name) != expect_earn:
32
+ # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
33
+ refresh = True
34
+ db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
19
35
 
20
- try:
21
- cached_data = Base.redis_client.get(redis_name).decode('utf-8')
22
- except AttributeError:
23
- # redis에 해당하는 값이 없는 경우
36
+ def fetch_red_scores(expect_earn_i: float) -> Dict:
24
37
  data = {}
25
38
  for i, code in enumerate(db_myredis.Corps.list_all_codes()):
26
- red_score = score.red(code, expect_earn)
27
- if red_score <= 0:
28
- continue
29
- data[code] = red_score
30
- # print(i, code, s)
31
-
32
- # print(data)
33
- if data:
34
- # 데이터를 Redis에 캐싱
35
- Base.redis_client.set(redis_name, json.dumps(data))
36
- # 12시간 후 키가 자동으로 제거됨
37
- Base.redis_client.expire(redis_name, 3600 * 12)
38
- print("analysers.eval 데이터 계산하기 - myredis.red_ranking")
39
- # ordereddict를 이용해서 딕셔너리의 값을 기준으로 내림차순 정렬함.
40
- return OrderedDict(sorted(data.items(), key=lambda item: item[1], reverse=True))
41
- else:
42
- print(f"Redis 캐시에서 데이터 가져오기(남은시간:{round(Base.redis_client.ttl(redis_name)/3600, 1)}시간) - myredis.red_ranking")
43
- # ordereddict를 이용해서 딕셔너리의 값을 기준으로 내림차순 정렬함.
44
- return OrderedDict(sorted(json.loads(cached_data).items(), key=lambda item: item[1], reverse=True))
39
+ red_score = score.red(code, expect_earn_i)
40
+ if red_score > 0:
41
+ data[code] = red_score
42
+ print(f"{i}: {code} - {red_score}")
43
+ return data
44
+
45
+ data = myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_red_scores, expect_earn)
46
+ return OrderedDict(sorted(data.items(), key=lambda item: item[1], reverse=True)), redis_name
45
47
 
46
48
 
47
- def red_n_score(code: str, expect_earn: float) -> dict:
49
+
50
+ def red_n_score(code: str, expect_earn: float, refresh=False) -> Tuple[dict, str]:
48
51
  """
49
- redis 사용 - 소멸타이머 사용
50
- 리턴값
51
- {
52
- 'red_price': red_price,
53
- '사업가치': 사업가치,
54
- '재산가치': 재산가치,
55
- '부채평가': 부채평가,
56
- '발행주식수': 발행주식수,
57
- 'date': [각 유효한 값의 년월값 리스트(ex- 2020/09)],
58
- }
52
+ red 평가후 스코어 계산후 red 딕셔너리에 첨가후 반환
53
+ :param code: 종목코드
54
+ :param expect_earn: 기대수익률(일반적으로 0.06 - 0.10)
55
+ :param refresh: 캐시를 사용하지 않고 강제로 다시 계산
56
+ :return:
59
57
  """
60
- redis_name = code + page + '_eval_' + 'red'
61
- try:
62
- cached_data = Base.redis_client.get(redis_name).decode('utf-8')
63
- except AttributeError:
64
- # redis에 해당하는 값이 없는 경우
65
- data = eval.red(code, expect_earn)
66
- data['score'] = score.red(code, expect_earn)
67
- # print(data)
68
- if data:
69
- # 데이터를 Redis에 캐싱
70
- Base.redis_client.set(redis_name, json.dumps(data))
71
- # 12시간 후 키가 자동으로 제거됨
72
- Base.redis_client.expire(redis_name, 3600 * 12)
73
- print("analysers.eval 데이터 계산하기 - myredis.red")
58
+ redis_name = f"{code}_{page}_red_n_score"
59
+ redis_name_e = f'{redis_name}_expect_earn'
60
+ if get_redis_expect_earn(redis_name) != expect_earn:
61
+ # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
62
+ refresh = True
63
+ # print(get_redis_expect_earn(redis_name))
64
+ db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
65
+
66
+ def fetch_red_n_score(code_i: str, expect_earn_i: float) -> dict:
67
+ data = eval.red(code_i, expect_earn_i)
68
+ data['score'] = score.red(code_i, expect_earn_i)
74
69
  return data
75
- else:
76
- print(f"Redis 캐시에서 데이터 가져오기(남은시간:{round(Base.redis_client.ttl(redis_name)/3600, 1)}시간) - myredis.red")
77
- return json.loads(cached_data)
70
+
71
+ return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_red_n_score, code, expect_earn), redis_name
78
72
 
79
73
 
80
- def mil_n_score(code: str, expect_earn: float) -> dict:
74
+ def mil_n_score(code: str, expect_earn: float, refresh=False) -> Tuple[dict, str]:
81
75
  """
82
76
  redis 사용 - 소멸타이머 사용
83
77
  리턴값
@@ -113,27 +107,22 @@ def mil_n_score(code: str, expect_earn: float) -> dict:
113
107
  https://www.investopedia.com/terms/p/pricetofreecashflow.asp
114
108
  pcr보다 정확하게 주식의 가치를 평가할수 있음. 10배이하 추천
115
109
  """
116
- redis_name = code + page + '_eval_' + 'mil'
117
- try:
118
- cached_data = Base.redis_client.get(redis_name).decode('utf-8')
119
- except AttributeError:
120
- # redis에 해당하는 값이 없는 경우
121
- data = eval.mil(code)
122
- data['score'] = score.mil(code, expect_earn)
123
- # print(data)
124
- if data:
125
- # 데이터를 Redis에 캐싱
126
- Base.redis_client.set(redis_name, json.dumps(data))
127
- # 12시간 후 키가 자동으로 제거됨
128
- Base.redis_client.expire(redis_name, 3600 * 12)
129
- print("analysers.eval 데이터 계산하기 - myredis.mil")
110
+ redis_name = f"{code}_{page}_mil_n_score"
111
+ redis_name_e = f'{redis_name}_expect_earn'
112
+ if get_redis_expect_earn(redis_name) != expect_earn:
113
+ # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
114
+ refresh = True
115
+ db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
116
+
117
+ def fetch_mil_n_score(code_i: str) -> dict:
118
+ data = eval.mil(code_i)
119
+ data['score'] = score.mil(code_i, expect_earn)
130
120
  return data
131
- else:
132
- print(f"Redis 캐시에서 데이터 가져오기(남은시간:{round(Base.redis_client.ttl(redis_name)/3600, 1)}시간) - myredis.mil")
133
- return json.loads(cached_data)
121
+
122
+ return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_mil_n_score, code), redis_name
134
123
 
135
124
 
136
- def blue_n_score(code: str) -> dict:
125
+ def blue_n_score(code: str, refresh=False) -> Tuple[dict, str]:
137
126
  """
138
127
  redis 사용 - 소멸타이머 사용
139
128
  리턴값
@@ -165,27 +154,17 @@ def blue_n_score(code: str) -> dict:
165
154
  <영업이익률>
166
155
  영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
167
156
  """
168
- redis_name = code + page + '_eval_' + 'blue'
169
- try:
170
- cached_data = Base.redis_client.get(redis_name).decode('utf-8')
171
- except AttributeError:
172
- # redis에 해당하는 값이 없는 경우
173
- data = eval.blue(code)
174
- data['score'] = score.blue(code)
175
- # print(data)
176
- if data:
177
- # 데이터를 Redis에 캐싱
178
- Base.redis_client.set(redis_name, json.dumps(data))
179
- # 12시간 후 키가 자동으로 제거됨
180
- Base.redis_client.expire(redis_name, 3600 * 12)
181
- print("analysers.eval 데이터 계산하기 - myredis.blue")
157
+ redis_name = f"{code}_{page}_blue_n_score"
158
+
159
+ def fetch_blue_n_score(code_i: str) -> dict:
160
+ data = eval.blue(code_i)
161
+ data['score'] = score.blue(code_i)
182
162
  return data
183
- else:
184
- print(f"Redis 캐시에서 데이터 가져오기(남은시간:{round(Base.redis_client.ttl(redis_name)/3600, 1)}시간) - myredis.blue")
185
- return json.loads(cached_data)
163
+
164
+ return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_blue_n_score, code), redis_name
186
165
 
187
166
 
188
- def growth_n_score(code: str) -> dict:
167
+ def growth_n_score(code: str, refresh=False) -> Tuple[dict, str]:
189
168
  """
190
169
  redis 사용 - 소멸타이머 사용
191
170
  리턴값
@@ -198,21 +177,11 @@ def growth_n_score(code: str) -> dict:
198
177
  <영업이익률>
199
178
  영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
200
179
  """
201
- redis_name = code + page + '_eval_' + 'growth'
202
- try:
203
- cached_data = Base.redis_client.get(redis_name).decode('utf-8')
204
- except AttributeError:
205
- # redis에 해당하는 값이 없는 경우
206
- data = eval.growth(code)
207
- data['score'] = score.growth(code)
208
- # print(data)
209
- if data:
210
- # 데이터를 Redis에 캐싱
211
- Base.redis_client.set(redis_name, json.dumps(data))
212
- # 12시간 후 키가 자동으로 제거됨
213
- Base.redis_client.expire(redis_name, 3600 * 12)
214
- print("analysers.eval 데이터 계산하기 - myredis.growth")
180
+ redis_name = f"{code}_{page}_growth_n_score"
181
+
182
+ def fetch_growth_n_score(code_i: str) -> dict:
183
+ data = eval.growth(code_i)
184
+ data['score'] = score.growth(code_i)
215
185
  return data
216
- else:
217
- print(f"Redis 캐시에서 데이터 가져오기(남은시간:{round(Base.redis_client.ttl(redis_name)/3600, 1)}시간) - myredis.growth")
218
- return json.loads(cached_data)
186
+
187
+ return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_growth_n_score, code), redis_name
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
4
4
 
5
5
  [project]
6
6
  name = "analyser_hj3415"
7
- version = "2.6.0"
7
+ version = "2.6.1"
8
8
  authors = [{name = "Hyungjin Kim", email = "hj3415@gmail.com"}]
9
9
  description = "Stock analyser and database processing programs"
10
10
  readme = "README.md"
@@ -12,7 +12,7 @@ license = {file = "LICENSE"}
12
12
  classifiers = ["License :: OSI Approved :: MIT License"]
13
13
  dependencies = [
14
14
  "utils-hj3415>=2.7.0",
15
- "db-hj3415>=3.7.2",
15
+ "db-hj3415>=3.7.3",
16
16
  ]
17
17
 
18
18
  [project.scripts]
File without changes