mns-common 1.4.1.8__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.
Files changed (50) hide show
  1. mns_common/api/akshare/__init__.py +0 -1
  2. mns_common/api/akshare/k_line_api.py +19 -2
  3. mns_common/api/akshare/stock_bid_ask_api.py +10 -3
  4. mns_common/api/akshare/stock_zb_pool.py +2 -0
  5. mns_common/api/akshare/stock_zt_pool_api.py +1 -1
  6. mns_common/api/em/gd/east_money_stock_gdfx_free_top_10_api.py +62 -7
  7. mns_common/api/em/real_time/__init__.py +1 -1
  8. mns_common/api/em/real_time/east_money_debt_api.py +140 -70
  9. mns_common/api/em/real_time/east_money_etf_api.py +138 -27
  10. mns_common/api/em/real_time/east_money_stock_a_api.py +24 -28
  11. mns_common/api/em/real_time/east_money_stock_a_v2_api.py +97 -53
  12. mns_common/api/em/real_time/east_money_stock_common_api.py +174 -0
  13. mns_common/api/em/real_time/east_money_stock_hk_api.py +223 -272
  14. mns_common/api/em/real_time/east_money_stock_hk_gtt_api.py +260 -0
  15. mns_common/api/em/real_time/east_money_stock_multi_thread_api_v3.py +154 -0
  16. mns_common/api/em/real_time/east_money_stock_us_api.py +146 -82
  17. mns_common/api/em/real_time/real_time_quotes_repeat_api.py +195 -0
  18. mns_common/api/k_line/stock_k_line_data_api.py +11 -1
  19. mns_common/api/kpl/common/kpl_common_api.py +35 -0
  20. mns_common/api/proxies/liu_guan_proxy_api.py +55 -5
  21. mns_common/api/ths/company/company_product_area_industry_index_query.py +46 -0
  22. mns_common/api/ths/company/ths_company_info_api.py +2 -1
  23. mns_common/api/ths/company/ths_company_info_web.py +159 -0
  24. mns_common/api/ths/concept/app/ths_concept_index_app.py +3 -1
  25. mns_common/api/ths/wen_cai/ths_wen_cai_api.py +1 -1
  26. mns_common/api/ths/zt/ths_stock_zt_pool_api.py +20 -1
  27. mns_common/api/ths/zt/ths_stock_zt_pool_v2_api.py +105 -29
  28. mns_common/api/xueqiu/xue_qiu_k_line_api.py +2 -2
  29. mns_common/component/common_service_fun_api.py +26 -6
  30. mns_common/component/data/data_init_api.py +13 -8
  31. mns_common/component/deal/deal_service_api.py +70 -8
  32. mns_common/component/deal/deal_service_v2_api.py +167 -0
  33. mns_common/component/em/em_stock_info_api.py +9 -3
  34. mns_common/component/main_line/main_line_zt_reason_service.py +237 -0
  35. mns_common/component/proxies/proxy_common_api.py +141 -45
  36. mns_common/component/us/us_stock_etf_info_api.py +125 -0
  37. mns_common/constant/db_name_constant.py +40 -16
  38. mns_common/constant/extra_income_db_name.py +79 -19
  39. mns_common/constant/strategy_classify.py +17 -2
  40. mns_common/db/MongodbUtil.py +3 -0
  41. mns_common/db/MongodbUtilLocal.py +3 -0
  42. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/METADATA +1 -1
  43. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/RECORD +47 -41
  44. mns_common/api/ths/concept/web/ths_company_info_web.py +0 -163
  45. mns_common/component/qmt/qmt_buy_service.py +0 -172
  46. mns_common/component/task/real_time_data_sync_check.py +0 -110
  47. /mns_common/component/{qmt → main_line}/__init__.py +0 -0
  48. /mns_common/component/{task → us}/__init__.py +0 -0
  49. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/WHEEL +0 -0
  50. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,46 @@
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
+
9
+ import requests
10
+
11
+
12
+ def company_product_area_industry(symbol, market, date):
13
+ if date is None:
14
+ url = (
15
+ f"https://basic.10jqka.com.cn/basicapi/operate/index/v1/product_index_query/?code={symbol}&market={market}"
16
+ f"&type=stock&account=1&timeField=date&analysisTypes=product,area,industry&sortIndex=income&currency=CNY&level=1&expands=product_introduction&locale=zh_CN")
17
+ else:
18
+
19
+ url = (
20
+ f"https://basic.10jqka.com.cn/basicapi/operate/index/v1/product_index_query/?code={symbol}&market={market}&date={date}"
21
+ f"&type=stock&account=1&timeField=date&analysisTypes=product,area,industry&sortIndex=income&currency=CNY&level=1&expands=product_introduction&locale=zh_CN")
22
+
23
+ headers = {
24
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
25
+ "Accept-Language": "zh-CN,zh;q=0.9",
26
+ "Cache-Control": "max-age=0",
27
+ "Connection": "keep-alive",
28
+ "Sec-Fetch-Dest": "document",
29
+ "Sec-Fetch-Mode": "navigate",
30
+ "Sec-Fetch-Site": "cross-site",
31
+ "Sec-Fetch-User": "?1",
32
+ "Upgrade-Insecure-Requests": "1",
33
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
34
+ "sec-ch-ua": "\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"",
35
+ "sec-ch-ua-mobile": "?0",
36
+ "sec-ch-ua-platform": "\"Windows\"",
37
+ }
38
+
39
+ response = requests.get(url, headers=headers)
40
+ data_json = response.json()
41
+ data_list = data_json['data']
42
+ return data_list
43
+
44
+
45
+ if __name__ == '__main__':
46
+ company_product_area_industry('688551', '17', None)
@@ -177,5 +177,6 @@ mongodb_util = MongodbUtil('27017')
177
177
  if __name__ == '__main__':
