news 2026/4/23 12:45:11

金融数据分析-基于Streamlit的多步骤分析系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
金融数据分析-基于Streamlit的多步骤分析系统设计与实现

一、项目概述

这是一个完整的金融数据分析Web应用系统,使用Python的Streamlit框架构建,实现从数据获取、处理到可视化展示的全流程分析。系统专注于申万家用电器行业沪深300指数的深度分析,共包含10个核心步骤。

二、系统架构设计

2.1 技术栈

  • 前端框架: Streamlit

  • 数据处理: pandas

  • 可视化: matplotlib + matplotlib.dates

  • 核心语言: Python

2.2 适用领域

金融分析、数据可视化、Web应用开发

2.3 数据集准备

数据来源:Tushare数据

三、核心功能逻辑

3.1 主程序架构

Steps是从行业筛选财务分析数据处理主成分分析交易分析指数构建基准对比技术分析,这实际上是一个从宏观到微观、从基本面到技术面的完整分析链。

# 1. 导入模块和库 import streamlit as st import step1, step2, step3, step4, step5, step6, step7, step8, step9, step10 import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # 2. 页面配置 st.set_page_config( page_title="多步骤金融分析系统", layout='wide', ) # 3. 步骤定义 STEPS = [ '1.申万家用电器行业股票代码获取', '2.申万家用电器行业股票财务指标数据获取', '3.申万家用电器行业股票财务指标数据处理', '4.主成分累计贡献率在95%', '5.家电行业2017年的股票交易数据', '6.家用电器行业交易指数', '7.沪深300指数年度涨跌幅', '8.沪深300指数2016年指数的关键转折点', '9.沪深300指数2016年平均收盘', '10.沪深300指数2016年收盘指数的现价指标' ]

3.2 数据预加载机制

# 读取.py文件内容 def read_py_file(file_path): with open(file_path, "r", encoding="utf-8") as f: return f.read() # 预加载所有代码内容 CODE_CONTENTS = {} for i in range(1, 11): CODE_CONTENTS[i] = read_py_file(f"step{i}.py") # 预加载原始数据文件 ORIGINAL_DATA = { 1: pd.read_excel('申万行业分类.xlsx'), 2: pd.read_excel('上市公司财务与指标数据2013-2017.xlsx'), 5: pd.read_excel('股票交易数据_2017.xlsx'), } # 加载沪深300数据(多个步骤共用) hs300_data = pd.read_excel('沪深300指数交易数据表.xlsx') for i in [7, 8, 9, 10]: ORIGINAL_DATA[i] = hs300_data

3.3 模块化步骤处理

# 获取步骤编号 def get_step_number(step_name): return int(step_name.split('.')[0]) # 显示原始数据 def show_original_data(step_num): st.subheader('原始数据(取前100条) ') if step_num in ORIGINAL_DATA: data = ORIGINAL_DATA[step_num] if step_num == 3: data = step2.return_values() elif step_num == 4: data = pd.DataFrame(step3.return_values()[0]) elif step_num == 6: data = step5.return_values() st.dataframe(data.head(100), use_container_width=True) # 显示代码 def show_code(step_num): st.subheader('代码 ') st.code(CODE_CONTENTS[step_num], language='python')

3.4 各步骤功能模块

每个步骤的处理逻辑完全独立,不会互相干扰。

