POLOXUE's BLOG

POLOXUE's BLOG

13 Jan 2025

使用 Streamlit 打造一个股票筛选分析工具

本文将介绍如何通过 Python、Streamlit 和 Tushare,搭建一个简单易用的股票筛选器,它不仅可以筛选股票,还能查看某个股票的详细数据生成动态 K 线图,让你对股票市场有更全面的了解。

概述

这个股票筛选器提供将提供几个筛选能力,包括市值范围、行业、地域条件。还支持股票的 K 线图,帮助用户直观分析价格走势。

效果如下:

这个小工具的实现离不开一个关键的 Python 开源库 - Streamlit。它可以快速构建交互式 Web 应用,只需几行代码,即可分享你的数据。对 streamlit 有兴趣可以深入了解下,这里不展开介绍。

如果不想看下面的详细步骤可直接从 github gist 拿到代码,完成第一部分的准备即可运行。

想进一步扩展的话,还可以添加更多筛选指标,此外还可为单只股票增加技术指标(如均线、RSI)分析、多股票价格走势对比、实时数据更新、模拟投资组合功能甚至是按筛选分析结果生成股票分析报告等功能。


接下来,讲解代码的每一步实现过程。

准备开始

安装要用到 python 库:

1
pip install tushare ploty streamlit

并提前导入依赖包:

1
2
3
4
import streamlit as st
import tushare as ts
import pandas as pd
import plotly.graph_objects as go

通过 pro = ts.pro\_api() 配置了 Tushare 接口,为数据获取做好准备。

1
2
ts.set_token("Your API Token")
pro = ts.pro_api()

注:tushare pro 依赖于 API Key,如果没有的话,到 tushare pro 平台注册获取。


股票数据

为了完成股票数据的筛选,要用到 tushare 的两个,分别是 stock_basic 股票基础数据和 stock_daily 每日最新指标,这里有要用到的市值数据。

基础信息

首先,获取所有上市股票的基本信息,包括股票代码、名称、行业、地域和上市日期。如果某些行业或地域数据缺失,用 “Unknown” 填补空值。

1
2
3
4
5
6
7
8
9
@st.cache_data
def get_stock_list():
    df = pro.stock_basic(
        exchange="",
        list_status="L",
        fields="ts_code,symbol,name,area,industry,list_date",
    )
    df["area"] = df["area"].fillna("Unknown")
    df["industry"] = df["industry"].fillna("Unknown")

为了提高性能和减少重复计算,这里用了 @st.cache_data  装饰器缓存数据结果,股票的基础数据是不怎么变化的,这样可避免每次交互重复加载数据。

市值数据

为了筛选高市值股票,调用每日基础数据接口,获取市值数据,并将其与基本信息合并。

1
2
3
4
market_cap_data = pro.daily_basic()
market_cap_data["total_mv"] = market_cap_data["total_mv"] / 10000  # 转换为"亿"
df = pd.merge(df, market_cap_data, on="ts_code", how="left")
df = df.rename(columns={"total_mv": "market_cap"})

到这里,我们生成了一份包含公司基本信息和市值的完整股票列表,为后续筛选做好准备。


界面和筛选条件

接下来,创建用户界面和筛选项。

1
2
st.title("Stock Screener")
st.sidebar.header("Filter Options")

侧边栏设置以下筛选条件:

  • 市值范围:设置筛选股票的最小和最大市值。
  • 行业和地域:按行业或地域选择股票。
  • 上市日期范围:筛选符合时间条件的公司。

筛选实现

以下代码实现了这些过滤功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 股票的基本信息
stocks = get_stock_list()

# 筛选市值范围
min_market_cap = st.sidebar.number_input("Minimum Market Cap (亿)", min_value=0, value=100)
max_market_cap = st.sidebar.number_input("Maximum Market Cap (亿)", min_value=0, value=1000)

# 筛选行业和地域
industry_list = stocks["industry"].unique().tolist()
selected_industry = st.sidebar.multiselect("Select Industry", industry_list)