178
178
  stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "ths_cookie", })
179
179
  ths_cookie_test = list(stock_account_info['cookie'])[0]
180
- company_df_test = get_company_hot_info('002331', ths_cookie_test)
180
+ company_df_test = get_company_hot_info('600756', ths_cookie_test)
181
+ target_title = company_df_test.split("\n")[0] # 关键修改:提取第一行
181
182
  print(company_df_test)
@@ -0,0 +1,159 @@
1
+ import sys
2
+ import os
3
+
4
+ file_path = os.path.abspath(__file__)
5
+ end = file_path.index('mns') + 14
6
+ project_path = file_path[0:end]
7
+ sys.path.append(project_path)
8
+
9
+ from loguru import logger
10
+ import pandas as pd
11
+ import requests
12
+ from bs4 import BeautifulSoup
13
+
14
+
15
+ # 获取股票基本信息
16
+ # https://basic.10jqka.com.cn/mobile/301016/companyprofilen.html?showtab=1&broker=anelicaiapp
17
+ def get_company_info(symbol: str = "688272") -> pd.DataFrame:
18
+ url = f"http://basic.10jqka.com.cn/mobile/{symbol}/companyprofilen.html?broker=pingan"
19
+ headers = {
20
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iOS AYLCAPP/9.1.2.0/h4526a24eb9445522492fd64caae11b1f scheme/anelicaiapp deviceinfo/I|9.1.2.0|NA|h4526a24eb9445522492fd64caae11b1f pastheme/0",
21
+ "Cookie": "ps_login_app_name=AYLCAPP;ps_login_token_id=N_C993F777ACC500B354C762A2627A8862348FC8163799A08EBEB2301C28A2135D220475787D0E81425C1134E15D8CC8761D639FEDBD46C00FE8EA6482C1E42D9801B19918FB3F5C34;ps_login_union_id=edc29089a2b64e3882062297030a0386;PAS.CURRENTUNIONID=edc29089a2b64e3882062297030a0386"
22
+ }
23
+ r = requests.get(url, headers=headers)
24
+ soup = BeautifulSoup(r.content.decode("utf-8"), 'lxml')
25
+ soup.find('table', attrs={'class': 'leveldatail-tab'}).find_all('tr')
26
+ temp_df = pd.read_html(r.content)[0]
27
+ temp_df = temp_df.T
28
+ temp_df = temp_df.iloc[1:2]
29
+ temp_df.rename(columns={
30
+ 0: "name",
31
+ 1: "former_name",
32
+ 2: "registered_address",
33
+ 3: "chairman",
34
+ 4: "board_secretary",
35
+ 5: "main_business",
36
+ 6: "company_type",
37
+ 7: "controlling_shareholder",
38
+ 8: "actual_controller",
39
+ 9: "ultimate_controller",
40
+ 10: "list_date",
41
+ 11: "issue_price",
42
+ 12: "number_workers",
43
+ 13: "tel",
44
+ 14: "url",
45
+ 15: "email"
46
+ }, inplace=True)
47
+
48
+ return temp_df
49
+
50
+
51
+ # 获取股票详细信息
52
+ # HK市场 https://basic.10jqka.com.cn/mobile/HK1456/profile.html https://basic.10jqka.com.cn/mobile/HK1456/company.html
53
+ # https://basic.10jqka.com.cn/new/HK1456/company.html
54
+ # https://basic.10jqka.com.cn/astockph/briefinfo/index.html?showhead=0&fromshare=1&code=300430&marketid=33&client_userid=ESgcM&back_source=hyperlink&share_hxapp=isc&fontzoom=no#/company/ziliao
55
+ def get_company_info_detail(symbol: str = "688272", market_id: str = "31") -> pd.DataFrame:
56
+ url = f'https://basic.10jqka.com.cn/basicapi/company_info/merge_info/v1/base_info/?code={symbol}&market={market_id}&type=stock'
57
+ headers = {
58
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0',
59
+ 'Host': 'basic.10jqka.com.cn',
60
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
61
+ 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
62
+ 'Accept-Encoding': 'gzip, deflate, br',
63
+ 'Connection': 'keep-alive',
64
+ 'Cookie': 'v=A0CN8EBXN21LtMtpV6ldAxf6Ec8XySSbxq14l7rRDNvuNe77Ytn0Ixa9SDQJ',
65
+ 'Upgrade-Insecure-Requests': '1',
66
+
67
+ }
68
+ r = requests.get(url, headers=headers)
69
+ data_json = r.json()
70
+ status_code = data_json['status_code']
71
+ status_msg = data_json['status_msg']
72
+ if status_code != 0 or status_msg != 'success':
73
+ logger.error("获取symbol公司详细信息异常:{}", symbol)
74
+ return pd.DataFrame()
75
+ if len(data_json['data']['industry']) == 0:
76
+ return pd.DataFrame()
77
+ data_df = pd.DataFrame(data_json['data']['industry'], index=[0])
78
+ data_df = data_df[[
79
+ 'hy',
80
+ 'hycode',
81
+ 'hy2',
82
+ 'hy2code',
83
+ 'hy3',
84
+ 'hy3code',
85
+ ]]
86
+
87
+ business_nature = data_json['data']['business_nature']
88
+ name = data_json['data']['code_name']
89
+ intro = data_json['data']['intro']
90
+ base_business = data_json['data']['base_business']
91
+
92
+ address = data_json['data']['address']
93
+ data_df['symbol'] = symbol
94
+ data_df['name'] = name
95
+
96
+ data_df['business_nature'] = business_nature
97
+
98
+ if len(data_json['data']['management']['holder_controller']) > 0:
99
+ holder_controller = pd.DataFrame(data_json['data']['management']['holder_controller'])
100
+ holder_controller_name = str(list(holder_controller['name'])).strip('[').strip(']').replace("'", "")
101
+ holder_controller_rate = holder_controller['rate']
102
+ data_df['holder_controller_name'] = holder_controller_name
103
+ data_df['holder_controller_rate'] = sum(holder_controller_rate)
104
+ else:
105
+ data_df['holder_controller_name'] = '暂无'
106
+ data_df['holder_controller_rate'] = 0
107
+ if len(data_json['data']['management']['final_controller']) > 0:
108
+ final_controller = pd.DataFrame(data_json['data']['management']['final_controller'])
109
+ final_controller_name = str(list(final_controller['name'])).strip('[').strip(']').replace("'", "")
110
+ final_controller_rate = sum(final_controller['rate'])
111
+ data_df['final_controller_name'] = final_controller_name
112
+ data_df['final_controller_rate'] = final_controller_rate
113
+ else:
114
+ data_df['final_controller_name'] = '暂无'
115
+ data_df['final_controller_rate'] = 0
116
+ if len(data_json['data']['management']['actual_controller']) > 0:
117
+ actual_controller = pd.DataFrame(data_json['data']['management']['actual_controller'])
118
+ actual_controller_name = str(list(actual_controller['name'])).strip('[').strip(']').replace("'", "")
119
+ actual_controller_rate = sum(actual_controller['rate'])
120
+ data_df['actual_controller_name'] = actual_controller_name
121
+ data_df['actual_controller_rate'] = actual_controller_rate
122
+ else:
123
+ data_df['actual_controller_name'] = '暂无'
124
+ data_df['actual_controller_rate'] = 0
125
+
126
+ data_df['base_business'] = base_business
127
+ data_df['intro'] = intro
128
+ data_df['address'] = address
129
+ market_id = data_json['data']['market_id']
130
+ data_df['market_id'] = market_id
131
+ # 初始化数据
132
+ data_df['main_business_list'] = [[]]
133
+ data_df['most_profitable_business'] = ''
134
+ data_df['most_profitable_business_rate'] = ''
135
+ data_df['most_profitable_business_profit'] = ''
136
+
137
+ # 业务构成
138
+ main_business_list = data_json['data']['main_business']
139
+
140
+ if len(main_business_list) > 0:
141
+ # 最盈利业务
142
+ profitable_business = data_json['data']['profitable_business']
143
+
144
+ data_df['main_business_list'] = [main_business_list]
145
+
146
+ most_profitable_business = profitable_business['name']
147
+
148
+ most_profitable_business_rate = profitable_business['profit_rate']
149
+
150
+ most_profitable_business_profit = profitable_business['profit']
151
+
152
+ data_df['most_profitable_business'] = most_profitable_business
153
+ data_df['most_profitable_business_rate'] = most_profitable_business_rate
154
+ data_df['most_profitable_business_profit'] = most_profitable_business_profit
155
+ return data_df
156
+
157
+
158
+ if __name__ == '__main__':
159
+ get_company_info_detail('603683','17')
@@ -152,7 +152,9 @@ from mns_common.db.MongodbUtil import MongodbUtil
152
152
 