Step1.py: 申万家用电器行业股票代码获取
# -*- coding: utf-8 -*- #1.读取“申万行业分类.xlsx”表,字段如下所示: # 行业名称 股票代码 股票名称 # 获得“家用电器”行业的所有上市公司股票代码和股票简称 # 结果用序列Fs来表示,其中index为股票代码、值为股票简称 def return_values(): import pandas as pd A=pd.read_excel('申万行业分类.xlsx') F = A[A['行业名称']=='家用电器'] Fs = pd.Series(F['股票名称'].values,index=F['股票代码']) return Fs
Step2.py: 申万家用电器行业股票财务指标数据获取
# -*- coding: utf-8 -*- ''' 基于上一关的结果,读取“上市公司财务与指标数据2013-2017.xlsx”数据,其中字段依次为: Stkcd、Accper、B001101000 、B001300000、B001000000、B002000000、A001000000、 A001212000、F050501B、F091301A、F091001A、F090101B 中文名称依次为股票代码、会计期间、财务与指标(教材第8章中总体规模与投资效率指标) 任务为:筛选出家用电器行业股票代码2016年的财务与指标数据,字段同原数据表,记为data ''' def return_values(): import pandas as pd import step1 r=step1.return_values() stkcd=list(r.index) A=pd.read_excel('上市公司财务与指标数据2013-2017.xlsx') A=A.iloc[A.iloc[:,1].values=='2016-12-31',:] data = A[A['Stkcd'].isin(stkcd)] return data
Step3.py: 申万家用电器行业股票财务指标数据处理
# -*- coding: utf-8 -*- ''' 在上一关基础上,对筛选出的家用电器行业股票代码2016年的财务与指标数据, 去掉空缺值、作均值-方差标准化处理,返回结果x(数组)和股票代码code(列表) ''' def return_values(): import step2 data=step2.return_values() #上一关的结果,家用电器行业股票代码2016年的财务与指标数据 data = data.dropna() #删除缺失值 code = data['Stkcd'].tolist() #转化为列表.tolist() from sklearn.preprocessing import StandardScaler scaler = StandardScaler() #创建对象 # 提取所有数值列 num = data.select_dtypes(include=['number']) x = num.values # 直接获取数值数组 scaler.fit(x) #调用fit()拟合方法 x = scaler.transform(x) return (x,code)
Step4.py: 主成分累计贡献率在95%
# -*- coding: utf-8 -*- ''' 在上一关基础上,对去掉缺失值和标准化后的x,进行主成分分析, 并提取主成分,要求累计贡献率在95% ''' def return_values(): import step3 from sklearn.decomposition import PCA r = step3.return_values() x = r[0] #导入主成分分析模块PCA #创建分析对象y y = PCA(n_components=0.95) #贡献率为0.95 y.fit(x) #对待分析的数据进行拟合训练 Y = y.transform(x) #返回提取的主成分 return Y
Step5.py: 家电行业2017年的股票交易数据
# -*- coding: utf-8 -*- """ 在第一关的基础上,读取"股票交易数据_2017.xlsx"表,字段如下: Stkcd、Trddt、Clsprc、Dnshrtrd、Dnvaltrd、Opnprc、Hiprc、Loprc, 中文名称依次为:股票代码、交易日期、收盘价、成交量、成交额、开盘价、最高价、最低价。 任务为:筛选出家电行业2017年的股票交易数据,字段同原表,记为data """ def return_values(): import pandas as pd import step1 r=step1.return_values() stkcd=list(r.index) A=pd.read_excel('股票交易数据_2017.xlsx') data = A[A['Stkcd'].isin(stkcd)] return data
Step6.py: 家用电器行业交易指数
# -*- coding: utf-8 -*- ''' 在上一关基础上,构造家用电器行业交易指数,其中指数计算公式为: 当日指数=当日总交易额/基准日总交易额*100 其中当日总交易额=当日所有股票交易额之和,基准日为2017年首个交易日, 返回index_val ''' def return_values(): import step5 data=step5.return_values() data_total = data.groupby('Trddt')['Dnvaltrd'].sum() # 获取基准日 d = data_total.index.min() #交易额 d_amount = data_total[d] # 指数=当日总交易额/基准日总交易额*100 index_val = (data_total / d_amount * 100) return index_val
Step7.py: 沪深300指数年度涨跌幅
# -*- coding: utf-8 -*- ''' "读取沪深300指数交易数据表.xlsx",字段依次为: Indexcd、Idxtrd01、Idxtrd05 中文名称依次为:指数代码、交易日期、收盘指数 分别计算2014-2017年的年度涨跌幅, 其中年度涨跌幅=(年末收盘指数-年初收盘指数)/年初收盘指数 依次返回年度涨跌幅(r1,r2,r3,r4) ''' def rdata(date1,date2,A): #定义一个计算年度涨跌幅的函数 #输入:年初日期date1、年末日期date2、交易数据A #返回:涨跌幅r #获取年初的收盘指数 start_data = A[A['Idxtrd01'] >= date1].iloc[0] start_price = start_data['Idxtrd05'] #获取年末的收盘指数 end_data = A[A['Idxtrd01'] <= date2].iloc[-1] end_price = end_data['Idxtrd05'] #年度涨跌幅=(年末收盘指数-年初收盘指数)/年初收盘指数 r = (end_price - start_price) / start_price return r def return_values(): import pandas as pd A=pd.read_excel('沪深300指数交易数据表.xlsx') r1=rdata('2014-01-01','2014-12-31',A) r2=rdata('2015-01-01','2015-12-31',A) r3=rdata('2016-01-01','2016-12-31',A) r4=rdata('2017-01-01','2017-12-31',A) return (r1,r2,r3,r4)
Step8.py: 沪深300指数2016年指数的关键转折点
# -*- coding: utf-8 -*- ''' 序列x1,x2,x3,如果|x2-(x1+x2)/2|越大,x2成为关键转折点的可能性就越大。 "读取沪深300指数交易数据表.xlsx",字段依次为: Indexcd、Idxtrd01、Idxtrd05 中文名称依次为:指数代码、交易日期、收盘指数 请计算获得2016年指数的关键转折点20个,包括年初和年末的两个点。 并输出结果,用一个序列Fs来表示,其中index为序号,值为收盘指数。 注意:序号按年度实际交易日期从0开始编号 ''' def return_values(): import pandas as pd import numpy as np A=pd.read_excel('沪深300指数交易数据表.xlsx') I1=A.iloc[:,1].values>='2016-01-01' I2=A.iloc[:,1].values<='2016-12-31' data=A.iloc[I1&I2,:].sort_values(['Idxtrd01']) turn_points = [] p = data['Idxtrd05'].values #价格 for i in range(1, len(p) - 1): #转折点 |x2-(x1 + x3)/2| a = abs(p[i] - (p[i-1] + p[i+1]) / 2) turn_points.append((i,a,p[i])) #转折18个点,加上首尾就20个 turn_points.sort(key=lambda x: x[1], reverse=True) sel_points = turn_points[:18] # 提取索引 sel_i = [] for point in sel_points: sel_i.append(point[0]) #提取价格 sel_p = [] for point in sel_points: sel_p.append(point[2]) #添加首尾两个点 sel_i = [0] + sel_i + [len(p)-1] sel_p = [p[0]] + sel_p + [p[-1]] #创建keydata序列 keydata = pd.Series(sel_p, index=sel_i) return keydata
Step9.py: 沪深300指数2016年平均收盘
# -*- coding: utf-8 -*- ''' "读取沪深300指数交易数据表.xlsx",字段依次为: Indexcd、Idxtrd01、Idxtrd05 中文名称依次为:指数代码、交易日期、收盘指数 请计算获得2016年收盘指数的10、20、30、60日移动平均收盘指数, 返回结果为(x10,x20,x30,x60),其中xi为序列,index按年度实际交易天数从0开始编号 ''' def return_values(): import pandas as pd A=pd.read_excel('沪深300指数交易数据表.xlsx') I1=A.iloc[:,1].values>='2016-01-01' I2=A.iloc[:,1].values<='2016-12-31' rdata=A.iloc[I1&I2,:].sort_values(['Idxtrd01']) #计算移动平均 x10 = rdata['Idxtrd05'].rolling(window=10).mean() x20 = rdata['Idxtrd05'].rolling(window=20).mean() x30 = rdata['Idxtrd05'].rolling(window=30).mean() x60 = rdata['Idxtrd05'].rolling(window=60).mean() #索引从0开始 x10 = x10.reset_index(drop=True) x20 = x20.reset_index(drop=True) x30 = x30.reset_index(drop=True) x60 = x60.reset_index(drop=True) return (x10,x20,x30,x60)
Step10.py: 沪深300指数2016年收盘指数的现价指标
# -*- coding: utf-8 -*- ''' "读取沪深300指数交易数据表.xlsx",字段依次为: Indexcd、Idxtrd01、Idxtrd05 中文名称依次为:指数代码、交易日期、收盘指数 请计算获得2016年收盘指数的现价指标,其公式为: 现价=当日收盘指数 / 过去 10 个交易日的移动平均收盘指数 返回结果为p10,为序列,index按年度实际交易天数从0开始编号 ''' def return_values(): import pandas as pd A=pd.read_excel('沪深300指数交易数据表.xlsx') I1=A.iloc[:,1].values>='2016-01-01' I2=A.iloc[:,1].values<='2016-12-31' rdata=A.iloc[I1&I2,:].sort_values(['Idxtrd01']) #10日移动平均收盘指数 ma10 = rdata['Idxtrd05'].rolling(window=10).mean() #现价=当日收盘指数 / 过去 10 个交易日的移动平均收盘指数 p10 = rdata['Idxtrd05'] / ma10 #重置索引,drop=True——去掉原先索引 p10 = p10.reset_index(drop=True) #reset_index()——重置索引 return p10

