ezKit 1.9.9__py3-none-any.whl → 1.9.11__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ezKit/stock.py +64 -39
- ezKit/utils.py +50 -71
- {ezKit-1.9.9.dist-info → ezKit-1.9.11.dist-info}/METADATA +1 -1
- {ezKit-1.9.9.dist-info → ezKit-1.9.11.dist-info}/RECORD +7 -7
- {ezKit-1.9.9.dist-info → ezKit-1.9.11.dist-info}/LICENSE +0 -0
- {ezKit-1.9.9.dist-info → ezKit-1.9.11.dist-info}/WHEEL +0 -0
- {ezKit-1.9.9.dist-info → ezKit-1.9.11.dist-info}/top_level.txt +0 -0
ezKit/stock.py
CHANGED
@@ -94,16 +94,17 @@ def kdj_vector(
|
|
94
94
|
# 有采用 ewm 使用 com=2 的, 但是如果使用 com=2 在默认值的情况下KDJ值是正确的.
|
95
95
|
# 但是非默认值, 比如调整参数, 尝试慢速 KDJ 时就不对了, 最终采用 alpha = 1/m 的情况, 对比同花顺数据, 是正确的.
|
96
96
|
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
# 检查参数
|
98
|
+
if isinstance(df, DataFrame) and df.empty:
|
99
|
+
logger.error("argument error: df")
|
100
|
+
return None
|
101
|
+
|
102
|
+
if not utils.check_arguments([(kdj_options, tuple, "kdj_options")]):
|
103
|
+
return None
|
104
|
+
|
105
|
+
if not all(utils.isTrue(item, int) for item in kdj_options):
|
106
|
+
logger.error("argument error: kdj_options")
|
107
|
+
return None
|
107
108
|
|
108
109
|
try:
|
109
110
|
low_list = df['low'].rolling(kdj_options[0]).min()
|
@@ -128,25 +129,23 @@ def data_vector(
|
|
128
129
|
) -> DataFrame | None:
|
129
130
|
"""数据运算"""
|
130
131
|
|
131
|
-
#
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
return None
|
136
|
-
case True if not any([utils.isTrue(macd_options, tuple), all(utils.isTrue(item, int) for item in macd_options)]):
|
137
|
-
logger.error("argument error: macd_options")
|
138
|
-
return None
|
139
|
-
case True if not any([utils.isTrue(kdj_options, tuple), all(utils.isTrue(item, int) for item in kdj_options)]):
|
140
|
-
logger.error("argument error: kdj_options")
|
141
|
-
return None
|
142
|
-
case _:
|
143
|
-
pass
|
132
|
+
# 检查参数
|
133
|
+
if isinstance(df, DataFrame) and df.empty:
|
134
|
+
logger.error("argument error: df")
|
135
|
+
return None
|
144
136
|
|
145
|
-
|
137
|
+
if not utils.check_arguments([(macd_options, tuple, "macd_options"), (kdj_options, tuple, "kdj_options")]):
|
138
|
+
return None
|
146
139
|
|
147
|
-
|
148
|
-
|
149
|
-
|
140
|
+
if not all(utils.isTrue(item, int) for item in macd_options):
|
141
|
+
logger.error("argument error: macd_options")
|
142
|
+
return None
|
143
|
+
|
144
|
+
if not all(utils.isTrue(item, int) for item in kdj_options):
|
145
|
+
logger.error("argument error: kdj_options")
|
146
|
+
return None
|
147
|
+
|
148
|
+
try:
|
150
149
|
|
151
150
|
# ------------------------------------------------------------------------------------------
|
152
151
|
|
@@ -174,7 +173,13 @@ def data_vector(
|
|
174
173
|
# ------------------------------------------------------------------------------------------
|
175
174
|
|
176
175
|
# 计算 MACD: 默认参数 12 26 9
|
177
|
-
macd_dif, macd_dea, macd_bar = ta.MACD(
|
176
|
+
macd_dif, macd_dea, macd_bar = ta.MACD( # type: ignore
|
177
|
+
df['close'].values,
|
178
|
+
fastperiod=macd_options[0],
|
179
|
+
slowperiod=macd_options[1],
|
180
|
+
signalperiod=macd_options[2]
|
181
|
+
)
|
182
|
+
|
178
183
|
macd_dif[np.isnan(macd_dif)], macd_dea[np.isnan(macd_dea)], macd_bar[np.isnan(macd_bar)] = 0, 0, 0
|
179
184
|
|
180
185
|
# https://www.bilibili.com/read/cv10185856
|
@@ -182,15 +187,26 @@ def data_vector(
|
|
182
187
|
df['MACD_DIF'] = macd_dif
|
183
188
|
df['MACD_DEA'] = macd_dea
|
184
189
|
|
185
|
-
#
|
190
|
+
# 初始化 MACD_X 列(0 无, 1 金叉, 2 死叉)
|
186
191
|
df['MACD_X'] = 0
|
192
|
+
|
193
|
+
# 计算 MACD 条件
|
187
194
|
macd_position = df['MACD_DIF'] > df['MACD_DEA']
|
188
|
-
|
189
|
-
|
195
|
+
|
196
|
+
# 设置 MACD_X = 1: 从 False 变为 True 的位置
|
197
|
+
df.loc[macd_position & ~macd_position.shift(fill_value=False), 'MACD_X'] = 1
|
198
|
+
|
199
|
+
# 设置 MACD_X = 2: 从 True 变为 False 的位置
|
200
|
+
df.loc[~macd_position & macd_position.shift(fill_value=False), 'MACD_X'] = 2
|
201
|
+
|
202
|
+
# 将浮点数限制为小数点后两位
|
203
|
+
df['MACD'] = df['MACD'].round(2)
|
204
|
+
df['MACD_DIF'] = df['MACD_DIF'].round(2)
|
205
|
+
df['MACD_DEA'] = df['MACD_DEA'].round(2)
|
190
206
|
|
191
207
|
# ------------------------------------------------------------------------------------------
|
192
208
|
|
193
|
-
# 计算 KDJ: : 默认参数 9 3 3
|
209
|
+
# # 计算 KDJ: : 默认参数 9 3 3
|
194
210
|
kdj_data = kdj_vector(df, kdj_options)
|
195
211
|
|
196
212
|
if kdj_data is not None:
|
@@ -200,11 +216,22 @@ def data_vector(
|
|
200
216
|
df['D'] = kdj_data['D'].values
|
201
217
|
df['J'] = kdj_data['J'].values
|
202
218
|
|
203
|
-
#
|
219
|
+
# 初始化 KDJ_X 列(0 无, 1 金叉, 2 死叉)
|
204
220
|
df['KDJ_X'] = 0
|
221
|
+
|
222
|
+
# 计算 MACD 条件
|
205
223
|
kdj_position = df['J'] > df['D']
|
206
|
-
|
207
|
-
|
224
|
+
|
225
|
+
# 设置 KDJ_X = 1: 从 False 变为 True 的位置
|
226
|
+
df.loc[kdj_position & ~kdj_position.shift(fill_value=False), 'KDJ_X'] = 1
|
227
|
+
|
228
|
+
# 设置 KDJ_X = 2: 从 True 变为 False 的位置
|
229
|
+
df.loc[~kdj_position & kdj_position.shift(fill_value=False), 'KDJ_X'] = 2
|
230
|
+
|
231
|
+
# 将浮点数限制为小数点后两位
|
232
|
+
df['K'] = df['K'].round(2)
|
233
|
+
df['D'] = df['D'].round(2)
|
234
|
+
df['J'] = df['J'].round(2)
|
208
235
|
|
209
236
|
# ------------------------------------------------------------------------------------------
|
210
237
|
|
@@ -261,12 +288,10 @@ def get_stock_data_from_akshare(
|
|
261
288
|
"收盘": "close",
|
262
289
|
"最高": "high",
|
263
290
|
"最低": "low",
|
264
|
-
"成交量": "volume"
|
265
|
-
"成交额": "turnover"
|
291
|
+
"成交量": "volume"
|
266
292
|
})
|
267
|
-
df = df.round({'turnover': 4})
|
268
293
|
logger.success(f"{info} [成功]")
|
269
|
-
return df[['date', 'open', 'close', 'high', 'low', 'volume'
|
294
|
+
return df[['date', 'open', 'close', 'high', 'low', 'volume']].copy()
|
270
295
|
except Exception as e:
|
271
296
|
logger.error(f"{info} [失败]")
|
272
297
|
logger.exception(e)
|
ezKit/utils.py
CHANGED
@@ -30,15 +30,10 @@ NoneType = type(None)
|
|
30
30
|
# --------------------------------------------------------------------------------------------------
|
31
31
|
|
32
32
|
|
33
|
-
def isTrue(
|
34
|
-
|
35
|
-
object_type: Any = None,
|
36
|
-
true_list: list | tuple | set | str | None = None,
|
37
|
-
false_list: list | tuple | set | str | None = None
|
38
|
-
) -> bool:
|
39
|
-
"""检查对象类型以及对象数据是否为 True"""
|
33
|
+
def isTrue(target: object, typeClass: Any) -> bool:
|
34
|
+
"""检查对象是否为真"""
|
40
35
|
|
41
|
-
#
|
36
|
+
# 常见布尔类型:
|
42
37
|
#
|
43
38
|
# Boolean bool False
|
44
39
|
# Numbers int/float 0/0.0
|
@@ -60,44 +55,33 @@ def isTrue(
|
|
60
55
|
# all() 用于检查一个可迭代对象(如列表、元组、集合等)中的 所有 元素是否为 真值 (truthy), 所有元素为真, 返回 True
|
61
56
|
# any() 用于检查一个可迭代对象(如列表、元组、集合等)中的 某个 元素是否为 真值 (truthy), 某个元素为真, 返回 True
|
62
57
|
# 与 all() 作用相反的 not any(), 可以用来检查所有元素是否为 假值 (falsy), any() 中所有元素为假, not any() 返回 True
|
58
|
+
#
|
59
|
+
# return target not in [False, None, 0, 0.0, '', (), [], {}, {*()}, {*[]}, {*{}}]
|
63
60
|
|
64
61
|
try:
|
62
|
+
return isinstance(target, typeClass) and bool(target)
|
63
|
+
except Exception as e:
|
64
|
+
logger.exception(e)
|
65
|
+
return False
|
65
66
|
|
66
|
-
if isinstance(object_data, object_type):
|
67
|
-
|
68
|
-
if all(
|
69
|
-
[
|
70
|
-
true_list is not None,
|
71
|
-
false_list is None,
|
72
|
-
isinstance(true_list, (list, tuple, set, str))
|
73
|
-
]
|
74
|
-
):
|
75
|
-
return object_data in true_list
|
76
|
-
|
77
|
-
if all(
|
78
|
-
[
|
79
|
-
true_list is None,
|
80
|
-
false_list is not None,
|
81
|
-
isinstance(false_list, (list, tuple, set, str))
|
82
|
-
]
|
83
|
-
):
|
84
|
-
return object_data not in false_list
|
85
|
-
|
86
|
-
if all(
|
87
|
-
[
|
88
|
-
true_list is not None,
|
89
|
-
false_list is not None,
|
90
|
-
isinstance(true_list, (list, tuple, set, str)),
|
91
|
-
isinstance(false_list, (list, tuple, set, str))
|
92
|
-
]
|
93
|
-
):
|
94
|
-
return (object_data in true_list) and (object_data not in false_list)
|
95
|
-
|
96
|
-
# return object_data not in [False, None, 0, 0.0, '', (), [], {}, {*()}, {*[]}, {*{}}]
|
97
|
-
return bool(object_data)
|
98
67
|
|
99
|
-
|
68
|
+
# --------------------------------------------------------------------------------------------------
|
69
|
+
|
70
|
+
|
71
|
+
def check_arguments(data: list) -> bool:
|
72
|
+
"""检查函数参数"""
|
73
|
+
|
74
|
+
# data 示例: [(name, str, "name"), (age, int, "age")]
|
100
75
|
|
76
|
+
try:
|
77
|
+
if not isTrue(data, list):
|
78
|
+
logger.error("argument error: data")
|
79
|
+
return False
|
80
|
+
for arg, arg_type, arg_name in data:
|
81
|
+
if not isTrue(arg, arg_type):
|
82
|
+
logger.error(f"argument error: {arg_name}")
|
83
|
+
return False
|
84
|
+
return True
|
101
85
|
except Exception as e:
|
102
86
|
logger.exception(e)
|
103
87
|
return False
|
@@ -116,13 +100,9 @@ def os_environ(
|
|
116
100
|
# Python 没有全局变量, 多个文件无法调用同一个变量.
|
117
101
|
# 为了解决这个问题, 将变量设置为系统变量, 从而实现多个文件调用同一个变量.
|
118
102
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
logger.error("argument error: name")
|
123
|
-
return None
|
124
|
-
case _:
|
125
|
-
pass
|
103
|
+
# 检查参数是否正确
|
104
|
+
if not check_arguments([(name, str, "name")]):
|
105
|
+
return None
|
126
106
|
|
127
107
|
try:
|
128
108
|
|
@@ -165,29 +145,24 @@ def mam_of_numbers(
|
|
165
145
|
# numbers 数字列表 (仅支持 list 和 tuple, 不支 set)
|
166
146
|
# dest_type 目标类型 (将数字列表中的数字转换成统一的类型)
|
167
147
|
|
168
|
-
#
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
return None
|
176
|
-
case _:
|
177
|
-
pass
|
148
|
+
# 检查参数是否正确
|
149
|
+
if not check_arguments([(numbers, (list, tuple), "numbers")]):
|
150
|
+
return None
|
151
|
+
|
152
|
+
if not any([isTrue(dest_type, str), dest_type is None]):
|
153
|
+
logger.error("argument error: dest_type")
|
154
|
+
return None
|
178
155
|
|
179
156
|
try:
|
180
157
|
|
181
158
|
_numbers = deepcopy(numbers)
|
182
159
|
|
183
160
|
# 转换数据类型
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
case _:
|
190
|
-
pass
|
161
|
+
if dest_type == "float":
|
162
|
+
_numbers = [float(i) for i in numbers]
|
163
|
+
|
164
|
+
if dest_type == "int":
|
165
|
+
_numbers = [int(i) for i in numbers]
|
191
166
|
|
192
167
|
# 提取数据
|
193
168
|
_num_max = max(_numbers)
|
@@ -248,6 +223,9 @@ def division(
|
|
248
223
|
divisor: int | float
|
249
224
|
) -> float | None:
|
250
225
|
"""Division"""
|
226
|
+
# 检查参数是否正确
|
227
|
+
if not check_arguments([(dividend, (int, float), "dividend"), (divisor, (int, float), "divisor")]):
|
228
|
+
return None
|
251
229
|
try:
|
252
230
|
return dividend / divisor
|
253
231
|
except Exception as e:
|
@@ -262,14 +240,15 @@ def check_file_type(
|
|
262
240
|
file_object: str,
|
263
241
|
file_type: str
|
264
242
|
) -> bool:
|
265
|
-
"""
|
266
|
-
check file type
|
243
|
+
"""检查文件类型"""
|
267
244
|
|
268
|
-
|
245
|
+
# file_object 文件对象
|
246
|
+
# file_type 文件类型
|
247
|
+
|
248
|
+
# 检查参数是否正确
|
249
|
+
if not check_arguments([(file_object, str, "file"), (file_type, str, "file_type")]):
|
250
|
+
return False
|
269
251
|
|
270
|
-
file_object 文件对象
|
271
|
-
file_type 文件类型
|
272
|
-
"""
|
273
252
|
try:
|
274
253
|
|
275
254
|
_file_path = Path(file_object)
|
@@ -9,12 +9,12 @@ ezKit/mongo.py,sha256=dOm_1wXEPp_e8Ml5Qq78M7FDNrQUAZaThzVIiiLJJwk,2393
|
|
9
9
|
ezKit/qywx.py,sha256=X_H4fzP-iEqeDEbumr7D1bXi6dxczaxfO8iyutzy02s,7171
|
10
10
|
ezKit/redis.py,sha256=g2_V4jvq0djRc20jLZkgeAeF_bYrq-Rbl_kHcCUPZcA,1965
|
11
11
|
ezKit/sendemail.py,sha256=tRXCsJm_RfTJ9xEWe_lTQ5kOs2JxHGPXvq0oWA7prq0,7263
|
12
|
-
ezKit/stock.py,sha256=
|
12
|
+
ezKit/stock.py,sha256=J-fM2XH2q7G6-Q30N8clqLIv7sSn87_fN1qjLOiTrFk,12088
|
13
13
|
ezKit/token.py,sha256=HKREyZj_T2S8-aFoFIrBXTaCKExQq4zE66OHXhGHqQg,1750
|
14
|
-
ezKit/utils.py,sha256=
|
14
|
+
ezKit/utils.py,sha256=TDsL3PRkQy6NdZgphkgwacbWvHqEmq4LOkfNzmxV4DY,42682
|
15
15
|
ezKit/xftp.py,sha256=XyIdr_2rxRVLqPofG6fIYWhAMVsFwTyp46dg5P9FLW4,7774
|
16
|
-
ezKit-1.9.
|
17
|
-
ezKit-1.9.
|
18
|
-
ezKit-1.9.
|
19
|
-
ezKit-1.9.
|
20
|
-
ezKit-1.9.
|
16
|
+
ezKit-1.9.11.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
17
|
+
ezKit-1.9.11.dist-info/METADATA,sha256=O05DZpUqxTH6u_llpwm7s7FCxb1EgTqMwX_xjYx3fcw,191
|
18
|
+
ezKit-1.9.11.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
19
|
+
ezKit-1.9.11.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
|
20
|
+
ezKit-1.9.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|