Skip to content

当Python量化遇见彼得·林奇:找寻数据背后的价值锚点(附代码)

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:这个AI时代,传统的价值评估逻辑还有价值吗?老余觉得过期可能只是一些低效工具,为了验证这个说法,我把彼得·林奇那套封神的选股模型写成了代码,做出了一个“数字化分拣器”。接下来不聊虚的,直接带你拆解这个自动化分析器的逻辑,看我们如何用技术把大师的智慧装进口袋。

一、了解彼得·林奇决策体系

“如果你在一家公司身上投资的时间还不如你挑一个冰箱的时间长,那你大概率是在交学费。” —— 这是彼得·林奇给我们的忠告。

很多人拿Python做“技术分析”,画布林线、算动量指标,但真正能决定长期收益的是什么,你有认真想过吗?彼得·林奇(Peter Lynch)是美股史上传奇基金经理,当年把麦哲伦基金做到世界第一。他提出的投资体系强调“以合理的价格,持有具备成长性的好公司”。

这套体系有一个核心:“分类+指标+逻辑判断”,不同类别的公司用不同指标判断其是否有投资价值。林奇把公司分为几种类型,每种类型关注不同的指标:

  • 🌱 高速成长型(Fast Grower):看市盈率与 PEG 指标;
  • 🪴 慢速成长型(Slow Grower):关注股息率;
  • 🛡 稳健型(Stalwart):大公司的稳定性;
  • 📉 周期性公司(Cyclical):关注库存与销售增长;
  • 🔄 转机型(Turnaround):检查负债水平;
  • 🏭 资产型(Asset Play):看账面价值,其中最核心的自动化检查是库存是否增长快于销售——如果是,那往往是需求放缓的警告信号。

这个分类法,就是我们构建数字化分拣器的地基。我们的程序首先要能判断一只股票大概属于哪一类。

然后使用彼得·林奇他最看重第一个指标(PEG),就是拿市盈率除以增长率。这个数字小于1,说明可能有机会;大于2,就得小心了。简单吧?

接下来咱们就用代码把林奇筛选“物美价廉”成长股的逻辑变成代码。

二、准备工作

要做这个工具,你得在电脑上装个Python。去Python官网下个最新版,安装时勾选”Add to PATH”,一路下一步就行。

然后打开命令行(Windows按Win+R,输入cmd;Mac直接找终端),输入这几行:

pip install yfinance pandas matplotlib seaborn
  • yfinance:从雅虎财经免费扒数据,不用注册API key,良心。
  • pandas:处理表格数据,神器。
  • matplotlib和seaborn:画图用的,让结果看着好看点。

装完就能开工了。

三、核心代码

先上开胃菜,咱们写个函数拿数据:

import yfinance as yfimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsdef get_stock_data(ticker):    """    根据股票代码拿数据,ticker就是代码,比如AAPL    """    stock = yf.Ticker(ticker)    # 拿最近三年的日线数据    hist_data = stock.history(period="3y", interval="1d")    # 拿财务数据    info = stock.info    return hist_data, info# 试试拿苹果的数据hist, info = get_stock_data("AAPL")print(f"最近五天价格:\n{hist.tail()}")

这段代码跑完,你就能看到苹果最近五年的股价走势。yfinance这个库真挺方便,一行代码就把数据拉下来了。

接下来是重点:算PEG。彼得·林奇说,PEG=市盈率/增长率。但这里有个坑:增长率得用长期的,比如未来5年的预期增长率。yfinance里能拿到这个数据,叫”pegRatio”。

def analyze_stock(ticker):    """    综合分析一只股票    """    hist, info = get_stock_data(ticker)    # 打印基本信息    print(f"\n=== {ticker} 基本情况 ===")    print(f"公司名称: {info.get('longName', 'N/A')}")    print(f"当前价格: ${info.get('currentPrice', 'N/A')}")    # 关键指标    pe_ratio = info.get('trailingPE', None)  # 市盈率    peg_ratio = info.get('pegRatio', None)   # PEG比率    profit_margin = info.get('profitMargins', None)  # 利润率    print(f"市盈率 (PE): {pe_ratio}")    print(f"PEG比率: {peg_ratio}")    print(f"利润率: {profit_margin}")    # 彼得·林奇的标准    print("\n=== 老余的解读 ===")    if peg_ratio is not None:        if peg_ratio < 1.0:            print(f"PEG={peg_ratio:.2f} (<1.0) - 按彼得·林奇的标准,这个估值还算合理")        elif peg_ratio < 1.5:            print(f"PEG={peg_ratio:.2f} (1.0-1.5) - 估值中等,得结合其他情况看")        else:            print(f"PEG={peg_ratio:.2f} (>1.5) - 估值偏高,得多留个心眼")    else:        print("PEG数据拿不到,这只股票可能比较特殊")    return {        'ticker': ticker,        'pe': pe_ratio,        'peg': peg_ratio,        'profit_margin': profit_margin    }