3.5 步骤管理系统

从步骤名称中提取编号,例如"1.申万家用电器行业股票代码获取" → 提取数字"1"。

# 获取步骤编号 def get_step_number(step_name): return int(step_name.split('.')[0])

3.6 智能数据展示系统

根据步骤号动态选择数据源;只显示前100条数据,避免页面卡顿。

def show_original_data(step_num): st.subheader('原始数据(取前100条) ') if step_num in ORIGINAL_DATA: data = ORIGINAL_DATA[step_num] # 特殊步骤的数据处理 if step_num == 3: data = step2.return_values() # 使用前一步的结果 elif step_num == 4: data = pd.DataFrame(step3.return_values()[0]) # 多维数据转换 elif step_num == 6: data = step5.return_values() # 引用其他模块结果 st.dataframe(data.head(100), use_container_width=True) #自适应布局:use_container_width=True让表格适应容器宽度

3.7 代码透明度设计

每个step步骤对应的Python代码都显示在网页上,支持语法高亮,便于阅读和学习。

def show_code(step_num): st.subheader('代码 ') st.code(CODE_CONTENTS[step_num], language='python')

3.8 导航与界面布局

# 侧边栏 - 导航控制中心 with st.sidebar: st.subheader('请选择实验') selected_step = st.selectbox(" ", STEPS) # selectbox(" ", STEPS)的空格占位使界面更简洁 # 主内容区域 - 动态显示标题 step_num = get_step_number(selected_step) st.subheader(f'//{selected_step}//')

