如何存储pandas DataFrame并定时对比筛选Yfinance显著变动股票数据
实现方案
1. 历史DataFrame的存储方案
你当前仅需存储上一次采集的快照做对比,数据体量极小,优先选无额外依赖的轻量方案:
- 直接使用
pandas自带的to_pickle()方法序列化存储,读写速度快,能完整保留DataFrame的结构和数据类型,存储路径固定为本地路径即可 - 如果后续需要回溯所有历史快照,可以改用sqlite轻量数据库,每次写入新增
snapshot_time字段标记批次即可
存储示例代码:
import pandas as pd # 每次采集生成新的DataFrame后,先作为最新快照存储 new_df.to_pickle('./latest_stock_snapshot.pkl')
2. 新旧DataFrame对比逻辑(显著变动判定)
你可以根据自身需求自定义「显著变动」的判定规则,以下是通用实现流程:
import os # 第一次运行无历史快照时,直接存新快照并触发首次推送 if not os.path.exists('./latest_stock_snapshot.pkl'): new_df.to_pickle('./latest_stock_snapshot.pkl') # 此处插入你原有邮件发送逻辑 else: last_df = pd.read_pickle('./latest_stock_snapshot.pkl')
你可以组合使用以下常用判定维度:
- 维度1:符合涨跌幅阈值的股票列表变化:上一次快照中涨跌幅超2%的标的和当前快照有新增/减少,即判定为变动
- 维度2:阈值内标的涨跌幅波动超过预设值:已经符合涨跌幅超2%的股票,两次采集的涨跌幅差值超过1%(可自行调整阈值),即判定为变动
- 维度3:阈值内标的数量变化超过预设值:两次采集符合条件的股票数量差超过2只(可自行调整阈值),即判定为变动
以下是组合判定的示例代码:
# 分别筛选新旧快照中涨跌幅超2%的标的,以股票代码为索引 new_trigger = new_df[new_df['change_rate']>2].set_index('stock_code') last_trigger = last_df[last_df['change_rate']>2].set_index('stock_code') # 判定条件1:新增符合阈值的股票 new_stocks = new_trigger.index.difference(last_trigger.index) # 判定条件2:有股票从阈值范围内移出 removed_stocks = last_trigger.index.difference(new_trigger.index) # 判定条件3:原有符合阈值的股票涨跌幅变动超过1个百分点 common_stocks = new_trigger.index.intersection(last_trigger.index) large_rate_change = abs(new_trigger.loc[common_stocks, 'change_rate'] - last_trigger.loc[common_stocks, 'change_rate']) > 1 is_significant_change = len(new_stocks) > 0 or len(removed_stocks) > 0 or large_rate_change.any()
3. 触发推送后的处理逻辑
if is_significant_change: # 执行你的原有邮件发送逻辑 send_email_notification(new_trigger) # 更新本地存储的历史快照,下次采集用本次的结果对比 new_df.to_pickle('./latest_stock_snapshot.pkl') else: # 无显著变动,不发送邮件,也不更新历史快照 pass
注意事项
- 每日收盘后要清空本地快照,或者新增日期校验逻辑:如果历史快照的采集日期和当前日期不一致,直接按首次运行逻辑处理,避免跨交易日对比出错
- 若Yfinance接口调用失败没有拿到有效新数据,不要覆盖本地历史快照,避免无效对比
内容的提问来源于stack exchange,提问作者user17328035
相关产品推荐
相关产品推荐

