Py学习  »  Python

手把手教你用Python实现巴菲特的选股策略

灵度智能 • 1 年前 • 378 次点击  

沃伦·巴菲特(Warren Buffett)是投资界的传奇人物,他的选股标准一直被广大投资者视为金科玉律,凭借独特的投资哲学,建立了一个令人瞩目的金融帝国。他的投资风格稳健,注重长期收益而非短期波动,强调基本面分析和风险控制。回溯历史,无论是2000年的互联网泡沫破灭,抑或是2008年的全球金融危机,巴菲特均能在一片哀鸿遍野中寻得机遇,不仅安然无恙,反而从中获利。

巴菲特的投资哲学可以总结为寻找和购买那些具有长期竞争优势、财务健康且价格合理的公司股票,并长期持有,通过公司的内在价值增长和市场价格修正来获得投资回报。

本文介绍巴菲特所看重的财务指标,并手把手教您如何基于这些财务指标,使用 Python 实现自动化筛选符合这些标准的优质股票,完整代码请见文末。

财务指标

1、债务/权益比(Debt/Equity):

债务/权益比应小于0.5,表明公司负债比例低,财务状况健康。

2、流动比率(Current Ratio):

流动比率应在1.5至2.5之间,确保公司有充足的流动资产,但不过度占用资金。

3、市净率(Price/Book):

市净率小于1.5,意味着股价相对于资产价值较为便宜。

4、股东权益回报率(ROE):

ROE应大于8%,且过去10年保持稳定或持续增长,反映公司的盈利能力。

5、资产回报率(ROA):

ROA应大于6%,且账面价值稳定增长,表明公司资产利用效率高。

6、每股收益(EPS):

每股收益应稳定增长,显示公司盈利能力持续增强。

7、股息增长(Dividend Growth):

股息增长应稳定,确保股东获得长期收益。

8、账面价值增长

账面价值的稳定增长意味着持续的资产积累和财务状况,为未来收益和股东价值奠定基础。

9、护城河(Moat)与利息覆盖率:

公司应拥有竞争优势,且利息覆盖率大于5倍,确保公司有能力偿还债务利息。

10.、利息覆盖率

利息覆盖率高于 5 倍表示有足够的收益来支付利息义务,降低财务困境的风险。

这些标准不仅关注公司的财务健康,还考察其盈利稳定性和长期竞争优势。遵循这些标准,可以帮助你筛选出财务稳健、估值合理且具备持续增长潜力的优秀公司,从而实现长期投资收益最大化。

Python 代码实现

整体流程


  1. 获取 S&P 500 股票代码:我们首先抓取 S&P 500 公司名单。这提供了一个全面的大盘股池供分析。


  2. 定义财务指标此函数使用 获取给定股票代码的各种财务指标。我们提取必要的参数,例如债务/权益、流动比率、价格/账面、ROE、ROA、利息覆盖率等。


  3. 处理数据检索:该脚本遍历每个代码,收集财务数据,并将其附加到列表中。错误处理可确保单个代码的任何问题都不会停止整个过程。


  4. 应用 Buffett 标准:收集完所有数据后,我们将其转换为 Pandas DataFrame 并根据概述的标准应用筛选条件。


  5. 输出:最终筛选的 DataFrame 显示符合 Buffett 标准的股票代码及其各自的财务指标。


【 扫描文末二维码加入星球获取完成代码 】


获取数据


def get_financial_data(ticker):    try:        stock = yf.Ticker(ticker, proxy="http://127.0.0.1:33210")        info = stock.info        # financials = stock.financials        # balance_sheet = stock.balance_sheet        cashflow = stock.cashflow        earnings = stock.earnings
# Extract necessary metrics roic = info.get('returnOnInvestment', np.nan) roe = info.get('returnOnEquity', np.nan) gross_margin = info.get('grossMargins', np.nan) revenue_growth = calculate_revenue_growth(earnings) free_cash_flow = calculate_free_cash_flow(cashflow) debt_to_equity = info.get('debtToEquity', np.nan) earnings_stability = calculate_earnings_stability(earnings)
return { 'Ticker': ticker, 'ROIC': roic, 'ROE': roe, 'Gross Margin': gross_margin, 'Revenue Growth': revenue_growth, 'Free Cash Flow': free_cash_flow, 'Debt to Equity': debt_to_equity, 'Earnings Stability': earnings_stability }
except Exception as e: print(f"Error fetching data for {ticker}: {e}") return None


定义指标


# Calculate Revenue Growth over the last 5 yearsdef calculate_revenue_growth(earnings):    try:        if len(earnings) >= 5:            revenue_t0 = earnings['Revenue'].iloc[0]            revenue_t4 = earnings['Revenue'].iloc[4]            growth = (revenue_t4 - revenue_t0) / revenue_t0            return growth        else:            return np.nan    except:        return np.nan

# Calculate Free Cash Flow (Simplified as Cash from Operations - Capital Expenditures)def calculate_free_cash_flow(cashflow): try: cfo = cashflow.loc['Total Cash From Operating Activities'][0] capex = cashflow.loc['Capital Expenditures'][0] if 'Capital Expenditures' in cashflow.index else 0 fcf = cfo + capex # Capex is usually negative return fcf except: return np.nan

# Calculate Earnings Stability (Standard Deviation of Earnings Growth)def calculate_earnings_stability(earnings): try: if len(earnings) >= 5: earnings_growth = earnings['Earnings'].pct_change().dropna() if len(earnings_growth) > 1: std_dev = earnings_growth.std() return std_dev else: return np.nan else: return np.nan except: return np.nan

