mns-common 1.3.9.9__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.

Files changed (65) hide show
  1. mns_common/__init__.py +1 -0
  2. mns_common/api/akshare/__init__.py +0 -1
  3. mns_common/api/akshare/k_line_api.py +19 -2
  4. mns_common/api/akshare/stock_bid_ask_api.py +21 -14
  5. mns_common/api/akshare/stock_zb_pool.py +2 -0
  6. mns_common/api/akshare/stock_zt_pool_api.py +1 -1
  7. mns_common/api/em/gd/east_money_stock_gdfx_free_top_10_api.py +62 -7
  8. mns_common/api/em/real_time/__init__.py +1 -1
  9. mns_common/api/em/real_time/east_money_debt_api.py +168 -71
  10. mns_common/api/em/real_time/east_money_etf_api.py +165 -27
  11. mns_common/api/em/real_time/east_money_stock_a_api.py +37 -38
  12. mns_common/api/em/real_time/east_money_stock_a_v2_api.py +97 -53
  13. mns_common/api/em/real_time/east_money_stock_common_api.py +174 -0
  14. mns_common/api/em/real_time/east_money_stock_hk_api.py +252 -271
  15. mns_common/api/em/real_time/east_money_stock_hk_gtt_api.py +291 -0
  16. mns_common/api/em/real_time/east_money_stock_multi_thread_api_v3.py +154 -0
  17. mns_common/api/em/real_time/east_money_stock_us_api.py +210 -82
  18. mns_common/api/em/real_time/real_time_quotes_repeat_api.py +195 -0
  19. mns_common/api/foreign_exchange/foreign_exchange_api.py +38 -0
  20. mns_common/api/k_line/stock_k_line_data_api.py +11 -1
  21. mns_common/api/kpl/common/__init__.py +3 -2
  22. mns_common/api/kpl/common/kpl_common_api.py +35 -0
  23. mns_common/api/kpl/symbol/symbol_his_quotes_api.py +1 -1
  24. mns_common/api/kpl/theme/kpl_theme_api.py +69 -0
  25. mns_common/api/kpl/yidong/__init__.py +7 -0
  26. mns_common/api/kpl/yidong/stock_bid_yi_dong_api.py +52 -0
  27. mns_common/api/proxies/liu_guan_proxy_api.py +55 -5
  28. mns_common/api/ths/company/company_product_area_industry_index_query.py +46 -0
  29. mns_common/api/ths/company/ths_company_info_api.py +2 -1
  30. mns_common/api/ths/company/ths_company_info_web.py +159 -0
  31. mns_common/api/ths/concept/app/ths_concept_index_app.py +3 -1
  32. mns_common/api/ths/wen_cai/ths_wen_cai_api.py +1 -1
  33. mns_common/api/ths/zt/ths_stock_zt_pool_api.py +20 -1
  34. mns_common/api/ths/zt/ths_stock_zt_pool_v2_api.py +105 -29
  35. mns_common/api/ths/zt/ths_stock_zt_reason_web_api.py +100 -0
  36. mns_common/api/us/ths_us_company_info_api.py +131 -0
  37. mns_common/api/xueqiu/xue_qiu_k_line_api.py +16 -5
  38. mns_common/component/common_service_fun_api.py +28 -8
  39. mns_common/component/company/company_common_service_new_api.py +2 -0
  40. mns_common/component/cookie/cookie_enum.py +16 -0
  41. mns_common/component/cookie/cookie_info_service.py +18 -8
  42. mns_common/component/data/data_init_api.py +13 -8
  43. mns_common/component/deal/deal_service_api.py +70 -8
  44. mns_common/component/deal/deal_service_v2_api.py +167 -0
  45. mns_common/component/em/em_stock_info_api.py +12 -3
  46. mns_common/component/main_line/__init__.py +7 -0
  47. mns_common/component/main_line/main_line_zt_reason_service.py +257 -0
  48. mns_common/component/proxies/proxy_common_api.py +169 -109
  49. mns_common/component/tfp/stock_tfp_api.py +82 -12
  50. mns_common/component/us/__init__.py +7 -0
  51. mns_common/component/us/us_stock_etf_info_api.py +130 -0
  52. mns_common/constant/db_name_constant.py +75 -26
  53. mns_common/constant/extra_income_db_name.py +94 -17
  54. mns_common/constant/strategy_classify.py +72 -0
  55. mns_common/db/MongodbUtil.py +3 -0
  56. mns_common/db/MongodbUtilLocal.py +3 -0
  57. {mns_common-1.3.9.9.dist-info → mns_common-1.6.1.4.dist-info}/METADATA +1 -1
  58. {mns_common-1.3.9.9.dist-info → mns_common-1.6.1.4.dist-info}/RECORD +62 -47
  59. mns_common/api/ths/concept/web/ths_company_info_web.py +0 -163
  60. mns_common/component/qmt/qmt_buy_service.py +0 -172
  61. mns_common/component/task/real_time_data_sync_check.py +0 -97
  62. /mns_common/{component/qmt → api/foreign_exchange}/__init__.py +0 -0
  63. /mns_common/{component/task → api/kpl/theme}/__init__.py +0 -0
  64. {mns_common-1.3.9.9.dist-info → mns_common-1.6.1.4.dist-info}/WHEEL +0 -0
  65. {mns_common-1.3.9.9.dist-info → mns_common-1.6.1.4.dist-info}/top_level.txt +0 -0
