From 8827ba8cd66ccc70e878a69fa749f22d230d87ac Mon Sep 17 00:00:00 2001 From: mianyang <784310601@qq.com> Date: Thu, 23 Apr 2026 23:04:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B6=A8=E5=81=9C=E6=9D=BF=E3=80=81=E7=82=B8?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- limit_up.py | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 limit_up.py diff --git a/limit_up.py b/limit_up.py new file mode 100644 index 0000000..5d42117 --- /dev/null +++ b/limit_up.py @@ -0,0 +1,126 @@ +import pandas as pd +from sqlalchemy import create_engine, text + +# --- 数据库配置 --- +# 请根据实际情况修改数据库连接信息 +# DB_CONN_STR = 'mysql+pymysql://root:password@127.0.0.1:3306/stock_data' + + +def init_db(engine): + """ + 初始化数据库表结构 + 1. 增加 symbol 列,位于 trade_date 之后 + 2. 建立 UNIQUE KEY 防止物理重复写入 + """ + create_table_sql = """ + CREATE TABLE IF NOT EXISTS `stock_limit_data` ( + `id` BIGINT AUTO_INCREMENT PRIMARY KEY, + `trade_date` DATE NOT NULL COMMENT '交易日期', + `symbol` VARCHAR(10) NOT NULL COMMENT '股票代码', + `ts_code` VARCHAR(20) NOT NULL COMMENT 'TS股票代码', + `name` VARCHAR(50) NOT NULL COMMENT '股票名称', + `status` TINYINT NOT NULL COMMENT '状态:1-涨停,2-炸板', + `limit_price` DECIMAL(16, 4) COMMENT '计算出的理论涨停价', + `close` DECIMAL(16, 4) COMMENT '实际收盘价', + `market` VARCHAR(20) COMMENT '所属板块', + UNIQUE KEY `uniq_date_code` (`trade_date`, `ts_code`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + """ + with engine.begin() as conn: + conn.execute(text(create_table_sql)) + + +def analyze_and_save_limits(start_date, end_date): + """ + 计算并在数据库中落地涨停、炸板详情 + """ + engine = create_engine( + "mysql+pymysql://yangfan@8.159.129.156:10836/level?charset=utf8mb4", + connect_args={ + "password": "aA%8023321088" + }, + pool_pre_ping=True + ) + + # 0. 初始化检查表结构 + init_db(engine) + + # 1. 获取基础数据和行情数据 + query = f""" + SELECT + d.trade_date, d.symbol, d.ts_code, b.name, + d.high, d.close, d.pre_close, b.market + FROM stock_daily d + JOIN stock_basic b ON d.ts_code = b.ts_code + WHERE d.trade_date > '{start_date}' + AND d.trade_date <= '{end_date}' + ORDER BY d.trade_date ASC + """ + + try: + df = pd.read_sql(query, engine) + if df.empty: + print(f"⚠️ 在指定区间 ({start_date} -> {end_date}] 内未获取到数据。") + return + + # 2. 涨停价计算规则 + def calc_limit(row): + m, p = str(row['market']), float(row['pre_close']) + # 主板10%,创业板/科创板20%,北交所30% + ratio = 1.2 if ('创业板' in m or '科创板' in m) else (1.3 if '北交所' in m else 1.1) + return round(p * ratio, 2) + + df['limit_price'] = df.apply(calc_limit, axis=1) + + # 3. 筛选涨停(1)和炸板(2) + df['is_limit'] = (df['high'] == df['limit_price']) & (df['close'] == df['limit_price']) + df['is_broken'] = (df['high'] == df['limit_price']) & (df['close'] < df['limit_price']) + + limit_df = df[df['is_limit']].copy() + limit_df['status'] = 1 + + broken_df = df[df['is_broken']].copy() + broken_df['status'] = 2 + + save_df = pd.concat([limit_df, broken_df]) + + if not save_df.empty: + # 4. 字段清洗与对齐 + final_df = save_df[[ + 'trade_date', 'symbol', 'ts_code', 'name', + 'status', 'limit_price', 'close', 'market' + ]] + + # 5. 【核心防重逻辑】:开启事务,先删后插 + with engine.begin() as conn: + # 获取待写入的所有交易日期 + target_dates = final_df['trade_date'].astype(str).unique() + date_list = ", ".join([f"'{d}'" for d in target_dates]) + + # 第一层逻辑防重:删除数据库中已存在的相同日期数据 + delete_query = f"DELETE FROM stock_limit_data WHERE trade_date IN ({date_list})" + conn.execute(text(delete_query)) + + # 第二层物理防重:通过 to_sql 写入,若触发 Unique Key 冲突会抛出异常回滚 + final_df.to_sql('stock_limit_data', conn, if_exists='append', index=False) + + print(f"✅ 处理成功!涉及交易日: {len(target_dates)} 天") + print(f"📊 总计入库: {len(final_df)} 条记录(已自动去重并覆盖历史数据)。") + else: + print("ℹ️ 该时段内全市场无涨停或炸板记录。") + + except Exception as e: + print(f"❌ 运行失败: {e}") + + +# ============================================================ +# 用户配置区 +# ============================================================ +if __name__ == "__main__": + # 开始日期:计算从该日期的下一个交易日开始 + START_DATE = '2026-04-01' + + # 结束日期 + END_DATE = '2026-04-22' + + analyze_and_save_limits(START_DATE, END_DATE) \ No newline at end of file