3.9 模块化步骤执行系统

# 步骤1:股票代码获取 if step_num == 1: r = step1.return_values() stock_codes = [str(code).zfill(6) for code in r.index] result_df = pd.DataFrame({'股票代码': stock_codes, '股票简称': r.values}) st.dataframe(result_df) # 步骤2:财务数据获取(直接展示) elif step_num == 2: r = step2.return_values() st.dataframe(r) # 步骤3:财务数据处理(组合展示) elif step_num == 3: x, code = step3.return_values() df = pd.DataFrame(x) df['Stkcd'] = code # 添加股票代码列 st.dataframe(df) # 步骤4 elif step_num == 4: r = step4.return_values() df = pd.DataFrame(r) st.dataframe(df) # 步骤7 elif step_num == 7: r = step7.return_values() df = pd.DataFrame(r) st.dataframe(df) # 步骤10 elif step_num == 10: r = step10.return_values() df = pd.DataFrame(r) st.dataframe(df)

3.10 高级可视化子系统

step5:股票走势可视化

多只股票对比,采用多线图,每条线代表一只股票,数据自动选取前5只股票,避免图表过于拥挤;使用groupby按股票代码分组绘制。

elif step_num == 5: # 数据处理 df['Trddt'] = pd.to_datetime(df['Trddt'], format='%Y-%m-%d') # 可视化配置 plt.rcParams['font.sans-serif'] = 'SimHei' st.subheader('可视化走势图 ') top5_stocks = df['Stkcd'].unique()[:5] # 只显示前5只股票 plot_data = df[df['Stkcd'].isin(top5_stocks)] # 多线图绘制 plt.figure(figsize=(10, 5)) for code, group in plot_data.groupby('Stkcd'): plt.plot(group['Trddt'], group['Clsprc'], markersize=3, label=str(code))

step6:行业指数可视化

单一指数走势,采用单线图,重点是时间序列模式。

# 专业的时间序列处理 df['Trddt'] = pd.to_datetime(df['Trddt'], format='%Y-%m-%d') df = df.sort_values('Trddt') # 按日期排序 plt.rcParams['font.sans-serif'] = 'SimHei' # 创建图表对象 fig, ax = plt.subplots(figsize=(12, 6)) # 绘制指数走势(限制前501个数据点) ax.plot(df['Trddt'][:501], df['行业指数'][:501], linewidth=2, color='blue', label='指数走势') # 专业的时间轴格式化 ax.xaxis.set_major_locator(mdates.MonthLocator()) # 按月设置刻度 ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) # 格式为年月

step8:转折点分析可视化

关键点位识别,采用折线+散点图,突出特殊点位。

# 数据准备 rdata['交易天数'] = range(len(rdata)) # 创建连续的交易天数序列 # 中文显示配置 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 绘制基础折线图 ax.plot(rdata['交易天数'], rdata['Idxtrd05'], 'b-', alpha=0.9, label='指数序列', linewidth=1.2) # 高亮转折点 ax.scatter(r.index, r.values, color='red', s=25, edgecolor='black', linewidth=0.8, zorder=5, label='转折点') # zorder=5确保散点图在折线图上方 # 样式优化 ax.spines['top'].set_visible(False) # 隐藏上边框 ax.spines['right'].set_visible(False) # 隐藏右边框