@@ -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
@@ -0,0 +1,100 @@
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
+ from bs4 import BeautifulSoup
11
+ from loguru import logger
12
+ import mns_common.component.cookie.cookie_info_service as cookie_info_service
13
+
14
+
15
+ # 获取公司热点
16
+ def get_ths_web_zt_reason_info(symbol, ths_cookie):
17
+ try:
18
+
19
+ url = "https://basic.10jqka.com.cn/new/" + symbol + "/"
20
+
21
+ headers = {
22
+ "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",
23
+ "Accept-Language": "zh-CN,zh;q=0.9",
24
+ "Cache-Control": "max-age=0",
25
+ "Connection": "keep-alive",
26
+ "Sec-Fetch-Dest": "document",
27
+ "Sec-Fetch-Mode": "navigate",
28
+ "Sec-Fetch-Site": "cross-site",
29
+ "Sec-Fetch-User": "?1",
30
+ "Upgrade-Insecure-Requests": "1",
31
+ "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",
32
+ "sec-ch-ua": "\"Google Chrome\";v=\"129\", \"Not=A?Brand\";v=\"8\", \"Chromium\";v=\"129\"",
33
+ "sec-ch-ua-mobile": "?0",
34
+ "sec-ch-ua-platform": "\"Windows\"",
35
+ "cookie": ths_cookie
36
+ }
37
+ cookies = {
38
+ "searchGuide": "sg",
39
+ "skin_color": "white",
40
+ "Hm_lvt_722143063e4892925903024537075d0d": "1725031809,1725842892,1726621825,1727227162",
41
+ "Hm_lvt_929f8b362150b1f77b477230541dbbc2": "1725031809,1725842892,1726621825,1727227162",
42
+ "spversion": "20130314",
43
+ "user": "MDq%2BsNDQcE06Ok5vbmU6NTAwOjYxMzk4NTQ0ODo1LDEsMjA7NiwxLDIwOzcsMTExMTExMTExMTEwLDIwOzgsMTExMTAxMTEwMDAwMTExMTEwMDEwMDEwMDEwMDAwMDAsMjA7MzMsMDAwMTAwMDAwMDAwLDIwOzM2LDEwMDExMTExMDAwMDExMDAxMDExMTExMSwyMDs0NiwwMDAwMTExMTEwMDAwMDExMTExMTExMTEsMjA7NTEsMTEwMDAwMDAwMDAwMDAwMCwyMDs1OCwwMDAwMDAwMDAwMDAwMDAwMSwyMDs3OCwxLDIwOzg3LDAwMDAwMDAwMDAwMDAwMDAwMDAxMDAwMCwyMDsxMTksMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAsMjA7MTI1LDExLDIwOzQ0LDExLDQwOzEsMTAxLDQwOzIsMSw0MDszLDEsNDA7MTAyLDEsNDA6Mjc6Ojo2MDM5ODU0NDg6MTcyODQ4NzEyNjo6OjE2MzQ1NjY5ODA6NjA0ODAwOjA6MTRhZjIxYmRiNTgzODUxOTgxZWVjZGQ4NjQxZjA2NDg5OmRlZmF1bHRfNDox",
44
+ "userid": "603985448",
45
+ "u_name": "%BE%B0%D0%D0pM",
46
+ "escapename": "%25u666f%25u884cpM",
47
+ "ticket": "955f0ee44d86aede75787f64ae45bae9",
48
+ "user_status": "0",
49
+ "utk": "2df15e757efe7d4a489cf764fa371ff9",
50
+ "Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1": "1728463065,1728526291,1728541890,1728550124",
51
+ "historystock": "301551%7C*%7C002205%7C*%7C000627%7C*%7C300746%7C*%7C300139",
52
+ "reviewJump": "nojump",
53
+ "usersurvey": "1",
54
+ "v": "A8mumxxpynGwb7YF90Bxvvav2P4mFrxUJwzh32s-RzXtX-dgs2bNGLda8aj4"
55
+ }
56
+ response = requests.get(url, headers=headers, cookies=cookies)
57
+ soup = BeautifulSoup(response.content, "html.parser")
58
+ for a in soup.find_all("a", class_="check_details f12"):
59
+ if "涨停分析" in a.get_text():
60
+ # 找到其后的兄弟节点中 class 为 check_else 的 div,包含详细内容
61
+ parent = a.find_parent("span", class_="performance_trailer")
62
+ if parent:
63
+ detail_div = parent.find("div", class_="check_else")
64
+ if detail_div:
65
+ # 提取div内的完整原始HTML字符串
66
+ raw_html = detail_div.decode_contents()
67
+ # 按<br/>切割,精准拆分 涨停原因 + 涨停分析
68
+ if '<br/>' in raw_html:
69
+ zt_reason, zt_analysis = raw_html.split('<br/>', 1) # 只切割1次,核心!
70
+ # 清洗文本:去除首尾空格/换行,纯文本提取
71
+ zt_reason = zt_reason.strip()
72
+ zt_analysis = zt_analysis.strip()
73
+ else:
74
+ # 容错:没有br标签的情况,全部给分析
75
+ zt_reason = ""
76
+ zt_analysis = detail_div.get_text(strip=True)
77
+ else:
78
+ result_dict = {
79
+ 'zt_reason': '',
80
+ 'zt_analysis': '',
81
+ }
82
+ logger.error("无涨停原因和分析:{}", symbol)
83
+ return result_dict
84
+
85
+ result_dict = {
86
+ 'zt_reason': zt_reason,
87
+ 'zt_analysis': zt_analysis,
88
+ }
89
+ return result_dict
90
+ except BaseException as e:
91
+ logger.error("获取公司涨停信息异常:{},{}", symbol, e)
92
+ result_dict = {
93
+ 'zt_reason': '',
94
+ 'zt_analysis': '',
95
+ }
96
+ return result_dict
97
+
98
+
99
+ if __name__ == '__main__':
100
+ get_ths_web_zt_reason_info('920021', cookie_info_service.get_ths_cookie())
@@ -5,5 +5,136 @@ file_path = os.path.abspath(__file__)
5
5
  end = file_path.index('mns') + 16
