mns-common 1.3.5.6__py3-none-any.whl → 1.3.5.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mns-common might be problematic. Click here for more details.
- mns_common/api/em/east_money_stock_quotes_sync_api.py +250 -0
- mns_common/component/task/real_time_data_sync_check.py +9 -9
- {mns_common-1.3.5.6.dist-info → mns_common-1.3.5.8.dist-info}/METADATA +1 -1
- {mns_common-1.3.5.6.dist-info → mns_common-1.3.5.8.dist-info}/RECORD +6 -5
- {mns_common-1.3.5.6.dist-info → mns_common-1.3.5.8.dist-info}/WHEEL +0 -0
- {mns_common-1.3.5.6.dist-info → mns_common-1.3.5.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
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 asyncio
|
|
9
|
+
from typing import Dict, List
|
|
10
|
+
import aiohttp
|
|
11
|
+
import pandas as pd
|
|
12
|
+
import datetime
|
|
13
|
+
import nest_asyncio
|
|
14
|
+
from loguru import logger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def fetch_single_page(
|
|
18
|
+
session: aiohttp.ClientSession, url: str, params: Dict
|
|
19
|
+
) -> Dict:
|
|
20
|
+
"""异步获取单页数据"""
|
|
21
|
+
async with session.get(url, params=params, ssl=False) as response:
|
|
22
|
+
return await response.json()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def fetch_all_pages_async(url: str, base_params: Dict) -> List[Dict]:
|
|
26
|
+
"""异步获取所有页面数据"""
|
|
27
|
+
# 首先获取总数以计算页数
|
|
28
|
+
first_page_params = base_params.copy()
|
|
29
|
+
first_page_params["pn"] = "1"
|
|
30
|
+
|
|
31
|
+
async with aiohttp.ClientSession() as session:
|
|
32
|
+
first_page_data = await fetch_single_page(session, url, first_page_params)
|
|
33
|
+
|
|
34
|
+
# 检查是否成功获取数据
|
|
35
|
+
if first_page_data.get("rc") != 0 or not first_page_data.get("data"):
|
|
36
|
+
return [first_page_data] # 返回错误信息
|
|
37
|
+
|
|
38
|
+
total = first_page_data["data"]["total"]
|
|
39
|
+
page_size = int(base_params["pz"])
|
|
40
|
+
total_pages = (total + page_size - 1) // page_size
|
|
41
|
+
|
|
42
|
+
# 限制页数,避免过大请求
|
|
43
|
+
total_pages = min(total_pages, 100)
|
|
44
|
+
|
|
45
|
+
# 创建所有页面的任务
|
|
46
|
+
tasks = []
|
|
47
|
+
for page in range(1, total_pages + 1):
|
|
48
|
+
page_params = base_params.copy()
|
|
49
|
+
page_params["pn"] = str(page)
|
|
50
|
+
tasks.append(fetch_single_page(session, url, page_params))
|
|
51
|
+
|
|
52
|
+
# 并发执行所有任务
|
|
53
|
+
results = await asyncio.gather(*tasks)
|
|
54
|
+
return results
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def process_data(page_results: List[Dict]) -> pd.DataFrame:
|
|
58
|
+
"""处理获取到的数据,转换为DataFrame"""
|
|
59
|
+
all_data = []
|
|
60
|
+
|
|
61
|
+
# 保存每个页面的结果和页码
|
|
62
|
+
page_number = 1
|
|
63
|
+
items_per_page = 100 # 假设每页100条
|
|
64
|
+
|
|
65
|
+
for result in page_results:
|
|
66
|
+
if result.get("rc") == 0 and result.get("data") and result["data"].get("diff"):
|
|
67
|
+
page_data = result["data"]["diff"]
|
|
68
|
+
|
|
69
|
+
# 添加页面信息以便后续计算序号
|
|
70
|
+
for item in page_data:
|
|
71
|
+
item["page_number"] = page_number
|
|
72
|
+
item["page_index"] = page_data.index(item)
|
|
73
|
+
|
|
74
|
+
all_data.extend(page_data)
|
|
75
|
+
page_number += 1
|
|
76
|
+
|
|
77
|
+
if not all_data:
|
|
78
|
+
return pd.DataFrame()
|
|
79
|
+
|
|
80
|
+
df = pd.DataFrame(all_data)
|
|
81
|
+
|
|
82
|
+
# 删除临时列
|
|
83
|
+
df.drop(columns=["page_number", "page_index"], inplace=True, errors="ignore")
|
|
84
|
+
|
|
85
|
+
df = df.rename(columns={
|
|
86
|
+
"f2": "now_price",
|
|
87
|
+
"f3": "chg",
|
|
88
|
+
"f5": "volume",
|
|
89
|
+
"f6": "amount",
|
|
90
|
+
"f8": "exchange",
|
|
91
|
+
"f10": "quantity_ratio",
|
|
92
|
+
"f22": "up_speed",
|
|
93
|
+
"f11": "up_speed_05",
|
|
94
|
+
"f12": "symbol",
|
|
95
|
+
"f14": "name",
|
|
96
|
+
"f15": "high",
|
|
97
|
+
"f16": "low",
|
|
98
|
+
"f17": "open",
|
|
99
|
+
"f18": "yesterday_price",
|
|
100
|
+
"f20": "total_mv",
|
|
101
|
+
"f21": "flow_mv",
|
|
102
|
+
"f26": "list_date",
|
|
103
|
+
"f33": "wei_bi",
|
|
104
|
+
"f34": "outer_disk",
|
|
105
|
+
"f35": "inner_disk",
|
|
106
|
+
"f62": "today_main_net_inflow",
|
|
107
|
+
"f66": "super_large_order_net_inflow",
|
|
108
|
+
"f69": "super_large_order_net_inflow_ratio",
|
|
109
|
+
"f72": "large_order_net_inflow",
|
|
110
|
+
# "f78": "medium_order_net_inflow",
|
|
111
|
+
# "f84": "small_order_net_inflow",
|
|
112
|
+
"f100": "industry",
|
|
113
|
+
# "f103": "concept",
|
|
114
|
+
"f184": "today_main_net_inflow_ratio",
|
|
115
|
+
"f352": "average_price",
|
|
116
|
+
"f211": "buy_1_num",
|
|
117
|
+
"f212": "sell_1_num"
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
# 选择需要的列并确保所有需要的列都存在
|
|
121
|
+
desired_columns = [
|
|
122
|
+
'symbol',
|
|
123
|
+
"now_price",
|
|
124
|
+
"chg",
|
|
125
|
+
"volume",
|
|
126
|
+
"amount",
|
|
127
|
+
"exchange",
|
|
128
|
+
"quantity_ratio",
|
|
129
|
+
"up_speed",
|
|
130
|
+
"up_speed_05",
|
|
131
|
+
"high",
|
|
132
|
+
"low",
|
|
133
|
+
"open",
|
|
134
|
+
"yesterday_price",
|
|
135
|
+
"total_mv",
|
|
136
|
+
"flow_mv",
|
|
137
|
+
"wei_bi",
|
|
138
|
+
"outer_disk",
|
|
139
|
+
"inner_disk",
|
|
140
|
+
"today_main_net_inflow",
|
|
141
|
+
"super_large_order_net_inflow",
|
|
142
|
+
"super_large_order_net_inflow_ratio",
|
|
143
|
+
"large_order_net_inflow",
|
|
144
|
+
"today_main_net_inflow_ratio",
|
|
145
|
+
"average_price",
|
|
146
|
+
"buy_1_num",
|
|
147
|
+
"sell_1_num",
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
# 过滤出存在的列
|
|
151
|
+
available_columns = [col for col in desired_columns if col in df.columns]
|
|
152
|
+
df = df[available_columns]
|
|
153
|
+
|
|
154
|
+
# 转换数值类型
|
|
155
|
+
numeric_columns = [
|
|
156
|
+
"now_price",
|
|
157
|
+
"chg",
|
|
158
|
+
"volume",
|
|
159
|
+
"amount",
|
|
160
|
+
"exchange",
|
|
161
|
+
"quantity_ratio",
|
|
162
|
+
"up_speed",
|
|
163
|
+
"up_speed_05",
|
|
164
|
+
"high",
|
|
165
|
+
"low",
|
|
166
|
+
"open",
|
|
167
|
+
"yesterday_price",
|
|
168
|
+
"total_mv",
|
|
169
|
+
"flow_mv",
|
|
170
|
+
"wei_bi",
|
|
171
|
+
"outer_disk",
|
|
172
|
+
"inner_disk",
|
|
173
|
+
"today_main_net_inflow",
|
|
174
|
+
"super_large_order_net_inflow",
|
|
175
|
+
"super_large_order_net_inflow_ratio",
|
|
176
|
+
"large_order_net_inflow",
|
|
177
|
+
"today_main_net_inflow_ratio",
|
|
178
|
+
"average_price",
|
|
179
|
+
"buy_1_num",
|
|
180
|
+
"sell_1_num",
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
for col in numeric_columns:
|
|
184
|
+
if col in df.columns:
|
|
185
|
+
df.loc[df[col] == '-', col] = 0
|
|
186
|
+
df[col] = pd.to_numeric(df[col], errors="coerce")
|
|
187
|
+
|
|
188
|
+
# 大单比例
|
|
189
|
+
df['large_order_net_inflow_ratio'] = round((df['large_order_net_inflow'] / df['amount']) * 100, 2)
|
|
190
|
+
|
|
191
|
+
# 外盘是内盘倍数
|
|
192
|
+
df['disk_ratio'] = round((df['outer_disk'] - df['inner_disk']) / df['inner_disk'], 2)
|
|
193
|
+
# 只有外盘没有内盘
|
|
194
|
+
df.loc[df["inner_disk"] == 0, ['disk_ratio']] = 1688
|
|
195
|
+
# 按涨跌幅降序排序
|
|
196
|
+
df.sort_values(by="chg", ascending=False, inplace=True)
|
|
197
|
+
|
|
198
|
+
return df
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
async def stock_zh_a_spot_em_async() -> pd.DataFrame:
|
|
202
|
+
fields = "f352,f2,f3,f5,f6,f8,f10,f11,f22,f12,f15,f16,f17,f18,f20,f21,f33,f34,f35,f62,f66,f69,f72,f184,f211,f212",
|
|
203
|
+
# 获取当前日期和时间
|
|
204
|
+
current_time = datetime.datetime.now()
|
|
205
|
+
|
|
206
|
+
# 将当前时间转换为时间戳(以毫秒为单位)
|
|
207
|
+
current_timestamp_ms = int(current_time.timestamp() * 1000)
|
|
208
|
+
"""
|
|
209
|
+
异步获取东方财富网-沪深京 A 股-实时行情
|
|
210
|
+
https://quote.eastmoney.com/center/gridlist.html#hs_a_board
|
|
211
|
+
:return: 实时行情
|
|
212
|
+
:rtype: pandas.DataFrame
|
|
213
|
+
"""
|
|
214
|
+
url = "https://82.push2.eastmoney.com/api/qt/clist/get"
|
|
215
|
+
params = {
|
|
216
|
+
"pn": "1",
|
|
217
|
+
"pz": "100",
|
|
218
|
+
"po": "1",
|
|
219
|
+
"np": "1",
|
|
220
|
+
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
|
|
221
|
+
"fltt": "2",
|
|
222
|
+
"invt": "2",
|
|
223
|
+
"fid": "f12",
|
|
224
|
+
"fs": "m:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23,m:0 t:81 s:2048",
|
|
225
|
+
"fields": fields,
|
|
226
|
+
"_": current_timestamp_ms
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
results = await fetch_all_pages_async(url, params)
|
|
230
|
+
return process_data(results)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def stock_real_quotes() -> pd.DataFrame:
|
|
234
|
+
"""
|
|
235
|
+
东方财富网-沪深京 A 股-实时行情 (同步接口)
|
|
236
|
+
https://quote.eastmoney.com/center/gridlist.html#hs_a_board
|
|
237
|
+
:return: 实时行情
|
|
238
|
+
:rtype: pandas.DataFrame
|
|
239
|
+
"""
|
|
240
|
+
try:
|
|
241
|
+
nest_asyncio.apply()
|
|
242
|
+
return asyncio.run(stock_zh_a_spot_em_async())
|
|
243
|
+
except Exception as e:
|
|
244
|
+
logger.error("同步实时行情出现异常:{}", e)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
if __name__ == "__main__":
|
|
248
|
+
while True:
|
|
249
|
+
stock_zh_a_spot_em_df = stock_real_quotes()
|
|
250
|
+
logger.info(stock_zh_a_spot_em_df)
|
|
@@ -78,15 +78,15 @@ def exist_sync_task():
|
|
|
78
78
|
def check_data_sync_task_status():
|
|
79
79
|
now_date = datetime.datetime.now()
|
|
80
80
|
str_day = now_date.strftime('%Y-%m-%d')
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
|
|
82
|
+
if bool(date_util.is_trade_time(now_date)):
|
|
83
|
+
if bool(1 - query_data_exist(str_day)) or bool(1 - exist_sync_task()):
|
|
84
|
+
real_time_sync_task_open()
|
|
85
|
+
time.sleep(2)
|
|
86
|
+
elif bool(date_util.is_no_trade_time(now_date)):
|
|
87
|
+
return
|
|
88
|
+
else:
|
|
89
|
+
time.sleep(5)
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
if __name__ == '__main__':
|
|
@@ -13,6 +13,7 @@ mns_common/api/em/east_money_etf_api.py,sha256=PtVBNArQ5sMjzBVCW-WBnAuqSp8qB4E1H
|
|
|
13
13
|
mns_common/api/em/east_money_stock_api.py,sha256=NkV8jmdYOrOpQd00KsMBNoAkPZuWGtw0N1Rryg21RZ0,9892
|
|
14
14
|
mns_common/api/em/east_money_stock_gdfx_free_top_10_api.py,sha256=jVy3fNdrkLq3ri7yUwXWt0ItB8LCHzt9CPz91Fj8sPA,9198
|
|
15
15
|
mns_common/api/em/east_money_stock_hk_api.py,sha256=C75TfZzRnNVaz_ILEPHcxhgJqV7f4rFrlWjgMWLRu7c,14788
|
|
16
|
+
mns_common/api/em/east_money_stock_quotes_sync_api.py,sha256=6KGu6qf4vD8VIwm0dVbTMy_4YzMG8qaKC45NdjQKZN0,7588
|
|
16
17
|
mns_common/api/em/east_money_stock_us_api.py,sha256=6u0fSkIxZqPVrI1JChhwTrUWRTCDDSBNvU5cehPA1uM,11417
|
|
17
18
|
mns_common/api/em/east_money_stock_v2_api.py,sha256=BxLZqIUecy71TkbMelAF8Bg3xEd3tR02r2Nj3NfF8Ts,16326
|
|
18
19
|
mns_common/api/em/em_concept_index_api.py,sha256=PP87ES8a_y0o3SKLzBsPrc7DCPI3MBCD-4SmoUUirl0,8285
|
|
@@ -112,7 +113,7 @@ mns_common/component/self_choose/__init__.py,sha256=wEg73KlZo-dU0yKGwpA1C2y6LZm4
|
|
|
112
113
|
mns_common/component/self_choose/black_list_service_api.py,sha256=BUySMNHDM3OzXe3g7WGola8_yGZ0ub_fjHj7e6-eB7s,1993
|
|
113
114
|
mns_common/component/self_choose/self_choose_service_api.py,sha256=v-ThYn5OMva-ciawOFaGi_joxDzLp5HYUHuIP7wz5Z8,1456
|
|
114
115
|
mns_common/component/task/__init__.py,sha256=wEg73KlZo-dU0yKGwpA1C2y6LZm4IBb94tNda1tqLeg,163
|
|
115
|
-
mns_common/component/task/real_time_data_sync_check.py,sha256=
|
|
116
|
+
mns_common/component/task/real_time_data_sync_check.py,sha256=Ss_7XRGCYPG5fwPLove2wtI-AF5r0x2S06DddaxyfY4,3333
|
|
116
117
|
mns_common/component/tfp/__init__.py,sha256=wEg73KlZo-dU0yKGwpA1C2y6LZm4IBb94tNda1tqLeg,163
|
|
117
118
|
mns_common/component/tfp/stock_tfp_api.py,sha256=iYCBA4DjZZ1ioDKuB8z_uUEuhL0eWPY7K9QkQl9yrik,2135
|
|
118
119
|
mns_common/component/trade_date/__init__.py,sha256=2U9DiKslxsWwLLEcZKjS8UiQPN1QgALvnK3HiJNIZE0,163
|
|
@@ -140,7 +141,7 @@ mns_common/utils/date_handle_util.py,sha256=XS-MyA8_7k35LOCFAYOHgVcVkMft_Kc4Wa9U
|
|
|
140
141
|
mns_common/utils/db_util.py,sha256=hSmfNAN4vEeEaUva6_cicZEhb2jSnib-Gvk2reke1vc,2590
|
|
141
142
|
mns_common/utils/file_util.py,sha256=egWu6PenGPRp_ixrNTHKarT4dAnOT6FETR82EHUZJnQ,1042
|
|
142
143
|
mns_common/utils/ip_util.py,sha256=UTcYfz_uytB__6nlBf7T-izuI7hi4XdB6ET0sJgEel4,969
|
|
143
|
-
mns_common-1.3.5.
|
|
144
|
-
mns_common-1.3.5.
|
|
145
|
-
mns_common-1.3.5.
|
|
146
|
-
mns_common-1.3.5.
|
|
144
|
+
mns_common-1.3.5.8.dist-info/METADATA,sha256=JahkuWPbhhn6h8jOg45CKz3kmWEsAPUKjBIvy8kQeaE,61
|
|
145
|
+
mns_common-1.3.5.8.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
146
|
+
mns_common-1.3.5.8.dist-info/top_level.txt,sha256=ZC58kAR-8Hvc6U2xhYNBNLAh3mb6sZazbdj5nZpvEkQ,11
|
|
147
|
+
mns_common-1.3.5.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|