153
153
  mongodb_util = MongodbUtil('27017')
154
154
  if __name__ == '__main__':
155
- end_time_test = '20241011093000'
155
+ get_new_concept_from_app_search('886104')
156
+
157
+ end_time_test = '20241011093500'
156
158
  result_df_test = get_ths_concept_his_info('20241011093000', end_time_test, 500, 2)
157
159
  result_df_test['block_code'] = result_df_test['block_code'].astype(int)
158
160
  result_df_test['_id'] = result_df_test['block_code']
@@ -115,7 +115,7 @@ def get_concept_detail_by_wen_cai(concept_name):
115
115
 
116
116
 
117
117
  if __name__ == '__main__':
118
- zt_df = wen_cai_api('涨停', 'stock', )
118
+ zt_df = wen_cai_api('001203涨停分析', 'stock', )
119
119
  print(zt_df)
120
120
  # concept_detail_df = get_concept_detail_by_wen_cai("光纤概念")
121
121
  # concept_df = get_concept_index_by_wen_cai()
@@ -274,5 +274,24 @@ def zt_reason_group(zt_pool_df):
274
274
  return result_group_df
275
275
 
276
276
 
277
+ def zt_analyse_reason(symbol):
278
+ try:
279
+ key = symbol + '涨停分析'
280
+ zt_dict = ths_wen_cai_api.wen_cai_api(key, 'stock')
281
+ zt_analyse_detail = zt_dict['涨停揭秘'][0]['content']['value']
282
+ zt_reason = zt_dict['涨停揭秘'][0]['title']['value']
283
+
284
+ result_dict = {
285
+ 'zt_analyse_detail': zt_analyse_detail,
286
+ 'zt_reason': zt_reason
287
+ }
288
+
289
+ return result_dict
290
+ except BaseException as e:
291
+ logger.error("获取涨停分享异常b:{},{}", symbol, str(e))
292
+ return ''
293
+
294
+
277
295
  if __name__ == '__main__':