6
6
  project_path = file_path[0:end]
7
7
  sys.path.append(project_path)
8
+ import requests
9
+ from bs4 import BeautifulSoup
10
+
8
11
 
9
12
  # 同花顺 美股地址:https://basic.10jqka.com.cn/168/PINS/company.html
13
+
14
+ # 获取美股公司信息 https://stockpage.10jqka.com.cn/LMT/company/
15
+ def get_us_ths_company_info(stock_code):
16
+ """
17
+ 根据股票代码,获取同花顺公司基本信息
18
+ :param stock_code: 股票代码,例如 LMT / AAPL 字符串格式,核心传参参数
19
+ :return: dict 结构化的公司基本信息,失败返回空字典
20
+ """
21
+ # 1. 基础配置:参数化拼接URL + 请求头(必须加,否则会被反爬拦截)
22
+ base_url = f"https://stockpage.10jqka.com.cn/{stock_code}/company/"
23
+ headers = {
24
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
25
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
26
+ }
27
+ company_data = {} # 存储最终的公司信息
28
+
29
+ try:
30
+ # 2. 发起GET请求获取网页源码
31
+ response = requests.get(url=base_url, headers=headers, timeout=10)
32
+ response.raise_for_status() # 抛出请求异常(404/500等)
33
+ response.encoding = "utf-8" # 指定编码,防止中文乱码
34
+
35
+ # 3. 解析HTML网页结构
36
+ soup = BeautifulSoup(response.text, "html.parser")
37
+ # 精准定位目标表格(唯一核心表格)
38
+ table = soup.find("table", class_="companyinfo-tab")
39
+ if not table:
40
+ print(f"错误:未找到 {stock_code} 的公司信息表格")
41
+ return company_data
42
+
43
+ # 4. 提取所有表格内的文本内容+清洗数据
44
+ all_tds = table.find_all("td")
45
+ for td in all_tds:
46
+ td_text = td.get_text(strip=True) # 自动去除首尾空格/换行
47
+ if not td_text:
48
+ continue
49
+ # 按【字段名:字段值】的格式拆分数据,封装到字典
50
+ if ":" in td_text:
51
+ key, value = td_text.split(":", 1) # 只分割第一个冒号
52
+ company_data[key] = value
53
+
54
+ # 单独提取:公司LOGO图片地址(补充信息,可选)
55
+ logo_img = table.find("img")
56
+ if logo_img:
57
+ company_data["公司LOGO"] = logo_img.get("src", "")
58
+ company_data["LOGO备注"] = logo_img.get("alt", "")
59
+
60
+ # 特殊清洗:公司简介 去除多余空格/换行符,格式化展示
61
+ if "公司简介" in company_data:
62
+ company_data["公司简介"] = company_data["公司简介"].replace("\r", "").replace("\n", "").strip()
63
+
64
+ except requests.exceptions.RequestException as e:
65
+ print(f"请求失败:{e}")
66
+ except Exception as e:
67
+ print(f"解析数据异常:{e}")
68
+
69
+ return company_data
70
+
71
+
72
+ def get_us_ths_company_info_v2(stock_code,market_code):
73
+ """
74
+ 根据股票代码,获取同花顺公司基本信息
75
+ :param stock_code: 股票代码,例如 LMT / AAPL 字符串格式,核心传参参数
76
+ :return: dict 结构化的公司基本信息,失败返回空字典
77
+ """
78
+ # 1. 基础配置:参数化拼接URL + 请求头(必须加,否则会被反爬拦截)
79
+ base_url = f"https://stockpage.10jqka.com.cn/{stock_code}/company/"
80
+ base_url = f"https://basic.10jqka.com.cn/{market_code}/{stock_code}/company.html"
81
+ headers = {
82
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
83
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
84
+ }
85
+ company_data = {} # 存储最终的公司信息
86
+
87
+ try:
88
+ # 2. 发起GET请求获取网页源码
89
+ response = requests.get(url=base_url, headers=headers, timeout=10)
90
+ response.raise_for_status() # 抛出请求异常(404/500等)
91
+ response.encoding = "utf-8" # 指定编码,防止中文乱码
92
+
93
+ # 3. 解析HTML网页结构
94
+ soup = BeautifulSoup(response.text, "html.parser")
95
+ # 精准定位目标表格(唯一核心表格)
96
+ table = soup.find("table", class_="companyinfo-tab")
97
+ if not table:
98
+ print(f"错误:未找到 {stock_code} 的公司信息表格")
99
+ return company_data
100
+
101
+ # 4. 提取所有表格内的文本内容+清洗数据
102
+ all_tds = table.find_all("td")
103
+ for td in all_tds:
104
+ td_text = td.get_text(strip=True) # 自动去除首尾空格/换行
105
+ if not td_text:
106
+ continue
107
+ # 按【字段名:字段值】的格式拆分数据,封装到字典
108
+ if ":" in td_text:
109
+ key, value = td_text.split(":", 1) # 只分割第一个冒号
110
+ company_data[key] = value
111
+
112
+ # 单独提取:公司LOGO图片地址(补充信息,可选)
113
+ logo_img = table.find("img")
114
+ if logo_img:
115
+ company_data["公司LOGO"] = logo_img.get("src", "")
116
+ company_data["LOGO备注"] = logo_img.get("alt", "")
117
+
118
+ # 特殊清洗:公司简介 去除多余空格/换行符,格式化展示
119
+ if "公司简介" in company_data:
120
+ company_data["公司简介"] = company_data["公司简介"].replace("\r", "").replace("\n", "").strip()
121
+
122
+ except requests.exceptions.RequestException as e:
123
+ print(f"请求失败:{e}")
124
+ except Exception as e:
125
+ print(f"解析数据异常:{e}")
126
+
127
+ return company_data
128
+
129
+
130
+ # ------------------- 核心调用:参数传参 测试 -------------------
131
+ if __name__ == "__main__":
132
+ # 股票代码 作为参数传入函数,满足你的核心要求 ✅
133
+ stock_code_param = "GEV" # 这里可替换任意股票代码,例如:AAPL、MSFT
134
+ result1=get_us_ths_company_info_v2('META','168')
135
+ result = get_us_ths_company_info(stock_code_param)
136
+
137
+ # 格式化打印结果
138
+ print(f"===== {stock_code_param} 公司基本信息 =====")
139
+ for k, v in result.items():
140
+ print(f"{k}: {v}")
@@ -54,9 +54,20 @@ def get_xue_qiu_k_line(symbol, period, cookie, end_time, hq):
54
54
  data=response_data['data']['item'],
