Day 72:【99天精通Python】金融数据看板 - 数据层实现

Day 72:【99天精通Python】金融数据看板 - 数据层实现

前言

欢迎来到第72天!

在昨天的课程中,我们规划了项目的蓝图。今天,我们要开始打地基——构建数据层
一个没有数据的看板就是个空壳。我们需要做两件事:

  1. 定义模型:告诉 Flask 数据库长什么样。
  2. 填充数据:编写脚本,从 BaoStock 接口把股票数据抓回来存进数据库。

本节内容:

  • 配置 Flask-SQLAlchemy
  • 编写models.py
  • 编写数据抓取服务 (services/data_fetcher.py)
  • 初始化数据库并测试抓取

一、配置 Flask 与 数据库

config.py中存放配置信息。

# config.pyimportos BASE_DIR=os.path.abspath(os.path.dirname(__file__))classConfig:# 数据库文件路径SQLALCHEMY_DATABASE_URI='sqlite:///'+os.path.join(BASE_DIR,'finance.db')# 关闭追踪修改,节省内存SQLALCHEMY_TRACK_MODIFICATIONS=False

app.py中初始化 Flask 和 DB。

# app.pyfromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemyfromconfigimportConfig app=Flask(__name__)app.config.from_object(Config)# 初始化 SQLAlchemydb=SQLAlchemy(app)# 临时路由测试@app.route("/")defindex():return"Finance Board API"if__name__=="__main__":app.run(debug=True)

二、编写数据模型 (models.py)

根据昨天的设计,我们需要两个模型。

# models.pyfromappimportdbclassStockBasic(db.Model):__tablename__='stock_basic'# code 是主键,如 'sh.600519'code=db.Column(db.String(20),primary_key=True)code_name=db.Column(db.String(50))industry=db.Column(db.String(50))update_date=db.Column(db.Date)# 上次更新数据的日期def__repr__(self):returnf"<Stock{self.code_name}>"classStockDaily(db.Model):__tablename__='stock_daily'id=db.Column(db.Integer,primary_key=True)# 建立索引加快查询速度code=db.Column(db.String(20),index=True)date=db.Column(db.Date,index=True)open=db.Column(db.Float)high=db.Column(db.Float)low=db.Column(db.Float)close=db.Column(db.Float)volume=db.Column(db.Float)# 联合唯一索引:同一只股票同一天只能有一条数据__table_args__=(db.UniqueConstraint('code','date',name='unique_code_date'),)

初始化数据库:
打开终端进入项目目录:

python>>>from appimportdb, app>>>with app.app_context():... db.create_all()>>>exit()

此时目录下应该生成了finance.db


三、编写数据抓取服务

我们需要一个独立的模块来处理与 BaoStock 的交互。

新建services/data_fetcher.py

importbaostockasbsimportpandasaspdfromdatetimeimportdatetime,timedeltafromappimportdb,appfrommodelsimportStockBasic,StockDailyfromsqlalchemy.excimportIntegrityErrorclassDataFetcher:def__init__(self):self.system=bs.login()def__del__(self):bs.logout()deffetch_stock_list(self):"""获取所有 A 股列表并存入 StockBasic"""# 获取当天日期date=datetime.now().strftime("%Y-%m-%d")# query_all_stock 接口获取所有股票rs=bs.query_all_stock(day=date)data_list=[]whilers.next():data_list.append(rs.get_row_data())# BaoStock 返回: code, tradeStatus, code_nameforrowindata_list:code,status,name=row# 只存还在交易的股票ifstatus=='1'andcode.startswith(('sh','sz')):# 存入数据库stock=StockBasic.query.get(code)ifnotstock:stock=StockBasic(code=code,code_name=name)db.session.add(stock)db.session.commit()print(f"股票列表更新完成,共{len(data_list)}条")deffetch_daily_data(self,code,start_date=None,end_date=None):"""获取某只股票的日线数据"""ifnotend_date:end_date=datetime.now().strftime("%Y-%m-%d")ifnotstart_date:# 默认抓取过去 1 年start_date=(datetime.now()-timedelta(days=365)).strftime("%Y-%m-%d")rs=bs.query_history_k_data_plus(code,"date,open,high,low,close,volume",start_date=start_date,end_date=end_date,frequency="d",adjustflag="3")data_list=[]whilers.next():data_list.append(rs.get_row_data())# 批量入库forrowindata_list:# row: [date, open, high, low, close, volume]try:daily=StockDaily(code=code,date=datetime.strptime(row[0],"%Y-%m-%d").date(),open=float(row[1]),high=float(row[2]),low=float(row[3]),close=float(row[4]),volume=float(row[5])ifrow[5]else0)db.session.add(daily)exceptValueError:continue# 跳过无效数据try:db.session.commit()print(f"{code}数据导入成功,共{len(data_list)}条")exceptIntegrityError:db.session.rollback()print(f"{code}数据部分重复,已回滚")# 测试代码if__name__=="__main__":# 需要在 app context 下运行,因为用到了 dbwithapp.app_context():fetcher=DataFetcher()# 1. 更新股票列表 (跑一次就行)# fetcher.fetch_stock_list()# 2. 更新茅台数据fetcher.fetch_daily_data("sh.600519")

