From f843197e279728dd876c61ea51a20529e295cfb0 Mon Sep 17 00:00:00 2001 From: yangfan <784310601@qq.com> Date: Fri, 24 Apr 2026 16:59:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=80=BB=E8=BE=91=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cal_date.py | 4 +- daily.py | 4 +- limit_up.py | 4 +- luoji.py | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 luoji.py diff --git a/cal_date.py b/cal_date.py index 775db91..9317a88 100644 --- a/cal_date.py +++ b/cal_date.py @@ -132,8 +132,8 @@ def run(start_date, end_date, token): # 5. 程序入口(只改这里) # ======================= if __name__ == "__main__": - START_DATE = "20240101" - END_DATE = "20260423" + START_DATE = "20240424" + END_DATE = "20260424" TUSHARE_TOKEN = "0fad3cf498757089e2630028455d5bbe1637475788bcdaa1f2175e93" diff --git a/daily.py b/daily.py index eeb867b..feb2a3f 100644 --- a/daily.py +++ b/daily.py @@ -144,7 +144,7 @@ def run(start_date, end_date): # ===== 输入参数 ===== if __name__ == "__main__": - START_DATE = "20240901" - END_DATE = "20260401" + START_DATE = "20260424" + END_DATE = "20260424" run(START_DATE, END_DATE) \ No newline at end of file diff --git a/limit_up.py b/limit_up.py index 5d42117..c36fbda 100644 --- a/limit_up.py +++ b/limit_up.py @@ -118,9 +118,9 @@ def analyze_and_save_limits(start_date, end_date): # ============================================================ if __name__ == "__main__": # 开始日期:计算从该日期的下一个交易日开始 - START_DATE = '2026-04-01' + START_DATE = '2026-04-23' # 结束日期 - END_DATE = '2026-04-22' + END_DATE = '2026-04-24' analyze_and_save_limits(START_DATE, END_DATE) \ No newline at end of file diff --git a/luoji.py b/luoji.py new file mode 100644 index 0000000..248cbf6 --- /dev/null +++ b/luoji.py @@ -0,0 +1,106 @@ +import pandas as pd +from sqlalchemy import create_engine + + +def analyze_stock_performance(start_date, end_date): + # --- 数据库配置 --- + try: + engine = create_engine( + "mysql+pymysql://yangfan@8.159.129.156:10836/level?charset=utf8mb4", + connect_args={ + "password": "aA%8023321088" + }, + pool_pre_ping=True + ) + + # 1. 获取涨停当日股票及价格 + limit_query = f""" + SELECT l.ts_code, l.name, d.open AS limit_day_open, d.high AS limit_day_high + FROM stock_limit_data l + LEFT JOIN stock_daily d ON l.ts_code = d.ts_code AND l.trade_date = d.trade_date + WHERE l.trade_date = '{start_date}' AND l.status = 1 + """ + df_limit = pd.read_sql(limit_query, engine) + + if df_limit.empty: + print(f"提示:{start_date} 当日没有涨停记录。") + return + + # 2. 获取行情区间数据 + codes = df_limit['ts_code'].unique().tolist() + codes_tuple = f"('{codes[0]}')" if len(codes) == 1 else str(tuple(codes)) + daily_query = f""" + SELECT ts_code, trade_date, high, low, close + FROM stock_daily + WHERE ts_code IN {codes_tuple} AND trade_date BETWEEN '{start_date}' AND '{end_date}' + ORDER BY trade_date ASC + """ + df_daily = pd.read_sql(daily_query, engine) + df_daily['trade_date'] = pd.to_datetime(df_daily['trade_date']) + + # 3. 核心逻辑处理 + final_report = [] + for _, limit_row in df_limit.iterrows(): + code = limit_row['ts_code'] + stock_data = df_daily[df_daily['ts_code'] == code].copy() + + if stock_data.empty: continue + + # A. 找到区间内的最高价及其第一次出现的日期 + max_high = float(stock_data['high'].max()) + # 获取最高价所在的那一行(如果有多个相同最高价,取第一个) + max_high_row = stock_data[stock_data['high'] == max_high].iloc[0] + max_date = max_high_row['trade_date'] + + # B. 寻找最高价日期之后的最低价 + post_max_data = stock_data[stock_data['trade_date'] > max_date] + + if not post_max_data.empty: + min_low = float(post_max_data['low'].min()) + last_close = float(post_max_data.iloc[-1]['close']) + + price_diff = max_high - min_low + drop_pct = (price_diff / max_high * 100) + rebound_pct = ((last_close - min_low) / min_low * 100) if min_low > 0 else 0 + else: + # 如果最高点出现在结束日当天,则没有“后期最低价” + min_low = None + price_diff = 0 + drop_pct = 0 + rebound_pct = 0 + + final_report.append({ + "代码": code, + "名称": limit_row['name'], + "当日开盘": float(limit_row['limit_day_open'] or 0), + "当日最高": float(limit_row['limit_day_high'] or 0), + "区间最高": max_high, + "最高日期": max_date.strftime('%Y-%m-%d'), + "见顶后最低": min_low, + "最大回落幅%": round(drop_pct, 2), + "低位至期末波动%": round(rebound_pct, 2) + }) + + # 4. 排序与输出 + if final_report: + result_df = pd.DataFrame(final_report) + result_df = result_df.sort_values(by="最大回落幅%", ascending=False) + + print(f"\n分析区间: {start_date} 至 {end_date}") + print("说明: '见顶后最低' 指最高价日期之后的最低点") + print("=" * 120) + print(result_df.to_string(index=False, na_rep='N/A')) + print("=" * 120) + + except Exception as e: + print(f"发生错误: {e}") + + +# ========================================== +# 设定日期 +# ========================================== +if __name__ == "__main__": + START_INPUT = '2024-09-24' + END_INPUT = '2026-04-23' + + analyze_stock_performance(START_INPUT, END_INPUT) \ No newline at end of file