Compare commits
2 Commits
7770468b1c
...
b84cfc6b02
| Author | SHA1 | Date | |
|---|---|---|---|
| b84cfc6b02 | |||
| f0205ec146 |
@@ -1 +0,0 @@
|
|||||||
{"cookies": [{"name": "fullscreengg", "value": "1", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "fullscreengg2", "value": "1", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "qgqp_b_id", "value": "3998be81d9d8e920bf1a47e9d7b68329", "domain": ".eastmoney.com", "path": "/", "expires": 1796311917.296861, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_nvi", "value": "pcDSsW8vzKoZZ2lzT5Z2i07df", "domain": ".eastmoney.com", "path": "/", "expires": 1793287917, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_si", "value": "92630991205653", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_pvi", "value": "92887489601905", "domain": ".eastmoney.com", "path": "/", "expires": 1796311917.368717, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_sp", "value": "2025-10-29%2023%3A31%3A57", "domain": ".eastmoney.com", "path": "/", "expires": 1796311917.369031, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_inirUrl", "value": "", "domain": ".eastmoney.com", "path": "/", "expires": 1796311917.369443, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_sn", "value": "1", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_psi", "value": "20251029233157369-113200313003-0751845929", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "st_asi", "value": "delete", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "nid", "value": "03decfaee3d761b8ded27f8ee073dc4b", "domain": ".eastmoney.com", "path": "/", "expires": 1769527917, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "nid_create_time", "value": "1761751917950", "domain": ".eastmoney.com", "path": "/", "expires": 1769527917, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "gvi", "value": "ppXpL14DB48utbjDwaDu6785e", "domain": ".eastmoney.com", "path": "/", "expires": 1769527917, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "gvi_create_time", "value": "1761751917950", "domain": ".eastmoney.com", "path": "/", "expires": 1769527917, "httpOnly": false, "secure": false, "sameSite": "Lax"}, {"name": "wsc_checkuser_ok", "value": "1", "domain": ".eastmoney.com", "path": "/", "expires": -1, "httpOnly": false, "secure": false, "sameSite": "Lax"}], "origins": [{"origin": "https://quote.eastmoney.com", "localStorage": [{"name": "st_inirUrl", "value": ""}, {"name": "st_pvi", "value": "92887489601905"}, {"name": "st_sp", "value": "2025-10-29 23:31:57"}]}]}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
import time
|
|
||||||
from playwright.sync_api import sync_playwright
|
|
||||||
from loguru import logger
|
|
||||||
import datetime
|
|
||||||
import re
|
|
||||||
import json
|
|
||||||
import pandas as pd
|
|
||||||
|
|
||||||
|
|
||||||
def index_data_scraper(index_code: str, data_file_path: str):
|
|
||||||
|
|
||||||
with sync_playwright() as p:
|
|
||||||
|
|
||||||
def on_response(response):
|
|
||||||
if "push2.eastmoney.com/api/qt/clist/get" in response.url:
|
|
||||||
try:
|
|
||||||
if response.request.failure is None and response.status == 200:
|
|
||||||
data = response.text()
|
|
||||||
# logger.info(f"最新数据: \n{data}")
|
|
||||||
|
|
||||||
# 保存响应数据
|
|
||||||
with open(data_file_path, "a", encoding="utf-8") as f:
|
|
||||||
f.write(data)
|
|
||||||
f.write("\n")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"处理响应数据失败: {e}")
|
|
||||||
|
|
||||||
browser_state_file_path = "./em_browser_state.json"
|
|
||||||
browser = p.chromium.launch(args=["--start-maximized"], headless=True)
|
|
||||||
context = browser.new_context(
|
|
||||||
storage_state=browser_state_file_path, no_viewport=True
|
|
||||||
)
|
|
||||||
page = context.new_page()
|
|
||||||
page.on("response", on_response)
|
|
||||||
url = f"https://quote.eastmoney.com/center/gridlist.html#{index_code}"
|
|
||||||
page.goto(url)
|
|
||||||
# page.pause()
|
|
||||||
for i in range(1, 500):
|
|
||||||
logger.info(f"第{i}次点击")
|
|
||||||
try:
|
|
||||||
page.get_by_role("link", name=">", exact=True).click(timeout=30000)
|
|
||||||
except Exception as e:
|
|
||||||
break
|
|
||||||
time.sleep(30)
|
|
||||||
|
|
||||||
|
|
||||||
def get_state():
|
|
||||||
with sync_playwright() as p:
|
|
||||||
browser_state_file_path = "./em_browser_state.json"
|
|
||||||
browser = p.chromium.launch(args=["--start-maximized"], headless=False)
|
|
||||||
page = browser.new_page()
|
|
||||||
url = f"https://quote.eastmoney.com/center/gridlist.html#index_sh"
|
|
||||||
page.goto(url)
|
|
||||||
page.pause()
|
|
||||||
browser.contexts[0].storage_state(path=browser_state_file_path)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse_data(data_file_path: str):
|
|
||||||
df_list = []
|
|
||||||
with open(data_file_path, "r", encoding="utf-8") as f:
|
|
||||||
for line in f:
|
|
||||||
match = re.search(r"\((\{.*\})\);?$", line)
|
|
||||||
json_str = match.group(1)
|
|
||||||
data = json.loads(json_str)
|
|
||||||
inner_temp_df = pd.DataFrame(data["data"]["diff"])
|
|
||||||
df_list.append(inner_temp_df)
|
|
||||||
temp_df = pd.concat(df_list, ignore_index=True)
|
|
||||||
temp_df["f3"] = pd.to_numeric(temp_df["f3"], errors="coerce")
|
|
||||||
temp_df.sort_values(by=["f3"], ascending=False, inplace=True, ignore_index=True)
|
|
||||||
temp_df.reset_index(inplace=True)
|
|
||||||
temp_df["index"] = temp_df["index"].astype(int) + 1
|
|
||||||
col_name_map = {
|
|
||||||
"f12": "代码",
|
|
||||||
"f14": "名称",
|
|
||||||
"f2": "最新价",
|
|
||||||
"f3": "涨跌幅",
|
|
||||||
"f4": "涨跌额",
|
|
||||||
"f5": "成交量",
|
|
||||||
"f6": "成交额",
|
|
||||||
"f7": "振幅",
|
|
||||||
"f15": "最高",
|
|
||||||
"f16": "最低",
|
|
||||||
"f17": "今开",
|
|
||||||
"f18": "昨收",
|
|
||||||
"f10": "量比",
|
|
||||||
}
|
|
||||||
temp_df.rename(
|
|
||||||
columns=col_name_map,
|
|
||||||
inplace=True,
|
|
||||||
)
|
|
||||||
new_cols = col_name_map.values()
|
|
||||||
temp_df = temp_df[new_cols]
|
|
||||||
for col in new_cols:
|
|
||||||
if col in [
|
|
||||||
"代码",
|
|
||||||
"名称",
|
|
||||||
]:
|
|
||||||
continue
|
|
||||||
temp_df[col] = pd.to_numeric(temp_df[col], errors="coerce")
|
|
||||||
return temp_df
|
|
||||||
|
|
||||||
|
|
||||||
def get_index_latest_data():
|
|
||||||
today = datetime.datetime.now().strftime("%Y%m%d")
|
|
||||||
data_file_path = f"./{today}.txt"
|
|
||||||
index_code = "index_sh"
|
|
||||||
index_code_list = ["index_sh", "index_sz", "index_components", "index_zzzs"]
|
|
||||||
for index_code in index_code_list:
|
|
||||||
logger.info(f"开始更新指数数据: {index_code}")
|
|
||||||
index_data_scraper(index_code=index_code, data_file_path=data_file_path)
|
|
||||||
df = parse_data(data_file_path)
|
|
||||||
return df
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# df = get_index_latest_data()
|
|
||||||
# code = "000001"
|
|
||||||
# df = df[df["代码"] == code]
|
|
||||||
# print(df)
|
|
||||||
get_state()
|
|
||||||
@@ -70,6 +70,10 @@ def main_calc_process():
|
|||||||
continue
|
continue
|
||||||
# 将 'date' 列转换为 datetime 类型,并设置为索引
|
# 将 'date' 列转换为 datetime 类型,并设置为索引
|
||||||
df["date"] = pd.to_datetime(df["date"])
|
df["date"] = pd.to_datetime(df["date"])
|
||||||
|
# 判断最新日期是否为今天,如果不是则跳过
|
||||||
|
today_str = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
if df["date"].max().strftime("%Y-%m-%d") != today_str:
|
||||||
|
continue
|
||||||
df = df.sort_values("date")
|
df = df.sort_values("date")
|
||||||
df.set_index("date", inplace=True)
|
df.set_index("date", inplace=True)
|
||||||
|
|
||||||
@@ -93,23 +97,40 @@ def main_calc_process():
|
|||||||
timeperiod=14,
|
timeperiod=14,
|
||||||
)
|
)
|
||||||
df_weekly = df_weekly.tail(1)
|
df_weekly = df_weekly.tail(1)
|
||||||
cci = df_weekly["cci"].values[0]
|
week_cci = df_weekly["cci"].values[0]
|
||||||
logger.info(f"{i}/{len(code_list)}: {code} cci: {cci}")
|
|
||||||
|
df["cci"] = ta.CCI(
|
||||||
|
high=df["high"],
|
||||||
|
low=df["low"],
|
||||||
|
close=df["close"],
|
||||||
|
timeperiod=14,
|
||||||
|
)
|
||||||
|
cci = df["cci"].tail(1).values[0]
|
||||||
|
logger.info(f"{i}/{len(code_list)}: {code} week_cci: {week_cci} day_cci: {cci}")
|
||||||
if cci < -100:
|
if cci < -100:
|
||||||
signal_list.append(
|
signal_list.append(
|
||||||
{"code": code, "name": code_info["指数名称"], "cci": cci}
|
{
|
||||||
|
"code": code,
|
||||||
|
"name": code_info["指数名称"],
|
||||||
|
"天cci": cci,
|
||||||
|
"周cci": week_cci,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
# break
|
# break
|
||||||
signal_df = pd.DataFrame(signal_list)
|
signal_df = pd.DataFrame(signal_list)
|
||||||
# dingtalk.send_markdown(
|
# dingtalk.send_markdown(
|
||||||
# f"CCI信号", signal_df.to_markdown(tablefmt="simple", index=False)
|
# f"CCI信号", signal_df.to_markdown(tablefmt="simple", index=False)
|
||||||
# )
|
# )
|
||||||
dingtalk.send_text(
|
if len(signal_list) > 0:
|
||||||
tabulate(signal_df, tablefmt="plain", headers="keys", showindex=False)
|
dingtalk.send_text(
|
||||||
)
|
tabulate(signal_df, tablefmt="plain", headers="keys", showindex=False)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.info("无信号")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
# main_calc_process()
|
||||||
...
|
...
|
||||||
# main()
|
# main()
|
||||||
# logger.info(datetime.now())
|
# logger.info(datetime.now())
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ from db_config import DatabaseManager, DatabaseConfig
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import akshare as ak
|
import akshare as ak
|
||||||
from index_downloader import get_all_stock_index
|
|
||||||
from em_index_sport import get_index_latest_data
|
|
||||||
import schedule
|
import schedule
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
@@ -19,28 +18,10 @@ secret = "SEC43a0fa0b29717f98637a119b92a0bd5f7b2b6da671bdd2bd1279ed8323454d5e"
|
|||||||
dingtalk = DingTalkBot(webhook, secret)
|
dingtalk = DingTalkBot(webhook, secret)
|
||||||
|
|
||||||
|
|
||||||
def set_proxy():
|
|
||||||
url = "http://v2.api.juliangip.com/company/postpay/getips?auto_white=1&num=1&pt=1&result_type=json&trade_no=6735165951220899&sign=bd763049a68b4b817608520dad35ea25"
|
|
||||||
r = requests.get(url)
|
|
||||||
data = r.json()
|
|
||||||
logger.info(data)
|
|
||||||
proxy = data["data"]["proxy_list"][0]
|
|
||||||
os.environ["https_proxy"] = f"http://{proxy}"
|
|
||||||
os.environ["http_proxy"] = f"http://{proxy}"
|
|
||||||
|
|
||||||
|
|
||||||
@retry(tries=3, delay=10)
|
|
||||||
def get_latest_index_kline_date():
|
def get_latest_index_kline_date():
|
||||||
# df = pd.read_csv(
|
|
||||||
# "/Users/aszer/Documents/vscode/etf/index_all_stock.csv", encoding="utf-8-sig"
|
df = ak.stock_zh_index_spot_sina()
|
||||||
# )
|
|
||||||
# index_hist_df = pd.read_csv(
|
|
||||||
# "/Users/aszer/Documents/vscode/etf/data/index_history_data/000001.csv",
|
|
||||||
# encoding="utf-8-sig",
|
|
||||||
# )
|
|
||||||
set_proxy()
|
|
||||||
df = get_all_stock_index()
|
|
||||||
# df = get_index_latest_data()
|
|
||||||
column_mapping = {
|
column_mapping = {
|
||||||
"date": "date",
|
"date": "date",
|
||||||
"代码": "code",
|
"代码": "code",
|
||||||
@@ -50,37 +31,13 @@ def get_latest_index_kline_date():
|
|||||||
"最新价": "close",
|
"最新价": "close",
|
||||||
"成交量": "volume",
|
"成交量": "volume",
|
||||||
}
|
}
|
||||||
|
|
||||||
df["date"] = None
|
df["date"] = None
|
||||||
df = df.rename(columns=column_mapping)
|
df = df.rename(columns=column_mapping)
|
||||||
|
df['code'] = df['code'].str.extract(r'(\d+)')[0]
|
||||||
df = df[column_mapping.values()]
|
df = df[column_mapping.values()]
|
||||||
df = df.drop_duplicates(subset=["code"])
|
df = df.drop_duplicates(subset=["code"])
|
||||||
|
|
||||||
# 获取上证指数最近30天的数据
|
|
||||||
code = "000001" # 用来获取当前最新k线数据的日期,参考 上证指数
|
|
||||||
latest = df[df["code"] == code].to_dict(orient="records")[0]
|
|
||||||
h, l, o, c = latest["high"], latest["low"], latest["open"], latest["close"]
|
|
||||||
cur_date = datetime.now().strftime("%Y%m%d")
|
cur_date = datetime.now().strftime("%Y%m%d")
|
||||||
seven_days_ago = (datetime.now() - pd.Timedelta(days=30)).strftime("%Y%m%d")
|
df["date"] = cur_date
|
||||||
index_hist_df = ak.index_zh_a_hist(
|
|
||||||
symbol=code,
|
|
||||||
period="daily",
|
|
||||||
start_date=seven_days_ago,
|
|
||||||
end_date=cur_date,
|
|
||||||
)
|
|
||||||
|
|
||||||
index_hist_df = index_hist_df.sort_values(
|
|
||||||
by="日期", ascending=False
|
|
||||||
) # 按时间降序排列
|
|
||||||
index_hist_df = index_hist_df[
|
|
||||||
(index_hist_df["最高"] == h)
|
|
||||||
& (index_hist_df["最低"] == l)
|
|
||||||
& (index_hist_df["开盘"] == o)
|
|
||||||
& (index_hist_df["收盘"] == c)
|
|
||||||
]
|
|
||||||
index_hist = index_hist_df.to_dict(orient="records")[0]
|
|
||||||
hist_date = index_hist["日期"]
|
|
||||||
df["date"] = hist_date
|
|
||||||
df.dropna(how="any", inplace=True)
|
df.dropna(how="any", inplace=True)
|
||||||
# df.to_csv(f"aaaa.csv", index=False, encoding="utf-8-sig")
|
# df.to_csv(f"aaaa.csv", index=False, encoding="utf-8-sig")
|
||||||
return df
|
return df
|
||||||
|
|||||||
Reference in New Issue
Block a user