55
55
  columns=response_data['data']['column']
56
56
  )
57
- # 处理DataFrame列(秒级时间戳)
58
- df['str_day'] = pd.to_datetime(df['timestamp'], unit='ms').dt.normalize()
59
- df["str_day"] = df["str_day"].dt.strftime("%Y-%m-%d")
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
+
60
71
  return df
61
72
  else:
62
73
  # 直接抛出带有明确信息的异常
@@ -65,8 +76,8 @@ def get_xue_qiu_k_line(symbol, period, cookie, end_time, hq):
65
76
 
66
77
  if __name__ == '__main__':
67
78
  number = 1
68
- cookies = "cookiesu=581743780372237; device_id=e315f5f93cf4d1af01436bc234312ebb; s=ci1338vttl; xq_a_token=75116a2a5439edb58d3d99533cfbc4d72e0ee819; xqat=75116a2a5439edb58d3d99533cfbc4d72e0ee819; xq_r_token=521f1781edc2a09cffdf7d59b5b3fe37c1c1f577; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOi0xLCJpc3MiOiJ1YyIsImV4cCI6MTc0OTk0OTc1MywiY3RtIjoxNzQ4MTU5ODU3NzYwLCJjaWQiOiJkOWQwbjRBWnVwIn0.HP0CrptQ8jJjU9eJ0LhdAA_PlErW_Sp4OA5SjCyIQhKN5nTlrlovKty3IKutb5Nn_8EgeLZqrTeLKTsNIIE1uRGEppgo-Suk6_IOV1X900M47R2aBV2TX-J3rSmfyP7mAXav8CVT1pwiRU8Xr_ag3XT8WxVNQY1aOiV5JEyKeJucwvRyoa0iB4sM9j2kxcRXCF3nK9JnofsvAg-I7ySf3hCly3csj-zWQQSWeUjpmMlMS2ddLjvAHQUNbBFMTZ2BVji0ae3mURUB2jz4A6O8pZGZHuh3qDdQfeLq0i80H2AnOEqsJ246THsS7RS20HidyWWbYm3gBlRptDr1lWgsGg; u=581743780372237; Hm_lvt_1db88642e346389874251b5a1eded6e3=1746435822,1747730708,1748159904; HMACCOUNT=2CB33FC8EC07B09A; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1748159918; ssxmod_itna=QqjxRQKiTx2DgD4qbD0nYDCDpEDymxBP01kD+xQ5DODLxn+xGdqufh=z3O=DcllGdHwiYK9DDsZ4xiNDAg40iDC3md1aUr0TPz=GmnG5Gyz7AbR3Otq2Q8c51cYZO7eBpjlSgy4xAEYDQKDoxGkDiyKD0FY+Diibx0rD0eDPxDYDGbwDDyIoUxDj7gwTzOsk77eo8oDb6xhfjxDR=dDSQ8vs8Os=Y3DarY3kUxGDmKDIalKf7oDF=d3Pq0ke4i35xEnbq0OSFYG2movzUrceE0rde4FKYR1=QiqOlG4aWG4ecpxnTillebZnbVQGFzDsQRS4xDGSKHBKqxs3DqhYkCuke4CQ+YKYozoo52q5xd1E4kEmROwyY5M04aAQKD5h05NGDs0Dl0DoCs4D; ssxmod_itna2=QqjxRQKiTx2DgD4qbD0nYDCDpEDymxBP01kD+xQ5DODLxn+xGdqufh=z3O=DcllGdHwiYK4Dfi3Qe+0wxDFOihv=8B0DD/CcBOpAgn9LMTKhhSafFNwTqw64jzZ/oQMQq4dVL95j2MbxV+kj1R3inzDd47u0y0+dUbwdeLB2QA+QBj4unSq=lSq0A0LhD1xfxGMR6KPLu+bTxvmj30MbWLjxqYLcc9=ajBhTle/THgetZmeTqY7GQCa7qFTx4+IfcbdxfeFbUSI7m5ndqfBxLhOyjZidzB887ak=NR/NzFlhDkTQPSksf+WR0WNGuFSqxSFFCh5BR5iaq0bVFpxSTc3PnQ0U9RIKDN0bA02TQDezeHGhVG7Vz4QnrLi03kGg+vRU0w4p3Ti0n7Kn5CWoGUPz99Fip6GEYZi+eIdFnD75WCq0iu1AbK7AFQDNQadaG5aIDkA4Xy+7gUS5SWGEGiWGAxHg+RipnTa3B948MFWQkPG9ay8MYs4B8vYw+4ycXQQhpmHecNj9YHuooqedamM7lW4QXaFnLdSTgBlfWG2SlAwvkmjTqwKuI4LR3cys+lX/uUiw4h8mfnKhZEcaXkTA33sFo+aT2djFUm2Cr2b/ECeLiqeOCmKiYbPZUhHC9vFm48Dnz1y5azM2wBzcKc89hcKXSpR8f4MnL5RBA/KxANHjN6g4NrXv0qCK7EX0GbbDo0WOH+EC2dj4z7tYGDh5Rf3QDrYVr3YwMGWB+QCWG+Q7ofPuoOIXGBrfIeE4nhd3o4h3YKo+pD5Crd0CRYC7Kp20qMSrziDD"
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'
69
80
  while True:
70
- test_df = get_xue_qiu_k_line('SZ000004', 'day', cookies, '1748246492232', 'after')
81
+ test_df = get_xue_qiu_k_line('SZ300188', '1m', cookies, '1760065317680', '')
71
82
  print(number)
72
83
  number = number + 1
@@ -71,22 +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()
91
+
80
92
 
81
93
  # 添加后缀
82
94
  def add_after_prefix_one(symbol):
83
95
  symbol_simple = symbol[0:6]
96
+ if bool(1 - is_valid_symbol(symbol_simple)):
97
+ return symbol
84
98
  if symbol_simple.startswith('6'):
85
- return symbol + '.SH'
99
+ return symbol_simple + '.SH'
86
100
  elif symbol_simple.startswith('0') or symbol_simple.startswith('3'):
87
- return symbol + '.SZ'
101
+ return symbol_simple + '.SZ'
88
102
  else:
89
- return symbol + '.BJ'
103
+ return symbol_simple + '.BJ'
90
104
 
91
105
 
92
106
  def symbol_amount_simple(real_time_quotes_now_df):
@@ -117,8 +131,7 @@ def exclude_st_symbol(real_time_quotes_now_df):
117
131
  # 排除带星的ST 容易退市
118
132
  def exclude_star_st_symbol(df):
119
133
  exclude_st_symbol_list = list(
120
- df.loc[(df['name'].str.contains('\*'))
121
- | (df['name'].str.contains('退'))]['symbol'])
134
+ df.loc[(df['name'].str.contains(r'\*')) | (df['name'].str.contains('退'))]['symbol'])
122
135
  return df.loc[
123
136
  ~(df['symbol'].isin(
124
137
  exclude_st_symbol_list))]
@@ -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'))]
@@ -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
 
@@ -0,0 +1,16 @@
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
+ KPL_COOKIE = ('kpl_cookie', '开盘啦cookie')
13
+
14
+ def __init__(self, cookie_code, cookie_name):
15
+ self.cookie_code = cookie_code
16
+ self.cookie_name = cookie_name
@@ -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', {"type": "ths_cookie", })
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
- @lru_cache(maxsize=None)
22
+ # 东财 cookie
23
23
  def get_em_cookie():
24
- stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "em_cookie", })
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
- @lru_cache(maxsize=None)
30
+ # 雪球 cookie
30
31
  def get_xue_qiu_cookie():
31
- stock_account_info = mongodb_util.find_query_data('stock_account_info', {"type": "xue_qiu", })
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
- 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)