278
- get_real_time_zt_info()
296
+ zt_analyse_reason('003027')
297
+ # get_real_time_zt_info()
@@ -140,7 +140,8 @@ def convert_statistics(stat):
140
140
  # 获取实时行情涨停列表
141
141
  def get_real_time_zt_info():
142
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[real_time_df['chg'] > common_service_fun_api.ZT_CHG]
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[[
@@ -197,24 +198,83 @@ def get_now_zt_pool_with_reason(str_day):
197
198
  real_time_zt_df = get_real_time_zt_info()
198
199
  # 昨日涨停列表
199
200
  last_trade_zt = zt_common_service_api.get_last_trade_day_zt(str_day)
200
- # 东方财富涨停列表
201
- em_now_zt_pool = stock_zt_pool_api.stock_em_zt_pool_df(date_handle_util.no_slash_date(str_day))
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
+
202
209
  if data_frame_util.is_not_empty(em_now_zt_pool):
203
210
  real_time_zt_df_wei_bi_100 = real_time_zt_df.loc[real_time_zt_df['symbol'].isin(em_now_zt_pool['symbol'])]
204
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
+
205
229
  else:
206
- real_time_zt_df_high_chg = real_time_zt_df
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)
207
273
 
208
- em_now_zt_pool = em_now_zt_pool[
209
- ['symbol', 'connected_boards_numbers',
210
- 'statistics', 'closure_funds', 'first_closure_time',
211
- 'last_closure_time', 'frying_plates_numbers']]
274
+ return now_zt_pool_df
212
275
 
213
- em_now_zt_pool = em_now_zt_pool.set_index(['symbol'], drop=True)
214
- real_time_zt_df_wei_bi_100 = real_time_zt_df_wei_bi_100.set_index(['symbol'], drop=False)
215
- real_time_zt_df_wei_bi_100 = pd.merge(real_time_zt_df_wei_bi_100, em_now_zt_pool, how='outer',
216
- left_index=True, right_index=True)
217
276
 
277
+ def handle_high_chg(real_time_zt_df_high_chg, last_trade_zt, real_time_zt_df_wei_bi_100):
218
278
  # 初始化数据
219
279
  real_time_zt_df_high_chg['closure_funds'] = 0
220
280
  real_time_zt_df_high_chg['first_closure_time'] = '153000'
@@ -228,6 +288,7 @@ def get_now_zt_pool_with_reason(str_day):
228
288
 
229
289
  last_trade_zt_copy_today_high_chg = last_trade_zt.loc[
230
290
  last_trade_zt['symbol'].isin(real_time_zt_df_high_chg_last_trade_zt['symbol'])]
291
+
231
292
  last_trade_zt_copy_today_high_chg = last_trade_zt_copy_today_high_chg[
232
293
  ['symbol', 'connected_boards_numbers', 'statistics']]
233
294
  last_trade_zt_copy_today_high_chg['connected_boards_numbers'] = last_trade_zt_copy_today_high_chg[
@@ -247,21 +308,10 @@ def get_now_zt_pool_with_reason(str_day):
247
308
  real_time_zt_df_high_chg_last_trade_zt,
248
309
  real_time_zt_df_high_chg_last_trade_no_zt])
