ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用akshare构建价值投资指标选股策略:从数据到代码

用akshare构建价值投资指标选股策略:从数据到代码 先把话说在前头这篇文章不是荐股也不是教你稳赚不赔的“圣杯”。它更像是我自己把价值投资理念落成可执行代码的一份实操笔记。核心就三件事怎么理解价值投资里那些关键指标怎么用 akshare 这个开源财经数据库把 A 股的财务和行情数据拉下来再怎么把这些指标翻译成一条能跑出候选股的筛选逻辑。akshare 是个好东西它是目前国内免费开源财经数据接口里覆盖最全的之一A股行情、财务报表、估值指标、宏观数据、资金流向都能拿。过去做“指标选股”这件事很多人卡在数据这一步——要么用现成的炒股软件导出量一大就卡死要么买商业数据库一年大几千。用 akshare 的话一台普通电脑、一个 Python 环境全市场几千只股票的估值和财务数据可以批量拉下来做量化初筛。这篇文章会把从安装到选股策略落地的完整链路走一遍适合刚开始接触量化选股、又不想被复杂金融工程劝退的朋友参考。1. 价值投资和指标选股到底在选什么1.1 价值投资的底层逻辑价值投资的祖师爷格雷厄姆有句话概括得很精准买股票就是买公司的一部分而市场短期是投票机长期是称重机。放到今天这句话可以拆成两层含义第一层你买的不是一个跳动的价格数字而是企业未来创造现金流的能力第二层价格围绕价值波动当价格明显低于内在价值时就是好买点。但“内在价值”是个动态的、模糊的东西。实际执行的时候我们只能通过一些可以量化的指标去逼近它。这也就是“价值投资/指标选股”最核心的思路用公开的财务数据构建一个价值评估框架然后从全市场股票里筛出符合框架的“便宜的好公司”。为什么有人愿意花时间做这件事而不是直接听消息或者追热点原因很简单情绪驱动的短线交易普通投资者在信息、速度、纪律上都拼不过专业机构但基于财务指标的长期筛选比拼的是耐心和基本面判断力这条路子反而是散户能做深做专的。1.2 指标选股的系统化优势手工选股最大的问题是“盯不过来”。A股已经五千多家上市公司如果你想一条条看财报一个人一个月也看不完。而用程序做指标选股可以把选股逻辑固化成规则让计算机全市场扫描几秒钟内就给你一个符合条件的小池子然后你只需要把精力花在这个小池子上做深度分析。再说一个容易被忽略的层面指标选股能帮人克服“屁股决定脑袋”。人只要对某只股票有了好感就会下意识找一堆理由说服自己。但规则是死的它不关心你手里有没有这只股票不符合条件就是剔除这样反而能对抗很多非理性持仓。这也是我后来越来越推崇“先有规则、后有交易”的原因——不是靠盘感而是靠一套可以回测、可以验证的标准化流程。2. 环境准备与 akshare 安装避坑2.1 安装 akshare 的两种方式我用 akshare 的版本已经迭代到很新的版本了官方要求 Python 3.8 以上但我个人建议直接用 Python 3.10 或 3.11因为新版本对 pandas、numpy 的依赖更友好不容易出现依赖冲突。安装方式没什么花活pip install akshare -U如果是在国内网络环境下下载速度感人建议直接用清华镜像源pip install akshare -U -i https://pypi.tuna.tsinghua.edu.cn/simple装完之后建议顺手装三个配套库pandas、numpy、matplotlib前两个做数据处理第三个用来画个简单的估值分布图。装完验证一下import akshare as ak print(ak.__version__)能正常输出版本号说明安装成功。如果这一步就报错那大概率是依赖冲突最省事的办法是换一个干净的虚拟环境重装。2.2 安装过程中的高频报错我在群里见过太多新人卡在安装这一步我把几个典型问题列一下pip 升级报错先pip install --upgrade pip再装 akshare。pandas 版本冲突akshare 对 pandas 版本有要求会出现PandasError之类的提示按报错里的要求升降级 pandas 就能解决。缺少 lxml / beautifulsoup4akshare 底层大量用到了网页解析缺少解析库就补装pip install lxml beautifulsoup4 html5lib jsonpath requests。提示“No module named ‘akshare’”但是明明装过了这种情况多半是 Python 环境搞混了。命令行里输入which python确认 pip 和 Python 是同一个环境。还有一个小建议akshare 更新频率挺高的接口字段偶尔会变。如果某段代码今天能跑、过两个月报错先试试升级 akshare 版本很多时候不是你的代码写错了是接口数据源上游调整了。3. 核心指标怎么选、为什么是它们3.1 估值类指标PE、PB、股息率做价值投资这么多年我自己的体感是估值类指标比技术指标靠谱得多因为技术指标反映的是市场情绪估值类指标反映的是“你花多少钱买到公司多少盈利和资产”。市盈率PE是最常被挂在嘴边的估值指标含义是“你为公司每 1 元利润支付多少对价”。PE 越低理论上投资的回收期越短。但 PE 有一个很大的坑强周期行业比如煤炭、钢铁、有色在盈利峰值期 PE 反而是最低的这时候进去容易买在高点。所以用完 PE 之后一定要叠加 PB 或者盈利稳定性指标过滤。市净率PB衡量的是“你为公司的净资产支付了多少溢价”。PB 低于 1 意味着你在用低于净资产的价格买入虽然这不代表绝对安全但至少在资产端给了你一层缓冲。股息率则是价值投资里一个偏防御的指标它代表你光凭分红就能拿到多少回报。A股里常年有高股息率蓝筹股比如银行、公用事业、高速公路这类现金流稳定的行业股息率高往往说明公司盈利没有被大比例挪用治理也相对规范。3.2 盈利质量类指标ROE 和毛利率如果说 PE 和 PB 回答的是“贵不贵”ROE净资产收益率回答的就是“赚不赚钱”。它衡量的是公司用股东投入的每一元净资产能够创造多少净利润。长期保持 15% 以上 ROE 的公司不需要看财报细节基本就能判断它具备短期无法模仿的商业模式或品牌护城河。毛利率则用来判断护城河的深度。毛利率高的企业说明它有定价权能够把成本压力转嫁给下游。比如很多医药、白酒企业毛利率能做到 80% 以上这种生意本身就自带“不容易被打价格战”的属性。我个人筛选时还有一个习惯看“净利润现金含量”也就是经营性现金流净额占净利润的比例。如果一家企业账面利润很高但经营性现金流常年为负那利润很可能只是纸面富贵。不过在批量选股阶段先用 ROE 和毛利率粗筛把这块放到个股复核阶段再细看会更务实。3.3 akshare 里的对应数据接口在 akshare 里这些指标分布在两个地方实时行情快照和财务指标接口。实时行情接口用stock_zh_a_spot_em()它一次性返回全 A 股的最新价、涨跌幅、换手率、动态市盈率、市净率、总市值等字段。这个接口非常快是“先粗筛”的第一步。财务指标接口稍微复杂一点我用得比较多的是stock_financial_analysis_indicator(symbol600519, start_year2022)它返回某一只股票历年的净资产收益率、销售毛利率、销售净利率、资产负债率等关键财务数据。这个接口适合对粗筛后的候选股做二次精筛因为要逐只调接口速度比行情快照慢很多不适合直接对全市场几千只股票循环。4. 完整选股策略的实现流程4.1 第一步用实时行情做低估值初筛我的策略框架是“宽进严出”先用估值和流动性指标把几千只股票快速砍到几十只再逐一拉财务数据做精筛。这个顺序完全是为了效率。初筛条件我会这么设动态 PE 大于 0 且小于 15PB 大于 0 且小于 2总市值大于 100 亿元剔除 ST、退市和名称里带“退”的股票换手率大于 0.5%保证一定的流动性不至于出现买得进卖不出的问题代码实现并不复杂import akshare as ak import pandas as pd df ak.stock_zh_a_spot_em() df df.rename(columns{ 市盈率-动态: PE, 市净率: PB, 总市值: mv, 换手率: turnover }) df df[~df[名称].str.contains(ST|退)] cond ( (df[PE] 0) (df[PE] 15) (df[PB] 0) (df[PB] 2) (df[mv] 100e8) (df[turnover] 0.5) ) candidate df[cond].sort_values(PE) print(candidate.shape[0]) candidate[[代码, 名称, PE, PB, mv, turnover]].head(20)为什么要把市值卡在 100 亿以上因为价值投资逻辑在中小盘上容易失效小公司治理不规范、财务数据稳定性差很容易出现“看着便宜实际上是价值陷阱”。卡一个大市值门槛能过滤掉相当一部分财务粉饰风险。4.2 第二步拉财务指标做二次精筛用初筛拿到一个几十只股票的池子之后接着循环拉取财务指标。这里我会重点关注 ROE 和毛利率辅以资产负债率做排雷。import time result [] for code in candidate[代码].head(30): try: fin ak.stock_financial_analysis_indicator(symbolcode, start_year2022) fin fin.sort_values(日期) latest fin.iloc[-1] result.append({ 代码: code, 最新_净资产收益率: latest[净资产收益率(%)], 最新_销售毛利率: latest[销售毛利率(%)], 最新_资产负债率: latest[资产负债率(%)], }) except Exception as e: print(f{code} 处理失败: {e}) time.sleep(0.5) fin_df pd.DataFrame(result) final candidate.merge(fin_df, on代码, howinner) final final[ (final[最新_净资产收益率] 15) (final[最新_销售毛利率] 30) (final[最新_资产负债率] 60) ].sort_values(最新_净资产收益率, ascendingFalse)这里有两个细节提醒一下。第一股价可能有前导零比如平安银行的代码是“000001”直接存成数字会把前导零丢掉。所以我一般拿到代码后都补一下df[代码] df[代码].astype(str).str.zfill(6)。第二财务接口如果某只股票多次请求失败一定不要让整个循环崩掉用 try-except 包住配合 sleep 做请求间隔实测下来稳定性会好很多。4.3 第三步给候选股打分排序纯筛选的问题在于“好公司”和“便宜价格”之间的平衡没法体现。我习惯再做一个简单的打分模型综合估值和盈利质量给候选股排个序。逻辑可以很朴素每项指标按百分位打分总得分 估值分 盈利分。final[PE_score] 100 * (final[PE].max() - final[PE]) / (final[PE].max() - final[PE].min()) final[ROE_score] 100 * (final[最新_净资产收益率] - final[最新_净资产收益率].min()) / (final[最新_净资产收益率].max() - final[最新_净资产收益率].min()) final[total_score] final[PE_score] * 0.5 final[ROE_score] * 0.5 final final.sort_values(total_score, ascendingFalse) print(final[[代码, 名称, PE, PB, 最新_净资产收益率, total_score]].head(10))这个打分模型确实很粗糙但它能把你从“凭感觉选股”变成“按规则排序”。之后你可以在这个基础上继续调权重比如更看重股息率就把股息率加进打分函数更看重质量就把 ROE 的权重调高。5. 常见问题与排查技巧实录5.1 akshare 数据源接口报错用 akshare 时间长了你一定会遇到“某某接口运行时报错”。我的经验是先看一眼报错信息里有没有data、urlopen之类的字样。如果有大概率是上游网页改版或网络波动这个没法从根本上避免只能定期升级 akshare或者在代码里加个重试机制。我自己写过一个简单的重试装饰器跑数据的时候好用import time from functools import wraps def retry(max_retries3, delay2): def decorator(func): wraps(func) def wrapper(*args, **kwargs): for i in range(max_retries): try: return func(*args, **kwargs) except Exception as e: print(f第{i1}次尝试失败: {e}) time.sleep(delay) raise Exception(多次重试仍失败) return wrapper return decorator5.2 数据对齐和字段类型问题另一个高频坑是“明明数据拉下来了合并之后全是 NaN”。大多数情况都是数据对齐出了问题行情表的代码是字符串“000001”财务接口返回的代码可能是数字 1或者带交易所后缀。合并之前务必统一列的数据类型用astype(str)处理一下把代码补成 6 位。还有一个细节是财务指标的日期列。stock_financial_analysis_indicator返回的是报告期日期按字符串排序可能排不准所以排序前最好转成pd.to_datetime()。5.3 别把“低估值”等同“能买”指标选股最大的风险是买到“价值陷阱”PE 低、PB 低但经营持续恶化越跌越便宜越便宜越看似有价值。我踩过最深的坑就是为了追求低 PE 选了某个行业里的夕阳公司最后账面亏损远超分红。后来我给自己定了几条硬规矩也写进了筛选项一是必须挑连续三年 ROE 都超过 12% 的股票只看单一年份数据容易被业绩暴增的周期股骗进去二是剔除有息负债率太高的公司企业负债结构如果极端依赖银行借款市场一抽贷现金流就完了三是筛选结果只是候选池不作为买入信号真正要下手前还得打开财报逐项核一遍尤其要看经营性现金流和应收账款变化。6. 关于这套流程的一些实际操作心得说点题外话吧。我从开始写这套“价值投资/指标选股akshare”流程到现在最大的感触是代码本身不难难的是你愿意相信一套纪律并且能坚持执行。akshare 让你过去需要花钱买、花时间找的数据变得随手可拿但数据只是原料加工数据的思想才是核心。最开始跑出来的候选股我一只都不敢买后面跑多了反而学会了对每周生成的列表“涨跌不惊”。我不太关注每天跑出来的结果里有什么“神票”我关注的是这套流程是不是被严格执行了有没有过滤掉可疑的财务指标有没有坚持用估值和盈利质量双重标准去卡。如果你也想试我建议你先拿近一年已经走过的行情回放一遍看看你的筛选规则能不能有效避雷再决定要不要让它指导下一笔投资。最后再分享一个小技巧akshare 的数据源是公开接口拉数据的时候要照顾一下服务器别在短时间内高频并发请求不然容易被限流。批量跑的时候加个 sleep安全和稳妥比快更重要。
返回列表