mns-common 1.3.3.5__py3-none-any.whl → 1.5.7.2__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.
- 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 +22 -97
- 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/__init__.py +7 -0
- mns_common/api/em/{east_money_stock_gdfx_free_top_10_api.py → gd/east_money_stock_gdfx_free_top_10_api.py} +64 -9
- mns_common/api/em/real_time/__init__.py +7 -0
- mns_common/api/em/{east_money_debt_api.py → real_time/east_money_debt_api.py} +154 -69
- mns_common/api/em/{east_money_etf_api.py → real_time/east_money_etf_api.py} +149 -27
- mns_common/api/em/real_time/east_money_stock_a_api.py +301 -0
- mns_common/api/em/real_time/east_money_stock_a_v2_api.py +340 -0
- 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 +288 -0
- mns_common/api/em/real_time/east_money_stock_hk_gtt_api.py +260 -0
- mns_common/api/em/real_time/east_money_stock_multi_thread_api_v3.py +154 -0
- mns_common/api/em/{east_money_stock_us_api.py → real_time/east_money_stock_us_api.py} +149 -72
- mns_common/api/em/real_time/real_time_quotes_repeat_api.py +195 -0
- mns_common/api/k_line/stock_k_line_data_api.py +11 -1
- mns_common/api/k_line/stock_minute_data_api.py +1 -0
- 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/proxies/__init__.py +7 -0
- mns_common/api/proxies/liu_guan_proxy_api.py +115 -0
- mns_common/api/ths/company/company_product_area_industry_index_query.py +46 -0
- mns_common/api/ths/company/ths_company_info_api.py +13 -9
- 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 +10 -7
- mns_common/api/ths/zt/ths_stock_zt_pool_api.py +21 -4
- mns_common/api/ths/zt/ths_stock_zt_pool_v2_api.py +111 -40
- mns_common/api/xueqiu/__init__.py +7 -0
- mns_common/api/xueqiu/xue_qiu_k_line_api.py +83 -0
- mns_common/component/__init__.py +1 -1
- mns_common/component/classify/symbol_classify_api.py +7 -7
- mns_common/component/common_service_fun_api.py +66 -6
- mns_common/component/company/company_common_service_api.py +21 -1
- mns_common/component/company/company_common_service_new_api.py +4 -1
- mns_common/component/cookie/cookie_enum.py +15 -0
- mns_common/component/cookie/cookie_info_service.py +9 -4
- 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/__init__.py +7 -0
- mns_common/component/em/em_real_time_quotes_api.py +56 -0
- mns_common/component/em/em_stock_info_api.py +48 -0
- mns_common/component/exception/ExceptionMonitor.py +86 -0
- mns_common/component/exception/__init__.py +7 -0
- mns_common/component/k_line/common/k_line_common_service_api.py +4 -0
- mns_common/component/main_line/__init__.py +7 -0
- mns_common/component/main_line/main_line_zt_reason_service.py +237 -0
- mns_common/component/proxies/__init__.py +7 -0
- mns_common/component/proxies/proxy_common_api.py +252 -0
- mns_common/component/self_choose/__init__.py +13 -0
- 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 +125 -0
- mns_common/constant/__init__.py +1 -0
- mns_common/constant/db_name_constant.py +65 -34
- mns_common/constant/extra_income_db_name.py +154 -0
- mns_common/constant/strategy_classify.py +72 -0
- mns_common/db/MongodbUtil.py +2 -1
- mns_common/db/MongodbUtilLocal.py +1 -0
- mns_common/db/v2/MongodbUtilV2.py +0 -4
- mns_common-1.5.7.2.dist-info/METADATA +4 -0
- {mns_common-1.3.3.5.dist-info → mns_common-1.5.7.2.dist-info}/RECORD +70 -45
- {mns_common-1.3.3.5.dist-info → mns_common-1.5.7.2.dist-info}/WHEEL +1 -1
- mns_common/api/em/east_money_stock_api.py +0 -222
- mns_common/api/em/east_money_stock_hk_api.py +0 -318
- mns_common/api/em/east_money_stock_v2_api.py +0 -219
- 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-1.3.3.5.dist-info/METADATA +0 -4
- /mns_common/{component/qmt → api/em/concept}/__init__.py +0 -0
- /mns_common/api/em/{em_concept_index_api.py → concept/em_concept_index_api.py} +0 -0
- {mns_common-1.3.3.5.dist-info → mns_common-1.5.7.2.dist-info}/top_level.txt +0 -0
|
@@ -14,7 +14,7 @@ end = file_path.index('mns') + 14
|
|
|
14
14
|
project_path = file_path[0:end]
|
|
15
15
|
sys.path.append(project_path)
|
|
16
16
|
import re
|
|
17
|
-
import mns_common.component.company.
|
|
17
|
+
import mns_common.component.company.company_common_service_new_api as company_common_service_new_api
|
|
18
18
|
import mns_common.component.zt.zt_common_service_api as zt_common_service_api
|
|
19
19
|
from loguru import logger
|
|
20
20
|
# question
|
|
@@ -40,7 +40,7 @@ from loguru import logger
|
|
|
40
40
|
# 当设置具体数值n时,循环请求n页,返回n页合并数据。
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
import mns_common.
|
|
43
|
+
import mns_common.component.em.em_real_time_quotes_api as em_real_time_quotes_api
|
|
44
44
|
from mns_common.db.MongodbUtil import MongodbUtil
|
|
45
45
|
import pandas as pd
|
|
46
46
|
import mns_common.component.common_service_fun_api as common_service_fun_api
|
|
@@ -139,13 +139,13 @@ def convert_statistics(stat):
|
|
|
139
139
|
|
|
140
140
|
# 获取实时行情涨停列表
|
|
141
141
|
def get_real_time_zt_info():
|
|
142
|
-
real_time_df =
|
|
143
|
-
real_time_df_zt = real_time_df.loc[
|
|
142
|
+
real_time_df = em_real_time_quotes_api.get_real_time_quotes_now(None, None)
|
|
143
|
+
real_time_df_zt = real_time_df.loc[
|
|
144
|
+
(real_time_df['chg'] > common_service_fun_api.ZT_CHG) | (real_time_df['wei_bi'] == 100)]
|
|
144
145
|
if data_frame_util.is_empty(real_time_df_zt):
|
|
145
146
|
return pd.DataFrame()
|
|
146
147
|
real_time_df_zt = real_time_df_zt[[
|
|
147
148
|
'symbol',
|
|
148
|
-
'name',
|
|
149
149
|
'chg',
|
|
150
150
|
'amount',
|
|
151
151
|
'quantity_ratio',
|
|
@@ -153,16 +153,17 @@ def get_real_time_zt_info():
|
|
|
153
153
|
'high',
|
|
154
154
|
'low',
|
|
155
155
|
'open',
|
|
156
|
-
'list_date',
|
|
157
156
|
'exchange',
|
|
158
157
|
'wei_bi',
|
|
159
158
|
'flow_mv',
|
|
160
159
|
'total_mv',
|
|
161
160
|
'buy_1_num'
|
|
162
161
|
]]
|
|
163
|
-
company_df =
|
|
162
|
+
company_df = company_common_service_new_api.get_company_all_info_info()
|
|
164
163
|
company_df = company_df[[
|
|
165
164
|
'_id',
|
|
165
|
+
'name',
|
|
166
|
+
'list_date',
|
|
166
167
|
"industry",
|
|
167
168
|
"first_sw_industry",
|
|
168
169
|
"second_sw_industry",
|
|
@@ -173,9 +174,6 @@ def get_real_time_zt_info():
|
|
|
173
174
|
"em_industry",
|
|
174
175
|
"company_type",
|
|
175
176
|
"mv_circulation_ratio",
|
|
176
|
-
"ths_concept_list_info",
|
|
177
|
-
"kpl_plate_name",
|
|
178
|
-
"kpl_plate_list_info",
|
|
179
177
|
"diff_days"
|
|
180
178
|
]]
|
|
181
179
|
company_df = company_df.loc[company_df['_id'].isin(real_time_df_zt['symbol'])]
|
|
@@ -200,24 +198,83 @@ def get_now_zt_pool_with_reason(str_day):
|
|
|
200
198
|
real_time_zt_df = get_real_time_zt_info()
|
|
201
199
|
# 昨日涨停列表
|
|
202
200
|
last_trade_zt = zt_common_service_api.get_last_trade_day_zt(str_day)
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
# 东方财富涨停列表
|
|
204
|
+
em_now_zt_pool = stock_zt_pool_api.stock_em_zt_pool_df(date_handle_util.no_slash_date(str_day))
|
|
205
|
+
except BaseException as e:
|
|
206
|
+
em_now_zt_pool = pd.DataFrame()
|
|
207
|
+
logger.error("获取东方财富涨停列表异常:{}", e)
|
|
208
|
+
|
|
205
209
|
if data_frame_util.is_not_empty(em_now_zt_pool):
|
|
206
210
|
real_time_zt_df_wei_bi_100 = real_time_zt_df.loc[real_time_zt_df['symbol'].isin(em_now_zt_pool['symbol'])]
|
|
207
211
|
real_time_zt_df_high_chg = real_time_zt_df.loc[~(real_time_zt_df['symbol'].isin(em_now_zt_pool['symbol']))]
|
|
212
|
+
|
|
213
|
+
em_now_zt_pool = em_now_zt_pool[['symbol',
|
|
214
|
+
'connected_boards_numbers',
|
|
215
|
+
'statistics',
|
|
216
|
+
'closure_funds',
|
|
217
|
+
'first_closure_time',
|
|
218
|
+
'last_closure_time',
|
|
219
|
+
'frying_plates_numbers']]
|
|
220
|
+
|
|
221
|
+
em_now_zt_pool = em_now_zt_pool.set_index(['symbol'], drop=True)
|
|
222
|
+
real_time_zt_df_wei_bi_100 = real_time_zt_df_wei_bi_100.set_index(['symbol'], drop=False)
|
|
223
|
+
real_time_zt_df_wei_bi_100 = pd.merge(real_time_zt_df_wei_bi_100, em_now_zt_pool, how='outer',
|
|
224
|
+
left_index=True, right_index=True)
|
|
225
|
+
|
|
226
|
+
now_continue_zt = last_trade_zt.loc[
|
|
227
|
+
last_trade_zt['symbol'].isin(list(real_time_zt_df_wei_bi_100['symbol']))]
|
|
228
|
+
|
|
208
229
|
else:
|
|
209
|
-
|
|
230
|
+
real_time_zt_df_wei_bi_100 = real_time_zt_df.loc[real_time_zt_df['wei_bi'] == 100]
|
|
231
|
+
|
|
232
|
+
real_time_zt_df_wei_bi_100['connected_boards_numbers'] = 1
|
|
233
|
+
real_time_zt_df_wei_bi_100['statistics'] = '1/1'
|
|
234
|
+
real_time_zt_df_wei_bi_100['closure_funds'] = real_time_zt_df_wei_bi_100['now_price'] * \
|
|
235
|
+
real_time_zt_df_wei_bi_100['buy_1_num'] * 100
|
|
236
|
+
real_time_zt_df_wei_bi_100['first_closure_time'] = '153000'
|
|
237
|
+
real_time_zt_df_wei_bi_100['last_closure_time'] = '153000'
|
|
238
|
+
real_time_zt_df_wei_bi_100['frying_plates_numbers'] = 0
|
|
239
|
+
now_continue_zt = last_trade_zt.loc[
|
|
240
|
+
last_trade_zt['symbol'].isin(list(real_time_zt_df_wei_bi_100['symbol']))]
|
|
241
|
+
|
|
242
|
+
if data_frame_util.is_not_empty(now_continue_zt):
|
|
243
|
+
now_continue_zt = now_continue_zt[['symbol', 'connected_boards_numbers', 'statistics']]
|
|
244
|
+
|
|
245
|
+
connected_boards_map = now_continue_zt.set_index('symbol')['connected_boards_numbers'].to_dict()
|
|
246
|
+
|
|
247
|
+
# 将映射的值加到原DataFrame上
|
|
248
|
+
real_time_zt_df_wei_bi_100['connected_boards_numbers'] = real_time_zt_df_wei_bi_100[
|
|
249
|
+
'connected_boards_numbers'] + \
|
|
250
|
+
real_time_zt_df_wei_bi_100['symbol'].map(
|
|
251
|
+
connected_boards_map).fillna(0)
|
|
252
|
+
|
|
253
|
+
real_time_zt_df_wei_bi_100 = real_time_zt_df_wei_bi_100.sort_values(by=['connected_boards_numbers'],
|
|
254
|
+
ascending=False)
|
|
255
|
+
|
|
256
|
+
real_time_zt_df_high_chg = real_time_zt_df.loc[real_time_zt_df['wei_bi'] != 100]
|
|
257
|
+
|
|
258
|
+
# todo
|
|
259
|
+
# 高涨幅处理
|
|
260
|
+
now_zt_pool_df = handle_high_chg(real_time_zt_df_high_chg, last_trade_zt, real_time_zt_df_wei_bi_100)
|
|
261
|
+
|
|
262
|
+
now_zt_pool_df = merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt, now_continue_zt)
|
|
263
|
+
|
|
264
|
+
result_first = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] == 1]
|
|
265
|
+
result_connected_boards = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] > 1]
|
|
266
|
+
result_connected_boards = result_connected_boards.sort_values(by=['connected_boards_numbers'], ascending=False)
|
|
267
|
+
result_first = result_first.sort_values(by=['first_closure_time'], ascending=True)
|
|
268
|
+
|
|
269
|
+
now_zt_pool_df = pd.concat([result_connected_boards,
|
|
270
|
+
result_first])
|
|
271
|
+
now_zt_pool_df = now_zt_pool_df.fillna('未知数据')
|
|
272
|
+
now_zt_pool_df.drop_duplicates('symbol', keep='last', inplace=True)
|
|
210
273
|
|
|
211
|
-
|
|
212
|
-
['symbol', 'connected_boards_numbers',
|
|
213
|
-
'statistics', 'closure_funds', 'first_closure_time',
|
|
214
|
-
'last_closure_time', 'frying_plates_numbers']]
|
|
274
|
+
return now_zt_pool_df
|
|
215
275
|
|
|
216
|
-
em_now_zt_pool = em_now_zt_pool.set_index(['symbol'], drop=True)
|
|
217
|
-
real_time_zt_df_wei_bi_100 = real_time_zt_df_wei_bi_100.set_index(['symbol'], drop=False)
|
|
218
|
-
real_time_zt_df_wei_bi_100 = pd.merge(real_time_zt_df_wei_bi_100, em_now_zt_pool, how='outer',
|
|
219
|
-
left_index=True, right_index=True)
|
|
220
276
|
|
|
277
|
+
def handle_high_chg(real_time_zt_df_high_chg, last_trade_zt, real_time_zt_df_wei_bi_100):
|
|
221
278
|
# 初始化数据
|
|
222
279
|
real_time_zt_df_high_chg['closure_funds'] = 0
|
|
223
280
|
real_time_zt_df_high_chg['first_closure_time'] = '153000'
|
|
@@ -231,6 +288,7 @@ def get_now_zt_pool_with_reason(str_day):
|
|
|
231
288
|
|
|
232
289
|
last_trade_zt_copy_today_high_chg = last_trade_zt.loc[
|
|
233
290
|
last_trade_zt['symbol'].isin(real_time_zt_df_high_chg_last_trade_zt['symbol'])]
|
|
291
|
+
|
|
234
292
|
last_trade_zt_copy_today_high_chg = last_trade_zt_copy_today_high_chg[
|
|
235
293
|
['symbol', 'connected_boards_numbers', 'statistics']]
|
|
236
294
|
last_trade_zt_copy_today_high_chg['connected_boards_numbers'] = last_trade_zt_copy_today_high_chg[
|
|
@@ -250,21 +308,10 @@ def get_now_zt_pool_with_reason(str_day):
|
|
|
250
308
|
real_time_zt_df_high_chg_last_trade_zt,
|
|
251
309
|
real_time_zt_df_high_chg_last_trade_no_zt])
|
|
252
310
|
|
|
253
|
-
now_zt_pool_df = merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt)
|
|
254
|
-
|
|
255
|
-
result_first = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] == 1]
|
|
256
|
-
result_connected_boards = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] > 1]
|
|
257
|
-
result_connected_boards = result_connected_boards.sort_values(by=['connected_boards_numbers'], ascending=False)
|
|
258
|
-
result_first = result_first.sort_values(by=['first_closure_time'], ascending=True)
|
|
259
|
-
|
|
260
|
-
now_zt_pool_df = pd.concat([result_connected_boards,
|
|
261
|
-
result_first])
|
|
262
|
-
now_zt_pool_df = now_zt_pool_df.fillna('未知数据')
|
|
263
|
-
now_zt_pool_df.drop_duplicates('symbol', keep='last', inplace=True)
|
|
264
311
|
return now_zt_pool_df
|
|
265
312
|
|
|
266
313
|
|
|
267
|
-
def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
|
|
314
|
+
def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt, now_continue_zt):
|
|
268
315
|
try:
|
|
269
316
|
zt_reason_df = get_ths_stock_zt_reason_with_cache(str_day)
|
|
270
317
|
except BaseException as e:
|
|
@@ -272,9 +319,17 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
|
|
|
272
319
|
logger.error("获取涨停原因异常:{}", e)
|
|
273
320
|
|
|
274
321
|
last_trade_zt_copy = last_trade_zt.copy()
|
|
322
|
+
|
|
275
323
|
if "zt_reason" not in last_trade_zt.columns:
|
|
276
324
|
last_trade_zt_copy['zt_reason'] = '暂无'
|
|
277
|
-
|
|
325
|
+
|
|
326
|
+
if 'main_line' not in last_trade_zt.columns:
|
|
327
|
+
last_trade_zt['main_line'] = ''
|
|
328
|
+
|
|
329
|
+
if 'sub_main_line' not in last_trade_zt.columns:
|
|
330
|
+
last_trade_zt['sub_main_line'] = ''
|
|
331
|
+
|
|
332
|
+
last_trade_zt_copy = last_trade_zt_copy[['symbol', 'zt_reason', 'sub_main_line', 'main_line']]
|
|
278
333
|
|
|
279
334
|
if data_frame_util.is_empty(zt_reason_df):
|
|
280
335
|
now_zt_pool_df['zt_reason'] = '暂无'
|
|
@@ -292,6 +347,21 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
|
|
|
292
347
|
zt_reason_df_copy = zt_reason_df_copy.set_index(['symbol'], drop=True)
|
|
293
348
|
now_zt_pool_df = now_zt_pool_df.set_index(['symbol'], drop=False)
|
|
294
349
|
|
|
350
|
+
if data_frame_util.is_not_empty(now_continue_zt):
|
|
351
|
+
now_continue_zt = now_continue_zt[['symbol', 'main_line', 'sub_main_line']]
|
|
352
|
+
|
|
353
|
+
# 创建一个 symbol 到 main_line 的映射
|
|
354
|
+
main_line_mapping = now_continue_zt.set_index('symbol')['main_line'].to_dict()
|
|
355
|
+
|
|
356
|
+
# 使用 map 更新 main_line 列
|
|
357
|
+
now_zt_pool_df['main_line'] = now_zt_pool_df['symbol'].map(main_line_mapping).fillna("")
|
|
358
|
+
|
|
359
|
+
# 创建一个 symbol 到 main_line 的映射
|
|
360
|
+
sub_main_line_mapping = now_continue_zt.set_index('symbol')['sub_main_line'].to_dict()
|
|
361
|
+
|
|
362
|
+
# 使用 map 更新 sub_main_line 列
|
|
363
|
+
now_zt_pool_df['sub_main_line'] = now_zt_pool_df['symbol'].map(sub_main_line_mapping).fillna("")
|
|
364
|
+
|
|
295
365
|
result_zt_df = pd.merge(now_zt_pool_df, zt_reason_df_copy, how='outer',
|
|
296
366
|
left_index=True, right_index=True)
|
|
297
367
|
|
|
@@ -302,8 +372,12 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
|
|
|
302
372
|
last_trade_zt_copy = last_trade_zt_copy.set_index(['symbol'], drop=True)
|
|
303
373
|
del zt_reason_na['zt_reason']
|
|
304
374
|
zt_reason_na = zt_reason_na.set_index(['symbol'], drop=False)
|
|
375
|
+
del last_trade_zt_copy['main_line']
|
|
376
|
+
del last_trade_zt_copy['sub_main_line']
|
|
377
|
+
|
|
305
378
|
zt_reason_na = pd.merge(zt_reason_na, last_trade_zt_copy, how='outer',
|
|
306
379
|
left_index=True, right_index=True)
|
|
380
|
+
|
|
307
381
|
zt_reason_na['zt_reason'] = zt_reason_na['zt_reason'].fillna('0')
|
|
308
382
|
# 删除昨日涨停 今日未涨停的
|
|
309
383
|
zt_reason_na.dropna(subset=['symbol'], inplace=True)
|
|
@@ -366,14 +440,11 @@ def zt_reason_group(zt_pool_df):
|
|
|
366
440
|
|
|
367
441
|
|
|
368
442
|
if __name__ == '__main__':
|
|
369
|
-
str_day_test = '
|
|
370
|
-
|
|
443
|
+
str_day_test = '2025-10-28'
|
|
444
|
+
# 同花顺涨停
|
|
445
|
+
ths_zt_pool_df = get_now_zt_pool_with_reason(str_day_test)
|
|
371
446
|
# 东财涨停池
|
|
372
447
|
em_now_zt_pool_test = stock_zt_pool_api.stock_em_zt_pool_df(date_handle_util.no_slash_date(str_day_test))
|
|
373
|
-
# 同花顺涨停
|
|
374
|
-
ths_zt_pool_df = get_zt_reason(str_day_test)
|
|
375
448
|
|
|
376
449
|
miss_zt_df = em_now_zt_pool_test.loc[~(em_now_zt_pool_test['symbol'].isin(ths_zt_pool_df['symbol']))]
|
|
377
450
|
pass
|
|
378
|
-
|
|
379
|
-
|
|
@@ -0,0 +1,83 @@
|
|
|
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 requests
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# year 年
|
|
13
|
+
# quarter 季度
|
|
14
|
+
# month 月度
|
|
15
|
+
# week 周
|
|
16
|
+
# day 日
|
|
17
|
+
def get_xue_qiu_k_line(symbol, period, cookie, end_time, hq):
|
|
18
|
+
url = "https://stock.xueqiu.com/v5/stock/chart/kline.json"
|
|
19
|
+
|
|
20
|
+
params = {
|
|
21
|
+
"symbol": symbol,
|
|
22
|
+
"begin": end_time,
|
|
23
|
+
"period": period,
|
|
24
|
+
"type": hq,
|
|
25
|
+
"count": "-120084",
|
|
26
|
+
"indicator": "kline,pe,pb,ps,pcf,market_capital,agt,ggt,balance"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
headers = {
|
|
30
|
+
"accept": "application/json, text/plain, */*",
|
|
31
|
+
"accept-language": "zh-CN,zh;q=0.9",
|
|
32
|
+
"origin": "https://xueqiu.com",
|
|
33
|
+
"priority": "u=1, i",
|
|
34
|
+
"referer": "https://xueqiu.com/S/SZ300879?md5__1038=n4%2BxgDniDQeWqxYwq0y%2BbDyG%2BYDtODuD7q%2BqRYID",
|
|
35
|
+
"sec-ch-ua": '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
|
|
36
|
+
"sec-ch-ua-mobile": "?0",
|
|
37
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
38
|
+
"sec-fetch-dest": "empty",
|
|
39
|
+
"sec-fetch-mode": "cors",
|
|
40
|
+
"sec-fetch-site": "same-site",
|
|
41
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
|
|
42
|
+
"cookie": cookie
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
response = requests.get(
|
|
46
|
+
url=url,
|
|
47
|
+
params=params,
|
|
48
|
+
headers=headers
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if response.status_code == 200:
|
|
52
|
+
response_data = response.json()
|
|
53
|
+
df = pd.DataFrame(
|
|
54
|
+
data=response_data['data']['item'],
|
|
55
|
+
columns=response_data['data']['column']
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# 1. 转换为 datetime(自动处理毫秒级时间戳)
|
|
59
|
+
df["beijing_time"] = pd.to_datetime(df["timestamp"], unit="ms")
|
|
60
|
+
|
|
61
|
+
# 2. 设置 UTC 时区
|
|
62
|
+
df["beijing_time"] = df["beijing_time"].dt.tz_localize("UTC")
|
|
63
|
+
|
|
64
|
+
# 3. 转换为北京时间(UTC+8)
|
|
65
|
+
df["beijing_time"] = df["beijing_time"].dt.tz_convert("Asia/Shanghai")
|
|
66
|
+
|
|
67
|
+
# 4. 提取年月日(格式:YYYY-MM-DD)
|
|
68
|
+
df["str_day"] = df["beijing_time"].dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
69
|
+
del df["beijing_time"]
|
|
70
|
+
|
|
71
|
+
return df
|
|
72
|
+
else:
|
|
73
|
+
# 直接抛出带有明确信息的异常
|
|
74
|
+
raise ValueError("调用雪球接口失败")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == '__main__':
|
|
78
|
+
number = 1
|
|
79
|
+
cookies ='cookiesu=291756518429127; device_id=8c5eef4332e51dbcbcd92943b0dd91e4; s=bz17174k1c; xq_a_token=b9c7e702181cba3ed732d5019efe2dfe2fb054b0; xqat=b9c7e702181cba3ed732d5019efe2dfe2fb054b0; xq_r_token=c1edaf05e1c6fdf8122671eced8049e8df8a4290; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTc2MTYxNDEwNywiY3RtIjoxNzU5OTc2NzUxOTI3LCJjaWQiOiJkOWQwbjRBWnVwIn0.JwQMnAT6E1lPSqfK-GnFpLNQz-Jr-xtZ6HoUfnCfeRTNKrDJqf0l5_iY7dhEo6A5m38MmXj0hgR-xYkzPm35fFcQCQnZ06dOK0XCP6AE9r5KVFd73GyqbXLijKDFPQVM0sPgbgCs9fTOmB7Nlju_7B_raPmZ8IIHzZRU6uSK9oXsrnwpo4TD0Mr2nMF3ktVwEQHdkZsjm9mdSZaT9fkDvayFKKmg_O-JbHDZ6mTF1i-zR6oH-5r3g6HJJU9-_NwzZMeBEVnLG8IWwO8_n9CWdpbqQ-qC-iue4yEHFdiTLBCRRgyFauVv0kJS1ZNKvvefxkETTVr-WgXobT82ED7ApA; u=291756518429127; Hm_lvt_1db88642e346389874251b5a1eded6e3=1759765103,1759808830,1759970243,1759976801; HMACCOUNT=4C4F802C04F4D70A; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1759978805'
|
|
80
|
+
while True:
|
|
81
|
+
test_df = get_xue_qiu_k_line('SZ300188', '1m', cookies, '1760065317680', '')
|
|
82
|
+
print(number)
|
|
83
|
+
number = number + 1
|
mns_common/component/__init__.py
CHANGED
|
@@ -35,26 +35,26 @@ def set_stock_type_by_deal_days(real_time_quotes_now_init):
|
|
|
35
35
|
real_time_quotes_now.loc[:, "stock_type"] = stock_type_classify_param['normal_stock']
|
|
36
36
|
# 交易天数五个交易日的股票
|
|
37
37
|
real_time_quotes_now.loc[(real_time_quotes_now['name'].str.startswith('C'))
|
|
38
|
-
| (real_time_quotes_now['deal_days']
|
|
38
|
+
| (real_time_quotes_now['deal_days'] < stock_type_classify_param[
|
|
39
39
|
'sub_stock_new_min_deal_days']), "stock_type"] = stock_type_classify_param['new_stock']
|
|
40
40
|
|
|
41
41
|
# 交易上市6-100天的次新股票
|
|
42
42
|
real_time_quotes_now.loc[
|
|
43
43
|
(real_time_quotes_now['stock_type'] != stock_type_classify_param['new_stock'])
|
|
44
|
-
& (real_time_quotes_now['deal_days']
|
|
45
|
-
& (real_time_quotes_now['deal_days']
|
|
44
|
+
& (real_time_quotes_now['deal_days'] >= stock_type_classify_param['sub_stock_new_min_deal_days'])
|
|
45
|
+
& (real_time_quotes_now['deal_days'] < stock_type_classify_param['sub_new_stock_max_deal_days']),
|
|
46
46
|
"stock_type"] = stock_type_classify_param['sub_stock_new']
|
|
47
47
|
|
|
48
48
|
# 上市次新股 100-365
|
|
49
49
|
real_time_quotes_now.loc[
|
|
50
|
-
(real_time_quotes_now['deal_days']
|
|
51
|
-
& (real_time_quotes_now['deal_days']
|
|
50
|
+
(real_time_quotes_now['deal_days'] >= stock_type_classify_param['sub_new_stock_max_deal_days'])
|
|
51
|
+
& (real_time_quotes_now['deal_days'] < stock_type_classify_param['sub_stock_max_deal_days']),
|
|
52
52
|
"stock_type"] = stock_type_classify_param['sub_stock']
|
|
53
53
|
|
|
54
54
|
# 交易天数 366-730
|
|
55
55
|
real_time_quotes_now.loc[
|
|
56
|
-
(real_time_quotes_now['deal_days']
|
|
57
|
-
& (real_time_quotes_now['deal_days']
|
|
56
|
+
(real_time_quotes_now['deal_days'] >= stock_type_classify_param['sub_stock_max_deal_days'])
|
|
57
|
+
& (real_time_quotes_now['deal_days'] < stock_type_classify_param['normal_stock_max_deal_days']),
|
|
58
58
|
"stock_type"] = stock_type_classify_param['normal_sub_stock']
|
|
59
59
|
|
|
60
60
|
return real_time_quotes_now
|
|
@@ -22,9 +22,9 @@ TEN_THOUSAND = 10000
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def total_mv_classification(real_time_quotes_now):
|
|
25
|
-
real_time_quotes_now['flow_mv_sp'] = round((real_time_quotes_now['flow_mv'] / HUNDRED_MILLION), 2)
|
|
26
|
-
real_time_quotes_now['total_mv_sp'] = round((real_time_quotes_now['total_mv'] / HUNDRED_MILLION), 2)
|
|
27
|
-
real_time_quotes_now['flow_mv_level'] = 0
|
|
25
|
+
real_time_quotes_now.loc[:, 'flow_mv_sp'] = round((real_time_quotes_now['flow_mv'] / HUNDRED_MILLION), 2)
|
|
26
|
+
real_time_quotes_now.loc[:, 'total_mv_sp'] = round((real_time_quotes_now['total_mv'] / HUNDRED_MILLION), 2)
|
|
27
|
+
real_time_quotes_now.loc[:, 'flow_mv_level'] = 0
|
|
28
28
|
|
|
29
29
|
real_time_quotes_now.reset_index(drop=True, inplace=True)
|
|
30
30
|
real_time_quotes_now.loc[(real_time_quotes_now["flow_mv_sp"] >= 0), ['flow_mv_level']] \
|
|
@@ -39,6 +39,20 @@ def classify_symbol(real_time_quotes_now_df):
|
|
|
39
39
|
return real_time_quotes_now_df
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
# 增加前缀
|
|
43
|
+
def add_pre_prefix(real_time_quotes_now_df):
|
|
44
|
+
real_time_quotes_now_df['symbol_prefix'] = real_time_quotes_now_df['symbol'].apply(
|
|
45
|
+
lambda symbol: add_pre_prefix_one(symbol))
|
|
46
|
+
return real_time_quotes_now_df
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# 增加后缀
|
|
50
|
+
def add_after_prefix(real_time_quotes_now_df):
|
|
51
|
+
real_time_quotes_now_df['symbol_prefix'] = real_time_quotes_now_df['symbol'].apply(
|
|
52
|
+
lambda symbol: add_after_prefix_one(symbol))
|
|
53
|
+
return real_time_quotes_now_df
|
|
54
|
+
|
|
55
|
+
|
|
42
56
|
# 单个股票分类
|
|
43
57
|
def classify_symbol_one(symbol):
|
|
44
58
|
if symbol.startswith('3'):
|
|
@@ -54,6 +68,41 @@ def classify_symbol_one(symbol):
|
|
|
54
68
|
return 'X'
|
|
55
69
|
|
|
56
70
|
|
|
71
|
+
# 添加前缀
|
|
72
|
+
def add_pre_prefix_one(symbol):
|
|
73
|
+
symbol_simple = symbol[0:6]
|
|
74
|
+
if bool(1 - is_valid_symbol(symbol_simple)):
|
|
75
|
+
return symbol
|
|
76
|
+
|
|
77
|
+
if symbol_simple.startswith('6'):
|
|
78
|
+
return 'SH' + symbol_simple
|
|
79
|
+
elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
|
|
80
|
+
return 'SZ' + symbol_simple
|
|
81
|
+
else:
|
|
82
|
+
return 'BJ' + symbol_simple
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def is_valid_symbol(symbol):
|
|
86
|
+
# 确保输入是字符串(避免数字或其他类型)
|
|
87
|
+
if not isinstance(symbol, str):
|
|
88
|
+
return False
|
|
89
|
+
# 检查长度是否为6且所有字符都是数字
|
|
90
|
+
return len(symbol) == 6 and symbol.isdigit()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# 添加后缀
|
|
94
|
+
def add_after_prefix_one(symbol):
|
|
95
|
+
symbol_simple = symbol[0:6]
|
|
96
|
+
if bool(1 - is_valid_symbol(symbol_simple)):
|
|
97
|
+
return symbol
|
|
98
|
+
if symbol_simple.startswith('6'):
|
|
99
|
+
return symbol_simple + '.SH'
|
|
100
|
+
elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
|
|
101
|
+
return symbol_simple + '.SZ'
|
|
102
|
+
else:
|
|
103
|
+
return symbol_simple + '.BJ'
|
|
104
|
+
|
|
105
|
+
|
|
57
106
|
def symbol_amount_simple(real_time_quotes_now_df):
|
|
58
107
|
real_time_quotes_now_df['amount_level'] = round(real_time_quotes_now_df['amount'] / HUNDRED_MILLION, 2)
|
|
59
108
|
return real_time_quotes_now_df
|
|
@@ -82,8 +131,7 @@ def exclude_st_symbol(real_time_quotes_now_df):
|
|
|
82
131
|
# 排除带星的ST 容易退市
|
|
83
132
|
def exclude_star_st_symbol(df):
|
|
84
133
|
exclude_st_symbol_list = list(
|
|
85
|
-
df.loc[(df['name'].str.contains('\*'))
|
|
86
|
-
| (df['name'].str.contains('退'))]['symbol'])
|
|
134
|
+
df.loc[(df['name'].str.contains(r'\*')) | (df['name'].str.contains('退'))]['symbol'])
|
|
87
135
|
return df.loc[
|
|
88
136
|
~(df['symbol'].isin(
|
|
89
137
|
exclude_st_symbol_list))]
|
|
@@ -145,6 +193,18 @@ def group_by_industry_sum(real_time_quotes_now, field1, field2):
|
|
|
145
193
|
return pd.DataFrame({field1: df_series.index, field2: df_series.values})
|
|
146
194
|
|
|
147
195
|
|
|
196
|
+
def symbol_add_prefix(symbol):
|
|
197
|
+
if bool(1 - symbol.isdigit()):
|
|
198
|
+
return symbol
|
|
199
|
+
symbol_simple = symbol[0:6]
|
|
200
|
+
if symbol_simple.startswith('6'):
|
|
201
|
+
return '1.' + symbol_simple
|
|
202
|
+
elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
|
|
203
|
+
return '0.' + symbol_simple
|
|
204
|
+
else:
|
|
205
|
+
return '0.' + symbol_simple
|
|
148
206
|
|
|
149
207
|
|
|
150
|
-
|
|
208
|
+
# 排除改变代码的北交所
|
|
209
|
+
def exclude_change_bjs_code(df):
|
|
210
|
+
return df[~df['symbol'].str.startswith(('8', '4'))]
|
|
@@ -15,6 +15,26 @@ import mns_common.constant.db_name_constant as db_name_constant
|
|
|
15
15
|
mongodb_util = MongodbUtil('27017')
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
@lru_cache(maxsize=None)
|
|
19
|
+
def get_company_info_name():
|
|
20
|
+
return mongodb_util.find_query_data_choose_field('company_info', {},
|
|
21
|
+
{"_id": 1, 'name': 1,
|
|
22
|
+
"industry": 1, "company_type": 1,
|
|
23
|
+
"ths_concept_name": 1, "ths_concept_code": 1,
|
|
24
|
+
"ths_concept_sync_day": 1, 'sub_stock': 1,
|
|
25
|
+
"first_sw_industry": 1, "second_sw_industry": 1,
|
|
26
|
+
"third_sw_industry": 1, "mv_circulation_ratio": 1,
|
|
27
|
+
"diff_days": 1,
|
|
28
|
+
'em_industry': 1,
|
|
29
|
+
'ths_concept_list_info': 1,
|
|
30
|
+
'ths_concept_name_list_str': 1,
|
|
31
|
+
"kpl_plate_name": 1,
|
|
32
|
+
"kpl_plate_list_info": 1,
|
|
33
|
+
'operate_profit': 1,
|
|
34
|
+
'total_operate_income': 1
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
|
|
18
38
|
@lru_cache(maxsize=None)
|
|
19
39
|
def get_company_info_industry():
|
|
20
40
|
return mongodb_util.find_query_data_choose_field('company_info', {},
|
|
@@ -26,7 +46,7 @@ def get_company_info_industry():
|
|
|
26
46
|
"diff_days": 1,
|
|
27
47
|
'em_industry': 1,
|
|
28
48
|
'ths_concept_list_info': 1,
|
|
29
|
-
'ths_concept_name_list_str':1,
|
|
49
|
+
'ths_concept_name_list_str': 1,
|
|
30
50
|
"kpl_plate_name": 1,
|
|
31
51
|
"kpl_plate_list_info": 1,
|
|
32
52
|
'operate_profit': 1,
|
|
@@ -9,6 +9,8 @@ from functools import lru_cache
|
|
|
9
9
|
from mns_common.db.MongodbUtil import MongodbUtil
|
|
10
10
|
import mns_common.constant.db_name_constant as db_name_constant
|
|
11
11
|
import pandas as pd
|
|
12
|
+
pd.set_option('future.no_silent_downcasting', True)
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
mongodb_util = MongodbUtil('27017')
|
|
14
16
|
|
|
@@ -102,7 +104,8 @@ def amend_ths_industry(real_time_quotes_now_init):
|
|
|
102
104
|
na_industry_data = na_industry_data.loc[na_industry_data['amount'] != 0]
|
|
103
105
|
|
|
104
106
|
real_time_quotes_now_result = pd.concat([real_time_quotes_now, na_industry_data], axis=0)
|
|
105
|
-
real_time_quotes_now
|
|
107
|
+
real_time_quotes_now.fillna({'connected_boards_numbers': 1}, inplace=True)
|
|
108
|
+
|
|
106
109
|
# 处理na值
|
|
107
110
|
real_time_quotes_now_result.fillna(0, inplace=True)
|
|
108
111
|
return real_time_quotes_now_result
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
'''
|
|
4
|
+
价格枚举
|
|
5
|
+
'''
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CookieEnum(Enum):
|
|
9
|
+
THS_COOKIE = ('ths_cookie', '同花顺cookie')
|
|
10
|
+
EM_COOKIE = ('em_cookie', '东方财富cookie')
|
|
11
|
+
XUE_QIU_COOKIE = ('xue_qiu_cookie', '雪球cookie')
|
|
12
|
+
|
|
13
|
+
def __init__(self, cookie_code, cookie_name):
|
|
14
|
+
self.cookie_code = cookie_code
|
|
15
|
+
self.cookie_name = cookie_name
|
|
@@ -9,18 +9,23 @@ from mns_common.db.MongodbUtil import MongodbUtil
|
|
|
9
9
|
|
|
10
10
|
mongodb_util = MongodbUtil('27017')
|
|
11
11
|
|
|
12
|
-
from functools import lru_cache
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
@lru_cache(maxsize=None)
|
|
13
|
+
# ths cookie
|
|
16
14
|
def get_ths_cookie():
|
|
17
15
|
stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "ths_cookie", })
|
|
18
16
|
ths_cookie = list(stock_account_info['cookie'])[0]
|
|
19
17
|
return ths_cookie
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
# 东财 cookie
|
|
23
21
|
def get_em_cookie():
|
|
24
22
|
stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "em_cookie", })
|
|
25
23
|
em_cookie = list(stock_account_info['cookie'])[0]
|
|
26
24
|
return em_cookie
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# 雪球 cookie
|
|
28
|
+
def get_xue_qiu_cookie():
|
|
29
|
+
stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "xue_qiu_cookie", })
|
|
30
|
+
cookie = list(stock_account_info['cookie'])[0]
|
|
31
|
+
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)
|