ezKit 1.9.9__py3-none-any.whl → 1.9.11__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.
- 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
|