四、运行与验证

  1. 运行python services/data_fetcher.py
  2. 观察控制台输出,确认数据下载成功。
  3. 使用 DB Browser 打开finance.db,查看stock_daily表,应该能看到一整年的茅台股价数据。

五、小结

query_all_stock

query_history_k

db.session.add

DataFetcher

BaoStock API

Models

股票列表

日线数据

SQLite

关键要点

  1. ORM 模型StockBasic存元数据,StockDaily存时间序列数据。
  2. UniqueConstraint:数据库层面的约束,防止同一天插入两条重复数据。
  3. App Context:在独立的脚本中使用 Flask 的db对象时,必须包裹在app.app_context()中。

六、课后作业

  1. 完善抓取逻辑:目前的fetch_stock_list比较慢,尝试只抓取我们感兴趣的几只股票(如上证50)。
  2. 断点更新:修改fetch_daily_data,每次抓取前先查询数据库,找出这只股票最新的一条数据的日期,然后只抓取那个日期之后的数据(增量更新)。
  3. 异常处理:如果在抓取过程中网络断了怎么办?给fetcher增加重试机制。

下节预告

Day 73:金融数据看板 - 后端接口与数据分析- 数据有了,明天我们写 API 接口,并计算 MA 均线,为前端绘图提供 JSON 数据。


系列导航

  • 上一篇:Day 71 - 项目篇开篇
  • 下一篇:Day 73 - 金融数据看板后端逻辑(待更新)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1170990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2026-01-17 全国各地响应最快的 BT Tracker 服务器(电信版)

数据来源&#xff1a;https://bt.me88.top 序号Tracker 服务器地域网络响应(毫秒)1http://60.249.37.20:80/announce广东东莞电信322http://211.75.210.221:6969/announce广东广州电信333http://43.250.54.137:6969/announce天津电信1314udp://152.53.152.105:54123/announce北…

MGeo实战案例:企业级地理信息去重系统的搭建步骤

MGeo实战案例&#xff1a;企业级地理信息去重系统的搭建步骤 1. 引言 1.1 业务场景描述 在现代企业数据治理中&#xff0c;地址信息的标准化与去重是构建高质量主数据体系的关键环节。尤其是在物流、电商、金融和城市服务等领域&#xff0c;同一实体&#xff08;如门店、客户…

AutoGLM-Phone-9B核心优势揭秘|轻量化多模态模型落地实战

AutoGLM-Phone-9B核心优势揭秘&#xff5c;轻量化多模态模型落地实战 1. 引言&#xff1a;移动端多模态推理的挑战与破局 随着智能终端设备对AI能力的需求日益增长&#xff0c;如何在资源受限的移动平台上实现高效、低延迟的多模态理解成为工程实践中的关键难题。传统大模型因…

软件I2C重复启动条件实现方法:操作指南

从零实现软件I2C重复启动&#xff1a;不只是“模拟”&#xff0c;更是对协议的深度掌控你有没有遇到过这种情况&#xff1f;调试一个MPU6050传感器&#xff0c;明明地址没错、时序看起来也正常&#xff0c;可每次读出来的寄存器值都是0xFF——典型的“通信失败”症状。换了个引…

Qwen3-Embedding-0.6B效果验证:余弦相似度计算结果准确性测试

Qwen3-Embedding-0.6B效果验证&#xff1a;余弦相似度计算结果准确性测试 1. 背景与测试目标 随着大模型在检索、分类和语义理解任务中的广泛应用&#xff0c;高质量的文本嵌入&#xff08;Text Embedding&#xff09;成为构建智能系统的核心基础。Qwen3-Embedding-0.6B 作为…

Day 73:【99天精通Python】金融数据看板 - 后端接口与数据分析

Day 73&#xff1a;【99天精通Python】金融数据看板 - 后端接口与数据分析 前言 欢迎来到第73天&#xff01; 在昨天&#xff0c;我们成功地将股票历史数据存入了 SQLite 数据库。今天&#xff0c;我们的任务是将这些"死数据"变成"活数据"。 前端&#xff…

为什么证件照总不合规?AI智能工坊保姆级教程一文详解

为什么证件照总不合规&#xff1f;AI智能工坊保姆级教程一文详解 1. 引言&#xff1a;证件照的“隐形门槛” 在日常生活中&#xff0c;无论是办理身份证、护照、社保卡&#xff0c;还是投递简历、报名考试&#xff0c;我们都需要提交符合规范的证件照。然而&#xff0c;很多人…

opencv实战-人脸检测

一 人脸检测进行获取数据包1 传入参数orderDict&#xff08;&#xff09; 按照循序进行导入字典 拒绝乱序访问方式使用命名空间对象使用字典&#xff08;args&#xff09;语法​args.shape_predictorargs["shape_predictor"]动态访问​不方便方便&#xff1a;args[ke…

树莓派插针定义应用场景:4B温度传感器接线指南