249
310
 
250
- now_zt_pool_df = merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt)
251
-
252
- result_first = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] == 1]
253
- result_connected_boards = now_zt_pool_df.loc[now_zt_pool_df['connected_boards_numbers'] > 1]
254
- result_connected_boards = result_connected_boards.sort_values(by=['connected_boards_numbers'], ascending=False)
255
- result_first = result_first.sort_values(by=['first_closure_time'], ascending=True)
256
-
257
- now_zt_pool_df = pd.concat([result_connected_boards,
258
- result_first])
259
- now_zt_pool_df = now_zt_pool_df.fillna('未知数据')
260
- now_zt_pool_df.drop_duplicates('symbol', keep='last', inplace=True)
261
311
  return now_zt_pool_df
262
312
 
263
313
 
264
- 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):
265
315
  try:
266
316
  zt_reason_df = get_ths_stock_zt_reason_with_cache(str_day)
267
317
  except BaseException as e:
@@ -269,9 +319,17 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
269
319
  logger.error("获取涨停原因异常:{}", e)
270
320
 
271
321
  last_trade_zt_copy = last_trade_zt.copy()
322
+
272
323
  if "zt_reason" not in last_trade_zt.columns:
273
324
  last_trade_zt_copy['zt_reason'] = '暂无'
