mns-common 1.3.9.2__py3-none-any.whl → 1.6.1.4__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.
Potentially problematic release.
This version of mns-common might be problematic. Click here for more details.
- mns_common/__init__.py +1 -0
- mns_common/api/akshare/__init__.py +0 -1
- mns_common/api/akshare/k_line_api.py +20 -82
- mns_common/api/akshare/stock_bid_ask_api.py +21 -14
- mns_common/api/akshare/stock_zb_pool.py +2 -0
- mns_common/api/akshare/stock_zt_pool_api.py +1 -1
- mns_common/api/em/gd/east_money_stock_gdfx_free_top_10_api.py +62 -7
- mns_common/api/em/real_time/__init__.py +1 -1
- mns_common/api/em/real_time/east_money_debt_api.py +168 -71
- mns_common/api/em/real_time/east_money_etf_api.py +165 -27
- mns_common/api/em/real_time/east_money_stock_a_api.py +37 -38
- mns_common/api/em/real_time/east_money_stock_a_v2_api.py +97 -53
- mns_common/api/em/real_time/east_money_stock_common_api.py +174 -0
- mns_common/api/em/real_time/east_money_stock_hk_api.py +252 -271
- mns_common/api/em/real_time/east_money_stock_hk_gtt_api.py +291 -0
- mns_common/api/em/real_time/east_money_stock_multi_thread_api_v3.py +154 -0
- mns_common/api/em/real_time/east_money_stock_us_api.py +210 -82
- mns_common/api/em/real_time/real_time_quotes_repeat_api.py +195 -0
- mns_common/api/foreign_exchange/foreign_exchange_api.py +38 -0
- mns_common/api/k_line/stock_k_line_data_api.py +11 -1
- mns_common/api/kpl/common/__init__.py +3 -2
- mns_common/api/kpl/common/kpl_common_api.py +35 -0
- mns_common/api/kpl/symbol/symbol_his_quotes_api.py +1 -1
- mns_common/api/kpl/theme/kpl_theme_api.py +69 -0
- mns_common/api/kpl/yidong/__init__.py +7 -0
- mns_common/api/kpl/yidong/stock_bid_yi_dong_api.py +52 -0
- mns_common/api/proxies/liu_guan_proxy_api.py +55 -5
- mns_common/api/ths/company/company_product_area_industry_index_query.py +46 -0
- mns_common/api/ths/company/ths_company_info_api.py +2 -1
- mns_common/api/ths/company/ths_company_info_web.py +159 -0
- mns_common/api/ths/concept/app/ths_concept_index_app.py +3 -1
- mns_common/api/ths/wen_cai/ths_wen_cai_api.py +1 -1
- mns_common/api/ths/zt/ths_stock_zt_pool_api.py +20 -1
- mns_common/api/ths/zt/ths_stock_zt_pool_v2_api.py +105 -29
- mns_common/api/ths/zt/ths_stock_zt_reason_web_api.py +100 -0
- mns_common/api/us/ths_us_company_info_api.py +131 -0
- mns_common/api/xueqiu/xue_qiu_k_line_api.py +31 -23
- mns_common/component/common_service_fun_api.py +28 -8
- mns_common/component/company/company_common_service_new_api.py +2 -0
- mns_common/component/cookie/cookie_enum.py +16 -0
- mns_common/component/cookie/cookie_info_service.py +18 -8
- mns_common/component/data/data_init_api.py +13 -8
- mns_common/component/deal/deal_service_api.py +70 -8
- mns_common/component/deal/deal_service_v2_api.py +167 -0
- mns_common/component/em/em_stock_info_api.py +12 -3
- mns_common/component/exception/ExceptionMonitor.py +86 -0
- mns_common/component/exception/__init__.py +7 -0
- mns_common/component/main_line/__init__.py +7 -0
- mns_common/component/main_line/main_line_zt_reason_service.py +257 -0
- mns_common/component/proxies/proxy_common_api.py +199 -31
- mns_common/component/tfp/stock_tfp_api.py +82 -12
- mns_common/component/us/__init__.py +7 -0
- mns_common/component/us/us_stock_etf_info_api.py +130 -0
- mns_common/constant/db_name_constant.py +75 -26
- mns_common/constant/extra_income_db_name.py +97 -11
- mns_common/constant/strategy_classify.py +72 -0
- mns_common/db/MongodbUtil.py +3 -0
- mns_common/db/MongodbUtilLocal.py +3 -0
- {mns_common-1.3.9.2.dist-info → mns_common-1.6.1.4.dist-info}/METADATA +1 -1
- {mns_common-1.3.9.2.dist-info → mns_common-1.6.1.4.dist-info}/RECORD +64 -47
- mns_common/api/ths/concept/web/ths_company_info_web.py +0 -163
- mns_common/component/qmt/qmt_buy_service.py +0 -172
- mns_common/component/task/real_time_data_sync_check.py +0 -97
- /mns_common/{component/qmt → api/foreign_exchange}/__init__.py +0 -0
- /mns_common/{component/task → api/kpl/theme}/__init__.py +0 -0
- {mns_common-1.3.9.2.dist-info → mns_common-1.6.1.4.dist-info}/WHEEL +0 -0
- {mns_common-1.3.9.2.dist-info → mns_common-1.6.1.4.dist-info}/top_level.txt +0 -0
|
@@ -6,28 +6,38 @@ end = file_path.index('mns') + 16
|
|
|
6
6
|
project_path = file_path[0:end]
|
|
7
7
|
sys.path.append(project_path)
|
|
8
8
|
from mns_common.db.MongodbUtil import MongodbUtil
|
|
9
|
+
from mns_common.component.cookie.cookie_enum import CookieEnum
|
|
9
10
|
|
|
10
11
|
mongodb_util = MongodbUtil('27017')
|
|
11
12
|
|
|
12
|
-
from functools import lru_cache
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
@lru_cache(maxsize=None)
|
|
14
|
+
# ths cookie
|
|
16
15
|
def get_ths_cookie():
|
|
17
|
-
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
16
|
+
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
17
|
+
{"type": CookieEnum.THS_COOKIE.cookie_code})
|
|
18
18
|
ths_cookie = list(stock_account_info['cookie'])[0]
|
|
19
19
|
return ths_cookie
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
# 东财 cookie
|
|
23
23
|
def get_em_cookie():
|
|
24
|
-
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
24
|
+
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
25
|
+
{"type": CookieEnum.EM_COOKIE.cookie_code})
|
|
25
26
|
em_cookie = list(stock_account_info['cookie'])[0]
|
|
26
27
|
return em_cookie
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
# 雪球 cookie
|
|
30
31
|
def get_xue_qiu_cookie():
|
|
31
|
-
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
32
|
+
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
33
|
+
{"type": CookieEnum.XUE_QIU_COOKIE.cookie_code })
|
|
34
|
+
cookie = list(stock_account_info['cookie'])[0]
|
|
35
|
+
return cookie
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# 开盘啦 token
|
|
39
|
+
def get_kpl_cookie():
|
|
40
|
+
stock_account_info = mongodb_util.find_query_data('stock_account_info',
|
|
41
|
+
{"type": CookieEnum.KPL_COOKIE.cookie_code, })
|
|
32
42
|
cookie = list(stock_account_info['cookie'])[0]
|
|
33
43
|
return cookie
|
|
@@ -60,16 +60,21 @@ def calculate_parameter_factor(real_time_quotes_now):
|
|
|
60
60
|
real_time_quotes_now['large_inflow_multiple'] = round(
|
|
61
61
|
(real_time_quotes_now['large_order_net_inflow'] / real_time_quotes_now['reference_main_inflow']), 2)
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
if 'real_disk_diff_amount_exchange' not in real_time_quotes_now.columns:
|
|
64
|
+
real_time_quotes_now.loc[:, 'real_disk_diff_amount_exchange'] = round(
|
|
65
|
+
(real_time_quotes_now['disk_diff_amount_exchange'] / real_time_quotes_now['mv_circulation_ratio']), 2)
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
if 'real_main_inflow_multiple' not in real_time_quotes_now.columns:
|
|
68
|
+
real_time_quotes_now.loc[:, 'real_main_inflow_multiple'] = round(
|
|
69
|
+
(real_time_quotes_now['main_inflow_multiple'] / real_time_quotes_now['mv_circulation_ratio']), 2)
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
if 'real_super_main_inflow_multiple' not in real_time_quotes_now.columns:
|
|
72
|
+
real_time_quotes_now.loc[:, 'real_super_main_inflow_multiple'] = round(
|
|
73
|
+
(real_time_quotes_now['super_main_inflow_multiple'] / real_time_quotes_now['mv_circulation_ratio']), 2)
|
|
74
|
+
|
|
75
|
+
if 'real_exchange' not in real_time_quotes_now.columns:
|
|
76
|
+
real_time_quotes_now.loc[:, 'real_exchange'] = round(
|
|
77
|
+
(real_time_quotes_now['exchange'] / real_time_quotes_now['mv_circulation_ratio']), 2)
|
|
73
78
|
|
|
74
79
|
real_time_quotes_now.loc[:, 'max_real_main_inflow_multiple'] = real_time_quotes_now[
|
|
75
80
|
['real_main_inflow_multiple', 'real_super_main_inflow_multiple']].max(axis=1)
|
|
@@ -7,6 +7,7 @@ project_path = file_path[0:end]
|
|
|
7
7
|
sys.path.append(project_path)
|
|
8
8
|
import json
|
|
9
9
|
import requests
|
|
10
|
+
from loguru import logger
|
|
10
11
|
|
|
11
12
|
'''
|
|
12
13
|
|
|
@@ -89,7 +90,12 @@ def get_position(terminal):
|
|
|
89
90
|
if response.status_code != 200:
|
|
90
91
|
result = {"message": '获取持仓失败'}
|
|
91
92
|
else:
|
|
92
|
-
|
|
93
|
+
try:
|
|
94
|
+
result = response.json()
|
|
95
|
+
except BaseException as e:
|
|
96
|
+
result_test = response.text
|
|
97
|
+
result = json.loads(result_test)
|
|
98
|
+
|
|
93
99
|
return result
|
|
94
100
|
|
|
95
101
|
|
|
@@ -126,7 +132,24 @@ def auto_login(terminal):
|
|
|
126
132
|
if response.status_code != 200:
|
|
127
133
|
result = {"message": '获取持仓失败'}
|
|
128
134
|
else:
|
|
135
|
+
|
|
136
|
+
result = response.json()
|
|
137
|
+
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# 查询订单
|
|
142
|
+
def query_orders(terminal):
|
|
143
|
+
param_order = {
|
|
144
|
+
'terminal': terminal}
|
|
145
|
+
param_json = json.dumps(param_order)
|
|
146
|
+
response = request_trader('/order', param_json)
|
|
147
|
+
if response.status_code != 200:
|
|
148
|
+
result = {"message": '查询订单失败'}
|
|
149
|
+
else:
|
|
150
|
+
|
|
129
151
|
result = response.json()
|
|
152
|
+
|
|
130
153
|
return result
|
|
131
154
|
|
|
132
155
|
|
|
@@ -138,18 +161,57 @@ def request_trader(url, param):
|
|
|
138
161
|
return requests.post(total_url, data=param, headers=headers)
|
|
139
162
|
|
|
140
163
|
|
|
164
|
+
# 获取交易价格
|
|
165
|
+
def get_trade_price(terminal, symbol, price_code, limit_chg):
|
|
166
|
+
param_position = {
|
|
167
|
+
'symbol': symbol,
|
|
168
|
+
'terminal': terminal,
|
|
169
|
+
'price_code': price_code,
|
|
170
|
+
'limit_chg': limit_chg}
|
|
171
|
+
|
|
172
|
+
param_json = json.dumps(param_position)
|
|
173
|
+
response = request_trader('/trade/price', param_json)
|
|
174
|
+
if response.status_code != 200:
|
|
175
|
+
result = {"message": '获取行情失败'}
|
|
176
|
+
else:
|
|
177
|
+
result = response.json()
|
|
178
|
+
return result
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# 获取qmt 行情
|
|
182
|
+
def get_qmt_real_time_quotes_detail(terminal, symbol_list):
|
|
183
|
+
param_position = {
|
|
184
|
+
'symbol_list': symbol_list,
|
|
185
|
+
'terminal': terminal}
|
|
186
|
+
|
|
187
|
+
param_json = json.dumps(param_position)
|
|
188
|
+
response = request_trader('/qmt/real/time/quotes/detail', param_json)
|
|
189
|
+
if response.status_code != 200:
|
|
190
|
+
result = {"message": '获取行情失败'}
|
|
191
|
+
else:
|
|
192
|
+
result = response.json()
|
|
193
|
+
return result
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
from mns_common.component.deal.terminal_enum import TerminalEnum
|
|
197
|
+
|
|
141
198
|
if __name__ == '__main__':
|
|
142
|
-
|
|
143
|
-
get_position(
|
|
199
|
+
terminal_test = TerminalEnum.QMT.terminal_code
|
|
200
|
+
get_position(terminal_test)
|
|
201
|
+
symbol_one_test = ['301181.SZ']
|
|
202
|
+
result_json = get_qmt_real_time_quotes_detail(terminal_test, symbol_one_test)
|
|
203
|
+
print(result_json)
|
|
204
|
+
# auto_login('qmt')
|
|
205
|
+
# get_position('qmt')
|
|
144
206
|
# terminal_test = 'easy_trader'
|
|
145
207
|
# order_cancel('251145121', terminal_test)
|
|
146
208
|
# get_position(terminal_test)
|
|
147
209
|
# auto_ipo_buy(terminal_test)
|
|
148
|
-
trade_buy(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
210
|
+
# trade_buy(
|
|
211
|
+
# '301314.SZ',
|
|
212
|
+
# 35.77,
|
|
213
|
+
# 1000000,
|
|
214
|
+
# 'qmt')
|
|
153
215
|
# trade_sell(
|
|
154
216
|
# '301314',
|
|
155
217
|
# 35.77,
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
file_path = os.path.abspath(__file__)
|
|
5
|
+
end = file_path.index('mns') + 16
|
|
6
|
+
project_path = file_path[0:end]
|
|
7
|
+
sys.path.append(project_path)
|
|
8
|
+
import json
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
'''
|
|
12
|
+
|
|
13
|
+
'''
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def trade_buy(symbol, buy_price, buy_volume, terminal):
|
|
17
|
+
'''
|
|
18
|
+
买入
|
|
19
|
+
:param symbol:
|
|
20
|
+
:param buy_price:
|
|
21
|
+
:param buy_volume:
|
|
22
|
+
:param terminal:
|
|
23
|
+
:return:
|
|
24
|
+
'''
|
|
25
|
+
param_buy = {
|
|
26
|
+
'symbol': symbol,
|
|
27
|
+
'buy_price': buy_price,
|
|
28
|
+
'buy_volume': buy_volume,
|
|
29
|
+
'terminal': terminal}
|
|
30
|
+
param_json = json.dumps(param_buy)
|
|
31
|
+
response = request_trader_post('/buy', param_json)
|
|
32
|
+
if response.status_code != 200:
|
|
33
|
+
buy_result = {"message": '买入失败'}
|
|
34
|
+
else:
|
|
35
|
+
buy_result = response.json()
|
|
36
|
+
return buy_result
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def trade_sell(symbol, sell_price, sell_volume, terminal):
|
|
40
|
+
'''
|
|
41
|
+
卖出
|
|
42
|
+
:param symbol:
|
|
43
|
+
:param sell_price:
|
|
44
|
+
:param sell_volume:
|
|
45
|
+
:param terminal:
|
|
46
|
+
:return:
|
|
47
|
+
'''
|
|
48
|
+
param_sell = {
|
|
49
|
+
'symbol': symbol,
|
|
50
|
+
'sell_price': sell_price,
|
|
51
|
+
'sell_volume': sell_volume,
|
|
52
|
+
'terminal': terminal}
|
|
53
|
+
param_json = json.dumps(param_sell)
|
|
54
|
+
response = request_trader_post('/sell', param_json)
|
|
55
|
+
if response.status_code != 200:
|
|
56
|
+
sell_result = {"message": '卖出失败'}
|
|
57
|
+
else:
|
|
58
|
+
sell_result = response.json()
|
|
59
|
+
return sell_result
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def auto_ipo_buy(terminal):
|
|
63
|
+
'''
|
|
64
|
+
自动打新
|
|
65
|
+
:param terminal:
|
|
66
|
+
:return:
|
|
67
|
+
'''
|
|
68
|
+
param_auto_ipo = {
|
|
69
|
+
'terminal': terminal}
|
|
70
|
+
param_json = json.dumps(param_auto_ipo)
|
|
71
|
+
response = request_trader_get('/auto/ipo/buy', param_json)
|
|
72
|
+
if response.status_code != 200:
|
|
73
|
+
result = {"message": '自动打新失败'}
|
|
74
|
+
else:
|
|
75
|
+
result = response.json()
|
|
76
|
+
return result
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_position(terminal):
|
|
80
|
+
'''
|
|
81
|
+
获取持仓
|
|
82
|
+
:param terminal:
|
|
83
|
+
:return:
|
|
84
|
+
'''
|
|
85
|
+
param_position = {
|
|
86
|
+
'terminal': terminal}
|
|
87
|
+
param_json = json.dumps(param_position)
|
|
88
|
+
response = request_trader_get('/position', param_json)
|
|
89
|
+
if response.status_code != 200:
|
|
90
|
+
result = {"message": '获取持仓失败'}
|
|
91
|
+
else:
|
|
92
|
+
result = response.json()
|
|
93
|
+
return result
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def order_cancel(entrust_no, terminal):
|
|
97
|
+
'''
|
|
98
|
+
撤单
|
|
99
|
+
:param entrust_no:
|
|
100
|
+
:param terminal:
|
|
101
|
+
:return:
|
|
102
|
+
'''
|
|
103
|
+
param_cancel = {
|
|
104
|
+
"entrust_no": entrust_no,
|
|
105
|
+
'terminal': terminal}
|
|
106
|
+
param_json = json.dumps(param_cancel)
|
|
107
|
+
response = request_trader_post('/cancel', param_json)
|
|
108
|
+
if response.status_code != 200:
|
|
109
|
+
result = {"message": '撤单失败'}
|
|
110
|
+
else:
|
|
111
|
+
result = response.json()
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# 自动登陆接口
|
|
116
|
+
def auto_login(terminal):
|
|
117
|
+
'''
|
|
118
|
+
自动登陆客户端
|
|
119
|
+
:param terminal:
|
|
120
|
+
:return:
|
|
121
|
+
'''
|
|
122
|
+
param_position = {
|
|
123
|
+
'terminal': terminal}
|
|
124
|
+
param_json = json.dumps(param_position)
|
|
125
|
+
response = request_trader_post('/auto/login', param_json)
|
|
126
|
+
if response.status_code != 200:
|
|
127
|
+
result = {"message": '获取持仓失败'}
|
|
128
|
+
else:
|
|
129
|
+
result = response.json()
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def request_trader_post(url, param):
|
|
134
|
+
total_url = "http://127.0.0.1:5002/api/trade" + url
|
|
135
|
+
headers = {
|
|
136
|
+
"Content-Type": "application/json"
|
|
137
|
+
}
|
|
138
|
+
return requests.post(total_url, data=param, headers=headers)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def request_trader_get(url, param):
|
|
142
|
+
total_url = "http://127.0.0.1:5002/api/trade" + url
|
|
143
|
+
headers = {
|
|
144
|
+
"Content-Type": "application/json"
|
|
145
|
+
}
|
|
146
|
+
return requests.get(total_url, data=param, headers=headers)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == '__main__':
|
|
150
|
+
# auto_login('qmt')
|
|
151
|
+
# get_position('qmt')
|
|
152
|
+
# terminal_test = 'easy_trader'
|
|
153
|
+
# order_cancel('251145121', terminal_test)
|
|
154
|
+
# get_position(terminal_test)
|
|
155
|
+
# auto_ipo_buy(terminal_test)
|
|
156
|
+
buy_result_test = trade_buy(
|
|
157
|
+
'688693.SH',
|
|
158
|
+
36.39,
|
|
159
|
+
1000,
|
|
160
|
+
'ths')
|
|
161
|
+
entrust_no_test = buy_result_test['entrust_no']
|
|
162
|
+
order_cancel(entrust_no_test, 'ths')
|
|
163
|
+
# trade_sell(
|
|
164
|
+
# '301314',
|
|
165
|
+
# 35.77,
|
|
166
|
+
# 100,
|
|
167
|
+
# 'easy_trader')
|
|
@@ -13,7 +13,12 @@ mongodb_util = MongodbUtil('27017')
|
|
|
13
13
|
|
|
14
14
|
# 获取东方财富A股全部信息
|
|
15
15
|
def get_a_stock_info():
|
|
16
|
-
|
|
16
|
+
em_a_stock_info = mongodb_util.find_all_data(extra_income_db_name.EM_A_STOCK_INFO)
|
|
17
|
+
em_a_stock_info['list_date'].fillna(19890604, inplace=True)
|
|
18
|
+
em_a_stock_info['list_date'] = em_a_stock_info['list_date'].replace(99990909, 19890604)
|
|
19
|
+
em_a_stock_info['list_date'] = em_a_stock_info['list_date'].replace(0, 19890604)
|
|
20
|
+
em_a_stock_info = em_a_stock_info[~em_a_stock_info['symbol'].str.startswith(('8', '4'))]
|
|
21
|
+
return em_a_stock_info
|
|
17
22
|
|
|
18
23
|
|
|
19
24
|
# 获取东方财富ETF全部信息
|
|
@@ -28,15 +33,19 @@ def get_kzz_info():
|
|
|
28
33
|
|
|
29
34
|
# 获取东方财富美股全部信息
|
|
30
35
|
def get_us_stock_info():
|
|
31
|
-
return mongodb_util.find_all_data(extra_income_db_name.
|
|
36
|
+
return mongodb_util.find_all_data(extra_income_db_name.US_STOCK_INFO_EM)
|
|
32
37
|
|
|
33
38
|
|
|
34
39
|
# 获取东方财富美股 eft全部信息
|
|
35
40
|
def get_us_etf_info():
|
|
36
|
-
return mongodb_util.find_all_data(extra_income_db_name.
|
|
41
|
+
return mongodb_util.find_all_data(extra_income_db_name.US_ETF_INFO_EM)
|
|
37
42
|
|
|
38
43
|
|
|
39
44
|
# 获取东方财富港股全部信息
|
|
40
45
|
|
|
41
46
|
def get_hk_stock_info():
|
|
42
47
|
return mongodb_util.find_all_data(extra_income_db_name.EM_HK_STOCK_INFO)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
get_a_stock_info()
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from typing import Optional, Callable
|
|
4
|
+
|
|
5
|
+
class ExceptionMonitor:
|
|
6
|
+
"""支持动态配置的异常监控器"""
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
threshold: int = 1000,
|
|
10
|
+
alert_handler: Optional[Callable[[int, int], None]] = None,
|
|
11
|
+
auto_reset: bool = True
|
|
12
|
+
):
|
|
13
|
+
"""
|
|
14
|
+
:param threshold: 报警阈值,默认1000次
|
|
15
|
+
:param alert_handler: 自定义报警函数,格式 func(current_count, threshold)
|
|
16
|
+
:param auto_reset: 触发报警后是否自动重置计数器
|
|
17
|
+
"""
|
|
18
|
+
self.counter = 0
|
|
19
|
+
self._threshold = threshold
|
|
20
|
+
self.alert_handler = alert_handler
|
|
21
|
+
self.auto_reset = auto_reset
|
|
22
|
+
self.lock = threading.Lock()
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def threshold(self) -> int:
|
|
26
|
+
"""当前报警阈值"""
|
|
27
|
+
return self._threshold
|
|
28
|
+
|
|
29
|
+
@threshold.setter
|
|
30
|
+
def threshold(self, value: int):
|
|
31
|
+
"""动态设置报警阈值"""
|
|
32
|
+
with self.lock:
|
|
33
|
+
self._threshold = value
|
|
34
|
+
|
|
35
|
+
def increment(self):
|
|
36
|
+
"""线程安全的计数器递增"""
|
|
37
|
+
with self.lock:
|
|
38
|
+
self.counter += 1
|
|
39
|
+
if self.counter >= self.threshold:
|
|
40
|
+
self.trigger_alert()
|
|
41
|
+
if self.auto_reset:
|
|
42
|
+
self.reset_counter()
|
|
43
|
+
|
|
44
|
+
def reset_counter(self):
|
|
45
|
+
"""手动重置计数器"""
|
|
46
|
+
with self.lock:
|
|
47
|
+
self.counter = 0
|
|
48
|
+
|
|
49
|
+
def trigger_alert(self):
|
|
50
|
+
"""触发报警(支持自定义处理逻辑)"""
|
|
51
|
+
if self.alert_handler:
|
|
52
|
+
self.alert_handler(self.counter, self.threshold)
|
|
53
|
+
else:
|
|
54
|
+
print(f"[ALERT] Exception count {self.counter} exceeded threshold {self.threshold}")
|
|
55
|
+
|
|
56
|
+
def exception_counter(
|
|
57
|
+
threshold: int = 1000,
|
|
58
|
+
alert_handler: Optional[Callable[[int, int], None]] = None,
|
|
59
|
+
auto_reset: bool = True
|
|
60
|
+
):
|
|
61
|
+
"""
|
|
62
|
+
异常计数装饰器工厂
|
|
63
|
+
:param threshold: 报警阈值
|
|
64
|
+
:param alert_handler: 自定义报警处理函数
|
|
65
|
+
:param auto_reset: 是否自动重置计数器
|
|
66
|
+
"""
|
|
67
|
+
def decorator(func):
|
|
68
|
+
# 为每个被装饰函数创建独立监控实例
|
|
69
|
+
monitor = ExceptionMonitor(
|
|
70
|
+
threshold=threshold,
|
|
71
|
+
alert_handler=alert_handler,
|
|
72
|
+
auto_reset=auto_reset
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
@wraps(func)
|
|
76
|
+
def wrapper(*args, **kwargs):
|
|
77
|
+
try:
|
|
78
|
+
return func(*args, **kwargs)
|
|
79
|
+
except Exception as e:
|
|
80
|
+
monitor.increment()
|
|
81
|
+
raise # 保持原始异常栈
|
|
82
|
+
|
|
83
|
+
# 暴露监控器以便外部访问
|
|
84
|
+
wrapper.monitor = monitor
|
|
85
|
+
return wrapper
|
|
86
|
+
return decorator
|