step9:移动平均线可视化

多周期分析,采用多线叠加图,展示不同周期的趋势。

# 多线图绘制(4条移动平均线) plt.plot(rdata['Idxtrd01'], x10, label='10日移动平均', linewidth=1, color='blue') plt.plot(rdata['Idxtrd01'], x20, label='20日移动平均', linewidth=1, color='orange') plt.plot(rdata['Idxtrd01'], x30, label='30日移动平均', linewidth=1, color='green') plt.plot(rdata['Idxtrd01'], x60, label='60日移动平均', linewidth=1, color='red') # 图表样式配置 plt.rcParams['font.sans-serif'] = 'SimHei' plt.title('2016年沪深300指数移动平均线', fontsize=14) plt.ylabel('指数点位', fontsize=12) plt.legend(fontsize=10) plt.grid(True, alpha=0.2) # 半透明网格 plt.xticks(rotation=45) # x轴标签旋转45度

四、技术亮点

4.1 模块化与数据智能管理

  • 10步模块化设计:将复杂的金融分析拆解为独立步骤,每个模块功能单一、接口统一

  • 智能数据流:支持原始数据、中间结果、最终分析的自动流转与共享,如沪深300数据一次加载多步骤复用

4.2 专业可视化与用户体验

  • 金融级可视化:内置多种专业图表(股票走势、行业指数、技术指标),支持时间序列优化显示

  • 一体化界面:侧边栏导航配合"原始数据-代码-结果-可视化"四段式布局,操作直观、分析透明

五、Streamlit页面部分展示

六、总结

这个项目展示了如何将复杂的金融数据分析任务分解为清晰的步骤,并通过现代化的Web界面呈现,是一个功能完整的分析工具,涵盖数据科学项目从数据处理到结果展示的全过程;这个系统可以作为金融数据分析的入门项目,也可以作为企业级分析工具的雏形进行进一步开发。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:26:21

基于C# WinForm实现的仿微信打飞机游戏

一、游戏架构设计 1. 分层架构模型 // 游戏主框架 public class GameForm : Form {private GameEngine engine;private SpriteManager spriteManager;protected override void OnLoad(EventArgs e) {engine new GameEngine(this);spriteManager new SpriteManager();Initiali…

作者头像 李华
网站建设 2026/4/23 11:27:30

TensorFlow 深度解析:从基础到实战的全维度指南

引言&#xff1a;人工智能时代的核心驱动力 在人工智能与机器学习飞速发展的今天&#xff0c;深度学习框架已成为技术落地的核心基础设施。TensorFlow 作为谷歌开源的深度学习框架&#xff0c;自 2015 年首次发布以来&#xff0c;凭借其强大的功能、灵活的架构和庞大的社区支持…

作者头像 李华
网站建设 2026/4/23 14:06:19

手搓RPC框架系列(一):基于架构设计原则的RPC基础架构设计

文 / Kenyon&#xff0c;资深软件架构师&#xff0c;15年软件开发和技术管理经验&#xff0c;从程序员做到企业技术高管&#xff0c;专注技术管理、架构设计、AI技术应用和落地。由于公众号推流的原因&#xff0c;请在关注页右上角加星标&#xff0c;这样才能及时收到新文章的推…

作者头像 李华
网站建设 2026/4/23 11:26:06

首发,速创API上线wan2.6模型API接口,中国版sora来啦

首发&#xff0c;速创API上线wan2.6模型API接口&#xff0c;中国版sora来啦 2025年12月16日&#xff0c;重磅官宣&#xff1a;**速创API同步全球首发接入「Wan 2.6」视频模型&#xff08;中国版SORA2&#xff09;** &#xff01; 无论是个人创作者的一键生成&#xff0c;还是企…

作者头像 李华
网站建设 2026/4/23 12:46:43

Nano Banana Pro 的“降维打击”:AI 芯片和硬件格局的战略重塑

在过去的 AI 浪潮中&#xff0c;硬件一直是瓶颈&#xff0c;尤其是高性能计算的 GPU&#xff0c;成为了事实上的“AI 军火商”。然而&#xff0c;谷歌的 Nano Banana Pro (NBP) 带来的最大战略威胁&#xff0c;在于它证明了极致优化的软件和算法&#xff0c;可以挑战传统硬件的…

作者头像 李华