274
- last_trade_zt_copy = last_trade_zt_copy[['symbol', 'zt_reason']]
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']]
275
333
 
276
334
  if data_frame_util.is_empty(zt_reason_df):
277
335
  now_zt_pool_df['zt_reason'] = '暂无'
@@ -289,6 +347,21 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
289
347
  zt_reason_df_copy = zt_reason_df_copy.set_index(['symbol'], drop=True)
290
348
  now_zt_pool_df = now_zt_pool_df.set_index(['symbol'], drop=False)
291
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
+
292
365
  result_zt_df = pd.merge(now_zt_pool_df, zt_reason_df_copy, how='outer',
293
366
  left_index=True, right_index=True)
294
367
 
@@ -299,8 +372,12 @@ def merge_zt_reason(now_zt_pool_df, str_day, last_trade_zt):
299
372
  last_trade_zt_copy = last_trade_zt_copy.set_index(['symbol'], drop=True)
300
373
  del zt_reason_na['zt_reason']
301
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
+
302
378
  zt_reason_na = pd.merge(zt_reason_na, last_trade_zt_copy, how='outer',
303
379
  left_index=True, right_index=True)
380
+
304
381
  zt_reason_na['zt_reason'] = zt_reason_na['zt_reason'].fillna('0')
305
382
  # 删除昨日涨停 今日未涨停的
306
383
  zt_reason_na.dropna(subset=['symbol'], inplace=True)
@@ -363,12 +440,11 @@ def zt_reason_group(zt_pool_df):
363
440
 
364
441
 
365
442
  if __name__ == '__main__':
366
- str_day_test = '2024-10-09'
367
-
443
+ str_day_test = '2025-10-28'
444
+ # 同花顺涨停
445
+ ths_zt_pool_df = get_now_zt_pool_with_reason(str_day_test)
368
446
  # 东财涨停池
369
447
  em_now_zt_pool_test = stock_zt_pool_api.stock_em_zt_pool_df(date_handle_util.no_slash_date(str_day_test))
370
- # 同花顺涨停
371
- ths_zt_pool_df = get_zt_reason(str_day_test)
372
448
 
373
449
  miss_zt_df = em_now_zt_pool_test.loc[~(em_now_zt_pool_test['symbol'].isin(ths_zt_pool_df['symbol']))]
374
450
  pass
@@ -76,8 +76,8 @@ def get_xue_qiu_k_line(symbol, period, cookie, end_time, hq):
76
76
 
77
77
  if __name__ == '__main__':
78
78
  number = 1