# Define scoring functions for each metricdef score_roic(roic): if pd.isna(roic): return 0 elif roic >= 15: return 1 elif roic >= 10: return 0.7 elif roic >= 5: return 0.4 else: return 0

def score_roe(roe): if pd.isna(roe): return 0 elif roe >= 20: return 1 elif roe >= 15: return 0.7 elif roe >= 10: return 0.4 else: return 0

def score_gross_margin (gm): if pd.isna(gm): return 0 elif gm >= 50: return 1 elif gm >= 40: return 0.7 elif gm >= 30: return 0.4 else: return 0

def score_revenue_growth(rg): if pd.isna(rg): return 0 elif rg >= 0.15: return 1 elif rg >= 0.10: return 0.7 elif rg >= 0.05: return 0.4 else: return 0

def score_free_cash_flow(fcf): if pd.isna(fcf): return 0 elif fcf > 0: return 1 else: return 0

def score_debt_to_equity(de): if pd.isna(de): return 0 elif de < 0.5: return 1 elif de < 1: return 0.7 elif de < 2: return 0.4 else: return 0

def score_earnings_stability(es): if pd.isna(es): return 0 elif es < 0.05: return 1 elif es < 0.10: return 0.7 elif es < 0.15: return 0.4 else: return 0

def compute_moat_score(row): scores = [ score_roic(row['ROIC']), score_roe(row['ROE']), score_gross_margin(row['Gross Margin']), score_revenue_growth(row['Revenue Growth']), score_free_cash_flow(row['Free Cash Flow']), score_debt_to_equity(row['Debt to Equity']), score_earnings_stability(row['Earnings Stability']) ] # Assign equal weights or customize as needed moat_score = np.sum(scores) / len(scores) # Average score return moat_score

筛选股票


def get_interest_coverage(ticker):    """    Fetches the Interest Coverage Ratio for a given stock ticker.
Parameters: ticker (str): The stock ticker symbol (e.g., 'AAPL').
Returns: float or None: The Interest Coverage Ratio, or None if data is unavailable. """ try: stock = yf.Ticker(ticker) income_statement = stock.financials
# Ensure the necessary data is present if 'Operating Income' in income_statement.index and 'Interest Expense' in income_statement.index: operating_income = income_statement.loc['Operating Income'][0] interest_expense = income_statement.loc['Interest Expense'][0]
# Handle cases where Interest Expense is zero to avoid division by zero if interest_expense != 0: interest_coverage = operating_income / abs(interest_expense) return round(interest_coverage, 2) else: print(f"Interest Expense is zero for {ticker}. Cannot compute Interest Coverage Ratio.") return None else: print(f"Necessary financial data not available for {ticker}.") return None
except Exception as e: print(f"Error fetching data for {ticker}: {e}") return None

def get_financials(ticker): try: stock = yf.Ticker(ticker) balance = stock.balance_sheet cashflow = stock.cashflow income = stock.financials info = stock.info
# Extract necessary metrics debt_equity = info.get('debtToEquity', np.nan) current_ratio = info.get('currentRatio', np.nan) price_book = info.get('priceToBook', np.nan) roe = info.get('returnOnEquity', np.nan) * 100 # Convert to percentage roa = info.get('returnOnAssets', np.nan) * 100 # Convert to percentage interest_coverage = get_interest_coverage(ticker) dividend_growth = info.get('dividendRate', np.nan) # Simplified eps_growth = info.get('earningsQuarterlyGrowth', np.nan)
# Book value and EPS growth could be more complex to calculate # Here we'll use simplified placeholders book_value_growth = info.get('bookValue', np.nan) # Placeholder eps = info.get('earningsPerShare', np.nan) # Latest EPS
# Economic moat is not directly available; using 'moat' information if available moat = get_moat_stocks(ticker)
return { 'Ticker': ticker, 'Debt/Equity': debt_equity, 'Current Ratio': current_ratio, 'Price/Book' : price_book, 'ROE (%)': roe, 'ROA (%)': roa, 'Interest Coverage': interest_coverage, 'Moat': moat, 'EPS Growth': eps_growth, # Additional fields can be added as needed } except Exception as e: print(f"Error fetching data for {ticker}: {e}") return None

# Fetch financial data for all tickersfinancial_data = []for ticker in sp500_tickers[:10]: # For demonstration, we're limiting to the first 10 tickers data = get_financials(ticker) if data: financial_data.append(data)
# Convert to DataFramedf = pd.DataFrame(financial_data)
# Apply Buffett's criteriafiltered_df = df[ (df['Debt/Equity'] < 0.5) & (df['Current Ratio'] > 1.5) & (df['Current Ratio'] < 2.5) & (df['Price/Book'] < 1.5) & (df['ROE (%)'] > 8) & (df['ROA (%)'] > 6) & (df['Interest Coverage'] > 5) & (df['Moat'] > 0) & (df['EPS Growth'] > 0.08) # Assuming 8% EPS growth ]

【 扫描文末二维码加入星球获取完成代码 】




▌关于我们

我们致力于提供优质的AI服务,涵盖人工智能、数据分析、深度学习、机器学习、计算机视觉、自然语言处理、语音处理等领域。如有相关需求,请私信与我们联系。

▌商务合作

请加微信“LingDuTech163”,或公众号后台私信“联系方式”。


关注【灵度智能】公众号,获取更多AI资讯。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/178207