"""彼得·林奇风格股票分析器老余捞鱼版本 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']])