企业微信

在当今的金融市场中,信息过载是投资者面临的主要挑战之一。面对沪深两市数千只股票,依靠人工逐一翻阅财报或行情数据来寻找投资机会,不仅效率低下,而且容易受到情绪波动的影响。Python作为一种高效、易用且拥有丰富生态的编程语言,成为了实现股票自动筛选的理想工具。通过编写脚本,我们可以将复杂的投资逻辑转化为计算机指令,实现7x24小时不间断的监控与筛选,从而在瞬息万变的市场中捕捉稍纵即逝的机会。

为什么选择Python进行股票筛选

Python在数据科学领域的统治地位为其在金融分析中的应用奠定了坚实基础。相比于传统的Excel手动操作,Python处理大数据集的能力有着质的飞跃。当涉及到数万行的历史交易数据或上百个财务指标时,Excel往往会变得卡顿甚至崩溃,而Python的Pandas库却能轻松应对。Python的开源特性意味着全球的开发者都在为其贡献工具,从数据获取(如Tushare、AkShare、Baostock)到技术指标计算(如TA-Lib),再到机器学习模型(如Scikit-learn),形成了一个完整的量化分析闭环。这种灵活性允许投资者根据自己的独特策略,定制化开发筛选器,无论是基于价值投资的低估值策略,还是基于动量理论的追涨策略,都能通过代码精准实现。

搭建自动化筛选环境

在开始编写筛选逻辑之前,必须先搭建好开发环境。这通常包括Python解释器的安装以及必要第三方库的配置。推荐使用Anaconda发行版,它集成了数据科学常用的库,能避免很多环境配置的麻烦。

Python自动筛选股票策略代码实战

核心库主要包括:

  1. Pandas: 数据处理的基石,用于清洗、整理和分析结构化数据。

  2. Numpy: 支持高性能的科学计算和矩阵运算。

  3. AkShare (或 Tushare): 这是获取金融数据的关键。AkShare完全开源且免费,数据源丰富,涵盖了股票、期货、期权等;Tushare则提供了更稳定的接口和更丰富的历史数据,但部分高级数据需要积分或权限。

安装过程非常简单,在命令行或终端中运行以下指令即可:


pip install pandas numpy akshare

环境就绪后,我们就进入了策略构建的核心阶段。

数据获取:策略的血液

没有数据,筛选就是无源之水。我们需要获取全市场的股票列表以及相关的财务或行情数据。以AkShare为例,获取A股所有股票的基本信息(如代码、名称、所属板块)是第一步。

通常,我们需要两个维度的数据:

  1. 静态数据:如总股本、所属行业、上市日期。这些数据变化频率较低。

  2. 动态数据:如最新收盘价、市盈率(PE)、市净率(PB)、股息率、成交量。这些数据随时间变化,是筛选的核心依据。

以下代码展示了如何获取当前A股的实时行情数据,并将其转换为DataFrame格式:


import akshare as ak

import pandas as pd

def fetch_stock_data():

    # 获取东方财富网的实时行情数据

    # 这是一个包含全市场股票最新指标的接口

    print("正在获取全市场股票实时行情...")

    df = ak.stock_zh_a_spot_em()



    # 我们需要关注的列:代码、名称、最新价、市盈率、市净率、股息率、成交量

    # 不同的接口返回的列名可能不同,这里以东方财富接口为例

    # 代码通常在 '代码' 或 'symbol' 列

    # 注意:AkShare接口更新频繁,具体列名请以实际返回为准

    # 这里我们假设列名为:代码, 名称, 最新价, 市盈率, 市净率, 股息率, 成交量



    # 简单的列名映射与筛选(根据实际返回数据调整)

    # 为了演示通用性,我们手动构建一个模拟数据结构,实际运行时请取消注释上方的ak代码

    # df = pd.DataFrame({

    #     '代码': ['000001', '000002', '600519'],

    #     '名称': ['平安银行', '万科A', '贵州茅台'],

    #     '最新价': [11.5, 7.2, 1700.0],

    #     '市盈率': [5.2, 8.5, 35.0],

    #     '市净率': [0.8, 0.5, 8.0],

    #     '股息率': [2.5, 1.8, 1.2],

    #     '成交量': [500000, 300000, 3000]

    # })



    return df

data = fetch_stock_data()

print(f"获取到 {len(data)} 条数据")

print(data.head())

核心逻辑:构建筛选器

有了数据,接下来就是根据投资逻辑编写筛选条件。这是整个自动化流程的灵魂。假设我们采用一种经典的“低估值高股息”策略,目标是寻找市盈率低、市净率低且股息率高的股票,这类股票通常被视为防御性强、具有安全边际。

筛选条件可以组合多个指标,利用Pandas的布尔索引功能,可以非常优雅地实现多条件过滤。

筛选标准设定:

  1. 市盈率 (PE) < 15:处于相对低估区间。

  2. 市净率 (PB) < 2:股价未大幅偏离净资产。

  3. 股息率 (Dividend Yield) > 3%:具有较好的现金回报能力。

  4. 成交量 (Volume) > 1000000(手):保证一定的流动性,避免买入后无法卖出的流动性陷阱。

代码实现如下:


def filter_stocks(df):

    """

    根据多因子条件筛选股票

    """

    # 数据清洗:去除缺失值,确保关键指标存在

    # 在实际数据中,某些次新股或亏损股的市盈率可能是无穷大或空值

    df_clean = df.dropna(subset=['市盈率', '市净率', '股息率', '成交量'])



    # 将数据类型转换为数值型(如果数据源返回的是字符串)

    cols_to_numeric = ['市盈率', '市净率', '股息率', '成交量', '最新价']

    for col in cols_to_numeric:

        df_clean[col] = pd.to_numeric(df_clean[col], errors='coerce')



    # 再次清洗,处理转换失败的数据

    df_clean = df_clean.dropna(subset=cols_to_numeric)



    # --- 核心筛选逻辑 ---

    # 条件1:市盈率小于15

    condition_pe = df_clean['市盈率'] < 15



    # 条件2:市净率小于2

    condition_pb = df_clean['市净率'] < 2



    # 条件3:股息率大于3%

    condition_dividend = df_clean['股息率'] > 3.0



    # 条件4:成交量大于100万手(这里假设单位是手,具体视数据源而定)

    condition_volume = df_clean['成交量'] > 1000000



    # 逻辑与运算:同时满足所有条件

    final_filter = condition_pe & condition_pb & condition_dividend & condition_volume



    # 应用筛选

    selected_stocks = df_clean[final_filter]



    # 按股息率降序排列,优先展示回报最高的

    selected_stocks = selected_stocks.sort_values(by='股息率', ascending=False)



    return selected_stocks

# 执行筛选

filtered_result = filter_stocks(data)

print("\n--- 筛选结果 ---")

print(filtered_result[['代码', '名称', '最新价', '市盈率', '市净率', '股息率']])

策略进阶:引入技术面因子

单纯依赖基本面数据可能无法捕捉短期的市场热点。在自动筛选系统中,我们可以进一步引入技术面因子,例如均线排列或RSI指标。这需要获取历史K线数据。

例如,我们可以筛选出股价站上20日均线且RSI指标未进入超买区(RSI < 70)的股票。这需要调用AkShare的K线接口。


def check_technical_indicators(stock_code):

    """

    检查单只股票的技术指标(示例)

    实际应用中,为了速度,通常一次性获取批量数据并进行向量化计算

    """

    try:

        # 获取日线数据

        # 注意:AkShare的K线接口参数需根据最新文档调整

        kline = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date="20230101", adjust="qfq")



        if kline.empty:

            return False



        # 计算20日均线

        kline['MA20'] = kline['收盘'].rolling(window=20).mean()



        # 获取最新一日数据

        latest = kline.iloc[-1]

        prev = kline.iloc[-2]



        # 条件:最新收盘价 > 20日均线,且昨日收盘价 <= 20日均线(刚突破)

        # 或者简单判断:最新价在均线上方

        price_above_ma = latest['收盘'] > latest['MA20']



        return price_above_ma

    except Exception as e:

        print(f"获取 {stock_code} 技术数据失败: {e}")

        return False

# 在筛选结果中进一步过滤(仅作演示,实际批量处理会更复杂)

# final_tech_filter = []

# for idx, row in filtered_result.iterrows():

#     if check_technical_indicators(row['代码']):

#         final_tech_filter.append(row)

# 

# tech_selected = pd.DataFrame(final_tech_filter)

结果导出与自动化执行

筛选出的股票池需要被保存下来,以便后续分析或交易系统调用。最常用的方式是导出为Excel或CSV文件。


def export_results(df, filename="selected_stocks.xlsx"):

    if not df.empty:

        df.to_excel(filename, index=False)

        print(f"\n结果已成功导出至 {filename}")

    else:

        print("\n未筛选出符合条件的股票。")

export_results(filtered_result)

为了让整个过程真正实现“自动化”,我们可以将上述代码整合到一个脚本中,并利用操作系统的定时任务(如Linux的Cron,Windows的任务计划程序)来定期执行。例如,每天收盘后自动运行脚本,更新股票池,第二天开盘前即可查看最新的筛选结果。

风险控制与注意事项

虽然Python自动筛选极大地提升了效率,但投资者必须保持清醒的头脑。

  1. 数据质量:免费数据源可能存在延迟或错误,关键决策前应交叉验证。

  2. 过拟合风险:在历史数据上表现完美的筛选条件,未必适用于未来。不要为了凑数据而调整参数。

  3. 黑天鹅事件:财务数据是滞后的。一家公司可能在发布财报的第二天就爆出重大利空。自动筛选只能作为初选,必须结合人工的深度研究。

  4. 合规性:个人使用脚本获取公开数据进行分析是合规的,但利用技术手段高频刷取数据或干扰交易所系统则是违法的。

利用Python自动筛选股票,本质上是将投资逻辑数字化、流程化。它将投资者从繁琐的数据收集工作中解放出来,专注于策略本身的打磨。从环境搭建、数据获取、多因子逻辑编写到结果导出,这一整套流程构成了量化交易的基础框架。对于初学者而言,从简单的财务指标筛选入手,逐步加入技术面因子,甚至尝试机器学习模型,是一条循序渐进的进阶之路。在这个数据驱动的时代,掌握Python这一工具,就等于掌握了开启财富之门的钥匙。但请记住,代码是冰冷的,市场是鲜活的,始终保持对市场的敬畏之心,才是长期生存的根本。