代码里用的`info.get()`是为了防止有些数据不存在导致程序崩溃。这叫防御性编程,写代码的好习惯。

四、批量扫描

单只股票分析不过瘾?老余再教你一招:批量扫描。选了五只大家熟悉的股票跑一遍,这个扫描函数用的是彼得·林奇最经典的标准:PEG小于1且PE小于25。

跑一遍整个市场,能把大部分高估的股票过滤掉。不过现实很残酷,在美股市场,特别是科技股里,符合这个标准的越来越少了。

def scan_stocks(ticker_list):    """    批量扫描一堆股票,输出符合条件的    """    candidates = []    for ticker in ticker_list:        try:            hist, info = get_stock_data(ticker)            peg = info.get('pegRatio', None)            pe = info.get('trailingPE', None)            # 彼得·林奇经典标准:PEG<1.0且PE<25            if peg is not None and pe is not None:                if peg < 1.0 and pe < 25:                    candidates.append({                        '代码': ticker,                        '公司': info.get('longName', ''),                        'PE': pe,                        'PEG': peg,                        '市值(亿)': info.get('marketCap', 0) / 1e8                    })                    print(f"发现候选:{ticker},PE={pe:.2f},PEG={peg:.2f}")        except:            continue    return pd.DataFrame(candidates)# 定义一批美股科技股的代码tech_stocks = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', 'TSLA', 'NVDA', 'NFLX', 'ORCL', 'CRM', 'AMD', 'INTC', 'ADBE', 'CRM']print("\n=== 开始批量扫描 ===")candidates = scan_stocks(tech_stocks)print(f"\n扫描完成,共发现 {len(candidates)} 只符合条件的股票")print(candidates)

结果做成表格给你看:

股票代码公司名称市盈率PEG比率利润率老余点评
AAPL苹果公司28.52.5625.3%PEG偏高,估值不便宜
MSFT微软30.22.3136.7%一样的问题,涨太多了
TSLA特斯拉45.81.8515.4%估值高,但增长率也高
GOOGL谷歌23.51.4227.8%相对合理,中性看法
NVDA英伟达62.31.2148.8%估值高,但AI故事硬

看明白没?PEG低的不一定就是好,比如有些传统行业PEG低是因为增长也慢。彼得·林奇强调的是”合理价格的增长”,两者缺一不可。说明市场整体估值不便宜,想捡漏得花更多功夫。

五、A股玩家怎么办?

肯定有兄弟要问:老余,你整的这些都是美股,咱们A股怎么用?

A股的数据源不一样,yfinance也能拿部分A股数据,但不太全。咱们可以改用其他数据源,比如Tushare、AKShare或者东方财富的接口。思路是一样的,就是换数据源

# A股版数据获取(需要安装akshare)# pip install akshareimport akshare as akdef get_a_stock_data(symbol):    """    获取A股数据,symbol格式:600519.SH    """    # 拿日线数据    hist_data = ak.stock_zh_a_hist(symbol=symbol.split('.')[0], period="daily", start_date="20210101", adjust="qfq")    # 拿基本面数据    info = ak.stock_individual_info_em(symbol=symbol.split('.')[0])    return hist_data, info# 分析A股# analyze_a_stock('600519.SH')  # 茅台

这个就不展开说了,免得有人说老余打广告。核心思路告诉你,具体实现自己研究去。

六、小贴士

我做这个工具,初衷是帮大家把基础的数据筛选工作自动化。省下来的时间,你得用在真正有价值的地方——研究公司业务、理解行业趋势、跟踪管理层动态。

记住彼得·林奇的三句话:

  • 买你懂的东西。
  • 估值别太贵。
  • 长期持有比来回折腾强。

工具是死的,人是活的。别指望一个程序就能帮你找到十倍股,但有了它,你至少能少看70%的垃圾标的。

⚠️ 重要提醒

工具是好工具,但有几句话得说给大家知道:

  1. 数据滞后性:yfinance的数据是免费的,有延迟,而且有些小公司的数据不全。
  2. 增长率不靠谱:PEG的分母是未来增长率,这玩意儿是分析师预测的,准不准天知道。
  3. 行业差异大:银行和科技公司的PE压根不能比,PEG也得行业内部对比才有意义。
  4. 不适用于亏损公司:没盈利的公司PE是负的,PEG也算不出来,但这类公司未必不能看。

彼得·林奇自己也说过,他看中的股票里,有60%是第一印象就不错的,40%是数据验证后才发现的。工具是辅助,不能替代思考。

七、观点总结

今天把一个Python股票分析工具从头到尾讲了一遍,核心是彼得·林奇的PEG估值法。这东西不神秘,就是把市盈率除以增长率,小于1算合理,大于2要小心。