79
- cookies ='cookiesu=431747207996803; device_id=e7bd664c2ad4091241066c3a2ddbd736; xq_is_login=1; u=9627701445; s=ck12tdw0na; bid=7a2d53b7ab3873ab7ec53349413f0a21_mb9aqxtx; xq_a_token=287767c9ca1fce01ce3022eceec5e0ce14f77840; xqat=287767c9ca1fce01ce3022eceec5e0ce14f77840; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOjk2Mjc3MDE0NDUsImlzcyI6InVjIiwiZXhwIjoxNzU0NzkxNTExLCJjdG0iOjE3NTIxOTk1MTE2OTYsImNpZCI6ImQ5ZDBuNEFadXAifQ.lAu_FRmvtIgHoK08PJo-a2RPBXiEd7mYp_Iw6S18CIciREuHnGsGkSRz64ZziGD4HRH3_tu8I24DZ1zFHTujFD2t6MBVVFGdN7JV6mhw0JJos2sgIAr6ykm3KJ9rNqiBeSQ1OGBm-5NC5kV3CJNZJj7YICJLJIjKx7940T1TFa3q5gxdDsg2UaRuWprW7cwLp3wtF7NUZ6Kv-OE9C-VaeNlosIFrs5fv1Egp5C5v4INGEK2WwKrhI7GBqfUvWSXXAw4Y-i1UiDVA2L1P_jJgLxvD-ObwgaB40H9hEXd9GpioObTeL1fVylZUpCBO3U03kMBoWj3IBIalEv4jwMIY7Q; xq_r_token=46ef264c7236f56849c570ed35df3f676411df2e; Hm_lvt_1db88642e346389874251b5a1eded6e3=1752069757,1752199513,1752240695,1752299269; HMACCOUNT=16733F9B51C8BBB0; is_overseas=0; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1752299406; ssxmod_itna=QqjOAKYIwGkYDQG0bGCYG2DmxewDAo40QDXDUqAQtGgnDFqAPDODCOGKD5=RmIqOOaflxRhxaGi+DtzDBkxoDSxD=7DK4GTmGZxHRet3UY2TO=fmGmQY1sUi9TCoGnlThvi0ce7pxMOLH4dlrCRiBCvrRDmD0aDmKDU=GQfpeDxhPD5xDTDWeDGDD37xGaDmeDeOfpD0RvpISfsIo3D7eDXxGC7GRjDiPD7ZgC5D2v/SAAiDDziBQeo7PtRDi3s+fwg+4KDiyDA3BvD7y3DlcxpkQD0OtSiB3fsdYc=pg6y40OD0FXI4oKniW0baF+8fhiK+eorKQgDNODoD5qx4PBqmBqIx8=GhsAx3R4RGDoYeYG53lmoxDir+/C2T/x0i4MpN/ZoVxib0eOB5KKAIj2ICDbADYnDvcGgAKzBq/QmrSG3QWhD+=/wTKexD; ssxmod_itna2=QqjOAKYIwGkYDQG0bGCYG2DmxewDAo40QDXDUqAQtGgnDFqAPDODCOGKD5=RmIqOOaflxRhxaGi+DtbDG+vjq3Vlx03rNW=rWDlp=bcqab0PF44a5YTk4YCHqE8wxCsmUS5So/mA3QCBr9DZxq8sCGHaPHeCgGFO=iqChTC=mIzkE78s0cFD8IaqA5e2xSIC2vsD381/69xUOpEjbAQhRoQFFBwU=uvA=DUL=wFaYOsd+TwaGH08owPCaS8BYgQTkYxpoq80QiCxHKrs3qeDIDthNu0fpFXeQQyUHF4PByzukFk/P8XtqUQ3wZDyMFq//IBFTgRy/79xinsnmStweMPiUuGeAa7K4ZIxxFX8iCRR58DOmaV8WFIPO9uDUH3dH6DFPSmQzE5vyxnplRBvj4xYqGDYf4qEf4tb8vR4B8OyFq4PpLI5pI34L58FpktuYEfp4PO3as3EnlurQAgBbMQqeje4VDuCkdubsfGRYFpYuQ4a8ndaBH/j5QDLKL7hhmVQW/jPKcLlYB9iqmyLFUeZjb4Sw83qGGeeHBdM7I0Qe4YRzFDp2gCkj+u=MMmi88UkILCKh2xjRmoGmh1esOZfEOGwXue2U1Xr09Yz5kHTEHyFpwPdYyI7M5N0xbY2ynROXRbn+91uGlzPW7B5bv+w2CkqDWqGI9f1MTuMr8PYxob4VohQBhNDe4xse4=i/csV5VoDD'
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
80
  while True:
81
- test_df = get_xue_qiu_k_line('SZ000001', '1m', cookies, '1752385814699', '')
81
+ test_df = get_xue_qiu_k_line('SZ300188', '1m', cookies, '1760065317680', '')
82
82
  print(number)
83
83
  number = number + 1
@@ -71,23 +71,36 @@ def classify_symbol_one(symbol):
71
71
  # 添加前缀
72
72
  def add_pre_prefix_one(symbol):
73
73
  symbol_simple = symbol[0:6]
74
+ if bool(1 - is_valid_symbol(symbol_simple)):
75
+ return symbol
76
+
74
77
  if symbol_simple.startswith('6'):
75
- return 'SH' + symbol
78
+ return 'SH' + symbol_simple
76
79
  elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
77
- return 'SZ' + symbol
80
+ return 'SZ' + symbol_simple
78
81
  else:
79
- return 'BJ' + symbol
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()
80
91
 
81
92
 
82
93
  # 添加后缀
83
94
  def add_after_prefix_one(symbol):
84
95
  symbol_simple = symbol[0:6]
96
+ if bool(1 - is_valid_symbol(symbol_simple)):
97
+ return symbol
85
98
  if symbol_simple.startswith('6'):
86
- return symbol + '.SH'
99
+ return symbol_simple + '.SH'
87
100
  elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
88
- return symbol + '.SZ'
101
+ return symbol_simple + '.SZ'
89
102
  else:
90
- return symbol + '.BJ'
103
+ return symbol_simple + '.BJ'
91
104
 
92
105
 
93
106
  def symbol_amount_simple(real_time_quotes_now_df):
@@ -181,6 +194,8 @@ def group_by_industry_sum(real_time_quotes_now, field1, field2):
181
194
 
182
195
 
183
196
  def symbol_add_prefix(symbol):
197
+ if bool(1 - symbol.isdigit()):
198
+ return symbol
184
199
  symbol_simple = symbol[0:6]
185
200
  if symbol_simple.startswith('6'):
186
201
  return '1.' + symbol_simple
@@ -188,3 +203,8 @@ def symbol_add_prefix(symbol):
188
203
  return '0.' + symbol_simple
189
204
  else:
190
205
  return '0.' + symbol_simple
206
+
207
+
208
+ # 排除改变代码的北交所
209
+ def exclude_change_bjs_code(df):
210
+ return df[~df['symbol'].str.startswith(('8', '4'))]
@@ -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
- real_time_quotes_now.loc[:, 'real_disk_diff_amount_exchange'] = round(
64
- (real_time_quotes_now['disk_diff_amount_exchange'] / real_time_quotes_now['mv_circulation_ratio']), 2)
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
- real_time_quotes_now.loc[:, 'real_main_inflow_multiple'] = round(
67
- (real_time_quotes_now['main_inflow_multiple'] / real_time_quotes_now['mv_circulation_ratio']), 2)
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
- real_time_quotes_now.loc[:, 'real_super_main_inflow_multiple'] = round(
70
- (real_time_quotes_now['super_main_inflow_multiple'] / real_time_quotes_now['mv_circulation_ratio']), 2)
71
- real_time_quotes_now.loc[:, 'real_exchange'] = round(
72
- (real_time_quotes_now['exchange'] / real_time_quotes_now['mv_circulation_ratio']), 2)
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)