area_list = stocks["area"].unique().tolist()
selected_area = st.sidebar.multiselect("Select Area", area_list)

根据这些条件,我们过滤股票数据:

1
2
3
4
5
6
7
8
9
filtered_stocks = stocks.copy()
filtered_stocks = filtered_stocks[
    (filtered_stocks["market_cap"] >= min_market_cap) &
    (filtered_stocks["market_cap"] <= max_market_cap)
]
if selected_industry:
    filtered_stocks = filtered_stocks[filtered_stocks["industry"].isin(selected_industry)]
if selected_area:
    filtered_stocks = filtered_stocks[filtered_stocks["area"].isin(selected_area)]

这样可以看到符合条件的股票列表。


结果显示

我们继续通过 streamlit 的表格形式展示筛选后的股票列表,按照市值大小排序。

1
2
3
4
display_df = filtered_stocks.copy()
display_df["market_cap"] = display_df["market_cap"].round(2)
display_df = display_df.sort_values(by="market_cap", ascending=False)
st.dataframe(display_df)

这样就可以清晰地看到结果,并快速找到目标股票。


单只股票详情

有了筛选的股票列表后,还可以继续扩展,查看单只股票的情况,如蜡烛图、价格表格。

日线数据

先通过 Tushare 接口获取用户选择的股票的日线数据,并根据日期范围过滤。

1
2
3
4
5
6
7
@st.cache_data
def get_daily_data(ts_code):
    return pro.daily(ts_code=ts_code)

daily_data = get_daily_data(stock_code)
daily_data["trade_date"] = pd.to_datetime(daily_data["trade_date"])
daily_data = daily_data.sort_values("trade_date", ascending=True)

筛选界面

配置筛选条件,包括股票选择框和日期范围。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Show details for selected stock
selected_stock = st.selectbox("Select a stock to view details", filtered_stocks["name"])

today = pd.Timestamp.today()
col1, col2 = st.columns(2)
with col1:
    start_date = st.date_input(
        "Start date", value=today - pd.Timedelta(days=365), max_value=today
    )
with col2:
    end_date = st.date_input(
        "End date", value=today, min_value=start_date, max_value=today
    )

筛选逻辑

如果设置了 selected_stock 进入到筛选逻辑中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
if selected_stock:
    stock_code = filtered_stocks[filtered_stocks["name"] == selected_stock][
        "ts_code"
    ].values[0]
    daily_data = get_daily_data(stock_code)

    daily_data["trade_date"] = pd.to_datetime(daily_data["trade_date"])
    daily_data = daily_data.sort_values("trade_date", ascending=True)

    # 按时间过滤
    daily_data = daily_data[
        (daily_data["trade_date"] >= pd.Timestamp(start_date))
        & (daily_data["trade_date"] <= pd.Timestamp(end_date))
    ]

    # 检查缺失数据
    if daily_data[["open", "high", "low", "close"]].isnull().values.any():
        st.warning("Some price data is missing - filling with previous values")
        daily_data[["open", "high", "low", "close"]] = daily_data[
            ["open", "high", "low", "close"]
        ].ffill()

绘制 K 线图

使用 Plotly 绘制动态 K 线图,让用户更直观地观察股票的价格变化。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
fig = go.Figure(
    data=[
        go.Candlestick(
            x=daily_data["trade_date"],
            open=daily_data["open"],
            high=daily_data["high"],
            low=daily_data["low"],
            close=daily_data["close"],
            increasing_line_color="green",
            decreasing_line_color="red",
        )
    ]
)
fig.update_layout(title=f"{selected_stock} Candlestick Chart", xaxis_title="Date", yaxis_title="Price")
st.plotly_chart(fig, use_container_width=True)

总结与扩展

通过以上步骤简单构建了一个股票筛选分析工具,它支持按市值、行业、地域和上市日期筛选股票,可视化 K 线图。

希望本文对你有用,开始构建属于你的股票分析工具吧!

本文来源于 POLOXUE's BLOG,地址: 使用 Streamlit 打造一个股票筛选分析工具