树莓派4B接温度传感器&#xff1f;别再被引脚搞晕了&#xff01;一文讲透DS18B20和DHT实战接线你是不是也曾在面包板前拿着杜邦线犹豫不决&#xff1a;这根该插哪个孔&#xff1f;GPIO4到底是第几号物理针脚&#xff1f;为什么读出来温度总是85C&#xff1f;别急&#xff0c;这…

Llama3-8B定时任务处理?Cron调度实战案例

Llama3-8B定时任务处理&#xff1f;Cron调度实战案例 1. 引言&#xff1a;从本地大模型部署到自动化调度的演进 随着大语言模型&#xff08;LLM&#xff09;在企业与个人场景中的广泛应用&#xff0c;如何将模型推理能力集成到日常自动化流程中&#xff0c;成为提升效率的关键…

实测阿里Paraformer模型,识别速度达5倍实时太强了

实测阿里Paraformer模型&#xff0c;识别速度达5倍实时太强了 1. 引言&#xff1a;中文语音识别的新选择 随着人工智能技术的快速发展&#xff0c;自动语音识别&#xff08;ASR&#xff09;在会议记录、访谈转写、语音输入等场景中扮演着越来越重要的角色。在众多开源ASR方案…

用bhyve-webadmin来管理FreeBSD系统下的bhyve虚拟机(上)

BVCP&#xff08;(Bhyve Virtual-Machine Control Panel &#xff0c;bhyve-webadmin &#xff09;是一个图形化和安全的web控制面板&#xff0c;旨在管理FreeBSD bhyve虚拟机。BVCP专为数据中心级可靠性而设计&#xff0c;专为连续24/7运行而构建&#xff0c;专注于稳定性和性…

NPP 草原:印度 Vindhyan,1986-1989 年,R1

NPP Grassland: Vindhyan, India, 1986-1989, R1 简介 该数据集包含四个文本格式 (.txt) 的数据文件。其中三个文件提供了 1986 年至 1989 年间印度北部文迪亚高原三个衍生稀树草原的地上和地下生产力数据&#xff0c;每个文件对应三种不同的处理方式。每个研究地点&#xff…

通义千问2.5-7B房地产:户型分析与描述生成

通义千问2.5-7B房地产&#xff1a;户型分析与描述生成 1. 引言 1.1 业务场景描述 在房地产行业&#xff0c;楼盘推广、线上平台展示和客户沟通高度依赖对户型图的精准解读与生动描述。传统方式下&#xff0c;房产文案撰写依赖人工经验&#xff0c;耗时长、成本高&#xff0c…

FSMN-VAD模型切换:多语言VAD适配可能性探讨

FSMN-VAD模型切换&#xff1a;多语言VAD适配可能性探讨 1. 引言 1.1 语音端点检测的技术背景 语音端点检测&#xff08;Voice Activity Detection, VAD&#xff09;是语音信号处理中的基础模块&#xff0c;其核心任务是从连续音频流中准确识别出有效语音段的起止时间&#x…

Day 68:【99天精通Python】设计模式 (Design Patterns) 下篇 - 观察者与策略

Day 68&#xff1a;【99天精通Python】设计模式 (Design Patterns) 下篇 - 观察者与策略 前言 欢迎来到第68天&#xff01; 在昨天的课程中&#xff0c;我们学习了如何优雅地创建对象&#xff08;单例、工厂&#xff09;。今天&#xff0c;我们来关注对象之间的交互。 观察者模…

Z-Image-ComfyUI工作流分享:导出导入JSON文件的操作步骤

Z-Image-ComfyUI工作流分享&#xff1a;导出导入JSON文件的操作步骤 1. 引言 1.1 业务场景描述 在当前AIGC&#xff08;人工智能生成内容&#xff09;快速发展的背景下&#xff0c;图像生成模型的应用日益广泛。Z-Image-ComfyUI作为基于阿里最新开源文生图大模型Z-Image的可…

Sambert性能优化技巧:让语音合成速度提升50%

Sambert性能优化技巧&#xff1a;让语音合成速度提升50% 1. 引言&#xff1a;多情感语音合成的性能挑战 随着AI语音技术在虚拟主播、智能客服、有声读物等场景中的广泛应用&#xff0c;用户对高质量、低延迟的语音合成服务提出了更高要求。Sambert-HifiGAN作为当前主流的中文…

Python3.8图像处理:云端OpenCV预装,免去编译痛苦

Python3.8图像处理&#xff1a;云端OpenCV预装&#xff0c;免去编译痛苦 你是不是也遇到过这种情况&#xff1f;作为一名设计师&#xff0c;想用Python来批量处理图片、自动裁剪构图、提取配色方案&#xff0c;或者给设计稿加水印。兴致勃勃地打开教程&#xff0c;照着代码敲完…

Day 69:【99天精通Python】C/C++ 扩展 (CTypes/Cython) - 给 Python 装上喷气引擎

Day 69&#xff1a;【99天精通Python】C/C 扩展 (CTypes/Cython) - 给 Python 装上喷气引擎 前言 欢迎来到第69天&#xff01; Python 的优点是开发效率极高&#xff0c;但缺点也很明显&#xff1a;运行速度慢&#xff08;相比 C/C&#xff09;。 在绝大多数场景下&#xff0c;…