实际应用场景描述
在量化投资研究中,策略的有效性高度依赖于参数的选取。以“4S选股法”(或任何基于基本面的选股策略)为例,研究员或投资者通常需要通过历史数据回测,来找到最优的筛选阈值(如“营业收入同比增长率 > 15%”或“ROE > 10%”)。
传统的做法是硬编码阈值,每次调整都需要修改代码并重新运行,效率低下且缺乏直观性。本工具旨在解决这一问题,提供一个可视化的、交互式的参数调优界面,让用户可以通过拖动滑块实时调整筛选条件,并立即查看符合条件的股票数量变化,从而快速锁定合理的参数区间。
引入痛点
1. 代码门槛高:非专业程序员(如金融分析师)难以通过修改代码行来调整复杂的SQL或Pandas筛选条件。
2. 调试效率低:修改一个阈值(如将ROE从10%调到12%),需要修改代码、保存、重新运行脚本、等待结果,循环往复,耗时耗力。
3. 缺乏直观反馈:无法实时感知参数微调对“幸存者数量”的影响,难以判断筛选条件是过严还是过宽。
核心逻辑讲解
本工具的核心逻辑基于 Streamlit 的交互式组件 与 Pandas 的数据过滤 能力:
1. 数据层:使用
"pandas" 加载包含股票基本面数据的 CSV 文件(如营业收入、ROE、市盈率等)。
2. 交互层:利用
"streamlit" 的
"slider"(滑块)组件,将原本硬编码的阈值(如
"roe_threshold = 0.1")暴露给用户。
3. 响应层:一旦用户拖动滑块,Streamlit 会重新运行脚本,此时筛选逻辑会使用最新的滑块数值,通过
"df.query()" 或布尔索引过滤数据。
4. 可视化:利用
"matplotlib" 或
"streamlit" 自带的图表功能,展示筛选后的结果分布(如直方图)或直接在表格中展示明细。
代码模块化实现
1. 环境准备 (
"requirements.txt")
streamlit>=1.20.0
pandas>=1.5.0
matplotlib>=3.7.0
numpy>=1.24.0
2. 核心应用代码 (
"app.py")
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# ==========================================
# 模块 1:数据加载与预处理
# ==========================================
@st.cache_data # 缓存数据,避免每次交互都重新读取大文件
def load_data(file_path='stock_data.csv'):
"""
加载股票基本面数据。
模拟数据包含:代码、名称、营收同比增长率(rev_growth)、ROE、市盈率(PE)、行业。
"""
try:
df = pd.read_csv(file_path)
# 数据清洗:确保关键列为数值类型
numeric_cols = ['rev_growth', 'roe', 'pe']
for col in numeric_cols:
df[col] = pd.to_numeric(df[col], errors='coerce')
return df.dropna(subset=numeric_cols)
except FileNotFoundError:
st.error(f"错误:未找到数据文件 {file_path}")
return None
def generate_mock_data():
"""生成模拟数据以供演示"""
np.random.seed(42)
codes = [f"SH60{str(i).zfill(4)}" for i in range(100, 200)]
names = [f"公司_{i}" for i in range(100)]
data = {
'code': codes,
'name': names,
'rev_growth': np.random.uniform(-0.5, 1.0, len(codes)), # -50% 到 100%
'roe': np.random.uniform(-0.2, 0.4, len(codes)), # -20% 到 40%
'pe': np.random.uniform(5, 100, len(codes)),
'industry': np.random.choice(['科技', '金融', '消费', '医药', '制造'], len(codes))
}
return pd.DataFrame(data)
# ==========================================
# 模块 2:侧边栏 - 参数控制面板
# ==========================================
def render_sidebar(df):
"""渲染侧边栏,包含所有的筛选阈值滑块"""
st.sidebar.header("📊 4S 选股指标调整")
# 营收增长阈值
rev_min = float(df['rev_growth'].min())
rev_max = float(df['rev_growth'].max())
rev_threshold = st.sidebar.slider(
"营收同比增长率下限 (%)",
min_value=rev_min * 100,
max_value=rev_max * 100,
value=10.0, # 默认值 10%
step=1.0,
help="仅保留营收增长高于此值的股票"
)
# ROE 阈值
roe_min = float(df['roe'].min())
roe_max = float(df['roe'].max())
roe_threshold = st.sidebar.slider(
"ROE (净资产收益率) 下限 (%)",
min_value=roe_min * 100,
max_value=roe_max * 100,
value=8.0, # 默认值 8%
step=0.5,
help="仅保留ROE高于此值的股票"
)
# 市盈率范围
pe_threshold = st.sidebar.slider(
"市盈率 (PE) 上限",
min_value=float(df['pe'].min()),
max_value=float(df['pe'].max()),
value=50.0,
step=1.0,
help="排除估值过高的股票"
)
return rev_threshold, roe_threshold, pe_threshold
# ==========================================
# 模块 3:核心筛选逻辑
# ==========================================
def filter_stocks(df, rev_thresh, roe_thresh, pe_thresh):
"""
根据阈值筛选股票。
业务逻辑:营收增长 > X% AND ROE > Y% AND PE < Z
"""
# 注意:滑块返回的是百分比数值,需转为小数进行比较
query_str = (
f"rev_growth > {rev_thresh / 100} and "
f"roe > {roe_thresh / 100} and "
f"pe < {pe_thresh}"
)
filtered_df = df.query(query_str)
return filtered_df
# ==========================================
# 模块 4:可视化展示
# ==========================================
def display_results(filtered_df, total_count):
"""展示筛选结果及统计图表"""
count = len(filtered_df)
# 关键指标展示
col1, col2, col3 = st.columns(3)
col1.metric("符合条件的股票数", f"{count} 只", f"{count/total_count*100:.1f}%")
if count > 0:
col2.metric("平均 ROE", f"{filtered_df['roe'].mean()*100:.2f}%")
col3.metric("平均营收增长", f"{filtered_df['rev_growth'].mean()*100:.2f}%")
st.divider()
# 行业分布图
if count > 0:
st.subheader("行业分布")
fig, ax = plt.subplots(figsize=(10, 4))
# 为了中文显示正常
plt.rcParams['font.family'] = 'WenQuanYi Micro Hei'
industry_counts = filtered_df['industry'].value_counts()
ax.barh(industry_counts.index, industry_counts.values, color='#4C72B0')
ax.set_xlabel("数量")
ax.invert_yaxis() # 让数量最多的在上面
st.pyplot(fig)
# 数据明细表
st.subheader("筛选明细")
# 格式化显示
display_df = filtered_df.copy()
display_df[['rev_growth', 'roe']] = display_df[['rev_growth', 'roe']].applymap(lambda x: f"{x*100:.2f}%")
display_df['pe'] = display_df['pe'].map(lambda x: f"{x:.2f}")
st.dataframe(display_df[['code', 'name', 'industry', 'rev_growth', 'roe', 'pe']])
else:
st.warning("当前参数组合下无符合条件的股票,请放宽筛选条件。")
# ==========================================
# 模块 5:主程序入口
# ==========================================
def main():
st.set_page_config(page_title="4S 选股指标可视化工具", layout="wide")
st.title("📈 4S 选股指标自定义修改工具")
st.caption("拖动滑块实时调整筛选阈值,观察选股池变化")
# 加载数据
df = load_data()
if df is None:
# 如果文件不存在,使用模拟数据
df = generate_mock_data()
st.info("💡 当前使用模拟数据进行演示。如需使用实盘数据,请将 `stock_data.csv` 放入同目录。")
total_count = len(df)
# 渲染控制面板
rev_thresh, roe_thresh, pe_thresh = render_sidebar(df)
# 执行筛选
filtered_df = filter_stocks(df, rev_thresh, roe_thresh, pe_thresh)
# 展示结果
display_results(filtered_df, total_count)
if __name__ == "__main__":
main()
README 文件 (
"README.md")
# 4S 选股指标可视化调整工具
[](https://www.python.org/)
[](https://streamlit.io/)
## 📖 项目简介
一个基于 Python 和 Streamlit 构建的交互式股票筛选工具。用户可以通过可视化滑块实时调整“4S选股法”中的核心指标阈值(营收增长率、ROE、PE),并即时查看筛选结果的变化。
## ✨ 功能特性
- **营收增长率筛选**:剔除增长停滞或衰退的企业。
- **ROE 筛选**:锁定盈利能力强的公司。
- **PE 估值筛选**:排除估值泡沫过大的标的。
- **实时统计**:显示符合条件的股票数量、占比及行业分布。
## 🚀 快速开始
### 1. 环境安装
bash
pip install -r requirements.txt
### 2. 准备数据
在项目根目录创建 `stock_data.csv`,需包含以下列:
- `code` (代码), `name` (名称), `industry` (行业)
- `rev_growth` (营收同比增长率, 小数形式, 如 0.15 代表 15%)
- `roe` (净资产收益率, 小数形式)
- `pe` (市盈率)
若无数据文件,应用将自动加载内置的模拟数据进行演示。
### 3. 运行应用
bash
streamlit run app.py
## ⚙️ 技术架构
- **UI 框架**: Streamlit
- **数据处理**: Pandas
- **可视化**: Matplotlib
## ⚠️ 免责声明
本工具仅供技术研究与学习使用,不构成任何投资建议。股市有风险,投资需谨慎。
核心知识点卡片
1. 交互式数据应用架构
* 概念:将数据分析逻辑与前端展示分离,通过 UI 组件(如滑块、输入框)接收用户输入,实时更新后端计算结果。
* 实现:Streamlit 的
"st.slider" 绑定变量,一旦变量变化,脚本重新执行,驱动数据刷新。
2. 基本面选股逻辑 (4S 简化版)
* 营收增长 (Sales Growth):反映企业市场份额的扩张能力。
"rev_growth > 10%" 通常被视为成长型公司的门槛。
* ROE (Return on Equity):反映股东投入资本的回报率。长期来看,股价表现与 ROE 高度相关。
* PE (Price-to-Earnings):反映市场对公司未来增长的预期。低 PE 可能意味着低估,但也可能是价值陷阱。
3. 数据可视化反馈
* 原理:人类大脑处理图像的速度远快于数字。通过柱状图展示行业分布,比看表格更能快速发现“哪个行业在当前策略下更占优势”。
免责声明与风险提示
免责声明:
本工具为开源技术演示项目,旨在展示 Python 在数据科学领域的应用能力。
1. 工具中涉及的选股指标(如营收、ROE)仅为常见基本面分析维度,不代表任何投资价值判断。
2. 若使用真实市场数据,数据来源的准确性、完整性由数据提供方负责,本工具不承担任何数据相关责任。
3. 模拟数据仅为展示算法逻辑,不代表真实市场情况。
风险提示:
1. 回测不代表未来:基于历史财务数据的筛选无法预测未来股价走势。
2. 幸存者偏差:筛选出的“好公司”不代表就是“好股票”,还需考虑买入时机、市场情绪等因素。
3. 参数过拟合:过度优化参数以适应历史数据,可能导致策略在未来失效。
总结
本文介绍了如何利用 Python + Streamlit 构建一个“4S选股指标可视化调整工具”。
通过 模块化 的设计(数据层、控制层、逻辑层、展示层),我们将枯燥的代码逻辑转化为直观的 滑块交互。这不仅降低了量化策略调试的门槛,也极大地提升了研究效率。
核心收获:
1. Streamlit 是将 Python 脚本转化为 Web 应用的利器,特别适合数据科学类 Demo。
2. Pandas 的
"query" 方法结合字符串格式化,可以优雅地实现动态筛选逻辑。
3. 在量化研究中,工具化思维(将重复劳动自动化、可视化)是提升生产力的关键。
本文代码仅供学习与技术交流,不构成任何投资建议,股市有风险,入市需谨慎!
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!