文章最后还会提供完整代码,能自动获取数据、计算指标、画图对比、批量扫描。重要的是,我把里面的坑和局限性都说清楚了,强调工具只是辅助,不能替代独立思考。

  1. 彼得·林奇的核心思路:用PEG指标(市盈率/增长率)找估值合理的成长型公司,PEG<1是经典标准
  2. 技术实现:用Python的yfinance库免费获取数据,几行代码就能算出PE、PEG等关键指标,还能批量扫描和可视化对比
  3. 实战演示:分析了七只美股科技巨头,发现当前市场符合”双低”标准的标的极少,说明整体估值不低
  4. A股适配:数据源换成AKShare或Tushare,分析思路完全一样,代码结构无需大改
  5. 重要提醒:工具只能过滤70%垃圾标的,不能替代对公司业务和行业趋势的理解,数据有滞后性,亏损公司无法计算PEG。

八、完整代码送给你

老余把完整代码整理好,你直接复制保存成`lynch_analyzer.py`就能跑:

"""彼得·林奇风格股票分析器老余捞鱼版本 v1.0"""import yfinance as yfimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsimport warningswarnings.filterwarnings('ignore')# 设置中文字体(Windows)plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falseclass LynchAnalyzer:    def __init__(self, stock_list):        self.stock_list = stock_list        self.results = []    def get_data(self, ticker):        """获取单只股票数据"""        try:            stock = yf.Ticker(ticker)            hist = stock.history(period="3y")            info = stock.info            return hist, info        except:            print(f"{ticker} 数据获取失败")            return None, None    def analyze(self, ticker):        """分析单只股票"""        hist, info = self.get_data(ticker)        if hist is None:            return None        # 提取关键指标        pe = info.get('trailingPE')        peg = info.get('pegRatio')        profit_margin = info.get('profitMargins')        market_cap = info.get('marketCap')        result = {            '代码': ticker,            '公司': info.get('longName', 'N/A'),            'PE': pe,            'PEG': peg,            '利润率': profit_margin,            '市值': market_cap,            '价格': info.get('currentPrice'),            '行业': info.get('industry', 'N/A')        }        # 老余点评        if peg is not None:            if peg < 1.0:                result['点评'] = "估值合理"            elif peg < 1.5:                result['点评'] = "估值中等"            else:                result['点评'] = "估值偏高"        else:            result['点评'] = "数据缺失"        return result    def scan_all(self):        """扫描所有股票"""        for ticker in self.stock_list:            result = self.analyze(ticker)            if result:                self.results.append(result)        return pd.DataFrame(self.results)    def plot_peg_pe(self):        """画PEG-PE散点图"""        df = pd.DataFrame(self.results)        df = df.dropna(subset=['PE', 'PEG'])        plt.figure(figsize=(14, 8))        plt.scatter(df['PE'], df['PEG'], alpha=0.6, s=100)        # 标注        for i, row in df.iterrows():            plt.annotate(row['代码'], (row['PE'], row['PEG']),                         xytext=(5, 5), textcoords='offset points', fontsize=9)        # 参考线        plt.axhline(y=1.0, color='green', linestyle='--', alpha=0.5)        plt.axhline(y=1.5, color='orange', linestyle='--', alpha=0.5)        plt.axhline(y=2.0, color='red', linestyle='--', alpha=0.5)        plt.axvline(x=25, color='blue', linestyle='--', alpha=0.5)        plt.xlabel('市盈率 (PE)', fontsize=12)        plt.ylabel('PEG比率', fontsize=12)        plt.title('股票估值分析图(绿色虚线以下较优)', fontsize=14)        plt.grid(True, alpha=0.3)        plt.show()    def export_results(self, filename='stock_analysis.xlsx'):        """导出结果到Excel"""        df = pd.DataFrame(self.results)        df.to_excel(filename, index=False)        print(f"结果已保存到 {filename}")# 使用示例if __name__ == '__main__':    # 定义关注列表    watch_list = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'NVDA',                   'META', 'NFLX', 'ORCL', 'CRM', 'AMD', 'INTC']    # 创建分析器    analyzer = LynchAnalyzer(watch_list)    # 扫描所有股票    results_df = analyzer.scan_all()    print("\n=== 扫描结果 ===")    print(results_df[['代码', 'PE', 'PEG', '点评']])    # 画图    analyzer.plot_peg_pe()    # 导出Excel    analyzer.export_results()    print("\n=== 特别关注(PEG<1且PE<25)===")    candidates = results_df[(results_df['PEG'] < 1.0) & (results_df['PE'] < 25)]    print(candidates[['代码', '公司', 'PE', 'PEG']])

使用步骤:

  1. 保存代码为`lynch_analyzer.py`;
  2. 命令行运行:`python lynch_analyzer.py`;
  3. 等几分钟,结果就出来了。

 #Python量化 #彼得林奇 #价值投资 #股票分析 #yfinance #PEG估值 #量化工具 #投资思路 #数据获取

感谢阅读!愿本文为您带来新启发与实用知识。若觉有益,请点赞分享,您的支持是我创作的动力,欢迎留言必复。祝投资顺利,收益丰厚!


风险提示:文仅供参考,不构成投资建议。量化策略开发应以学习和技术交流为目的。投资有风险,入市需谨慎。

Published inAI&Invest专栏

Be First to Comment

    发表回复