Python 如何实现经典格雷厄姆价值投资策略?

Life is short,I use python to invest..囧

今天给大家分享一个超经典的价值投资策略

Benjamin Graham 是一位价值投资者。他比较有名的有 Graham number 和 Graham formula。

著名的 Graham number 公式

alt text

这个 22.5 是怎么来的呢?取自他的观点 -只买便宜的,投资 15 倍以下 pe 和 1.5 倍以下 pb 的股票。

著名的 Graham number 适用于 Defensive investor (防御型投资者),既然是防御保守型的投资者,那么除了较低的 PE 和 PB ratio 以外,还需要考察公司的其他几个方面(不然就选到垃圾股了)

抗风险的大公司,高市值,高销售

偿债能力,不会有破产风险 current ratio>2, long term debt<working captial

赚钱能力,利润持续增长

PE ratio < 15

PB ratio <1.5

这是价值投资的一个大概思路。每个月调仓一次。看下来中长期的投资回报还是相对稳健的。有兴趣的同学可以尝试修改完善。

这是收益图

alt text

这是源码

源码在 Ricequant实现

# 可以自己 import 我们平台支持的第三方 python 模块,、numpy 等。
import pandas as pd
import numpy as np
import datetime
import math

在这个方法中编写任何的初始化逻辑。context 对象将会在你的算法策略的任何方法之间做传递。

def init(context):

scheduler.run_monthly(rebalance,8)

你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新

def handle_bar(context, bar_dict):

pass

def before_trading(context): num_stocks = 10

#删选股票
fundamental_df = get_fundamentals(
    query(
        fundamentals.eod_derivative_indicator.pb_ratio,
        fundamentals.eod_derivative_indicator.pe_ratio,
        fundamentals.financial_indicator.inc_earnings_per_share,
        fundamentals.financial_indicator.inc_profit_before_tax,
        fundamentals.financial_indicator.quick_ratio,
        fundamentals.financial_indicator.earnings_per_share,
        fundamentals.financial_indicator.book_value_per_share,
    )
    .filter(
        fundamentals.eod_derivative_indicator.pe_ratio&lt;15
    )
    .filter(
        fundamentals.eod_derivative_indicator.pb_ratio&lt;1.5
    )
    .filter(
        fundamentals.financial_indicator.inc_earnings_per_share&gt;0
    )
    .filter(
        fundamentals.financial_indicator.inc_profit_before_tax&gt;0
    )
    .filter(
        fundamentals.financial_indicator.current_ratio&gt;2
    )
    .filter(
        fundamentals.financial_indicator.quick_ratio&gt;1
    )
    .order_by(
        fundamentals.eod_derivative_indicator.market_cap.desc()
    ).limit(
        num_stocks
    )
)



context.fundamental_df = fundamental_df
context.stocks = context.fundamental_df.columns.values

def rebalance(context,bar_dict):

#调仓
for stock in context.portfolio.positions:
    if stock not in context.fundamental_df:
        order_target_percent(stock, 0)

        

weight = update_weights(context, context.stocks)

for stock in context.fundamental_df:
    if weight != 0 and stock in context.fundamental_df:
        order_target_percent(stock,weight)

def update_weights(context,stocks): if len(stocks) == 0: return 0 else:

    weight = .95/len(stocks)
    return weight


Python 如何实现经典格雷厄姆价值投资策略?

1 回复

import pandas as pd
import numpy as np
import yfinance as yf
from datetime import datetime, timedelta

class GrahamValueStrategy:
    """
    格雷厄姆价值投资策略实现
    核心指标:
    1. 市盈率(P/E) < 15
    2. 市净率(P/B) < 1.5
    3. 资产负债率 < 50%
    4. 当前股价 < 净流动资产价值(NCAV)的2/3
    """
    
    def __init__(self, symbols):
        self.symbols = symbols
        self.results = []
    
    def calculate_ncav(self, balance_sheet, market_cap):
        """计算净流动资产价值(NCAV)"""
        try:
            current_assets = balance_sheet.loc['Total Current Assets'][0]
            total_liabilities = balance_sheet.loc['Total Liabilities Net Minority Interest'][0]
            ncav = current_assets - total_liabilities
            ncav_per_share = ncav / balance_sheet.loc['Common Stock'][0]
            return ncav_per_share
        except:
            return None
    
    def analyze_stock(self, symbol):
        """分析单只股票是否符合格雷厄姆标准"""
        try:
            stock = yf.Ticker(symbol)
            
            # 获取基本面数据
            info = stock.info
            financials = stock.financials
            balance_sheet = stock.balance_sheet
            
            # 提取关键指标
            pe_ratio = info.get('trailingPE', None)
            pb_ratio = info.get('priceToBook', None)
            debt_to_equity = info.get('debtToEquity', None)
            current_price = info.get('currentPrice', None)
            market_cap = info.get('marketCap', None)
            
            # 计算NCAV
            ncav_per_share = self.calculate_ncav(balance_sheet, market_cap)
            
            # 应用格雷厄姆标准
            criteria = {
                'symbol': symbol,
                'pe_ok': pe_ratio is not None and pe_ratio < 15,
                'pb_ok': pb_ratio is not None and pb_ratio < 1.5,
                'debt_ok': debt_to_equity is not None and debt_to_equity < 0.5,
                'ncav_ok': ncav_per_share is not None and current_price < (ncav_per_share * 2/3),
                'current_price': current_price,
                'pe_ratio': pe_ratio,
                'pb_ratio': pb_ratio,
                'debt_to_equity': debt_to_equity,
                'ncav_per_share': ncav_per_share
            }
            
            # 计算综合得分(符合的条件数量)
            criteria['score'] = sum([
                criteria['pe_ok'],
                criteria['pb_ok'], 
                criteria['debt_ok'],
                criteria['ncav_ok']
            ])
            
            return criteria
            
        except Exception as e:
            print(f"分析 {symbol} 时出错: {str(e)}")
            return None
    
    def run_screening(self):
        """运行股票筛选"""
        print("开始格雷厄姆价值投资策略筛选...")
        print("-" * 80)
        
        for symbol in self.symbols:
            result = self.analyze_stock(symbol)
            if result:
                self.results.append(result)
                
                # 打印结果
                status = "✓" if result['score'] >= 3 else "✗"
                print(f"{status} {symbol:6} | "
                      f"PE: {result['pe_ratio']:6.2f} | "
                      f"PB: {result['pb_ratio']:6.2f} | "
                      f"负债率: {result['debt_to_equity']:6.2f} | "
                      f"得分: {result['score']}/4")
        
        return self.results
    
    def get_recommendations(self, min_score=3):
        """获取推荐股票列表"""
        recommendations = [r for r in self.results if r['score'] >= min_score]
        
        print(f"\n推荐股票(得分>={min_score}):")
        print("=" * 80)
        for rec in sorted(recommendations, key=lambda x: x['score'], reverse=True):
            print(f"{rec['symbol']:6} | 价格: ${rec['current_price']:7.2f} | "
                  f"得分: {rec['score']}/4 | "
                  f"NCAV/股: ${rec['ncav_per_share']:7.2f if rec['ncav_per_share'] else 'N/A':>7}")

# 使用示例
if __name__ == "__main__":
    # 示例股票列表(实际使用时替换为关注的股票)
    symbols = ['AAPL', 'MSFT', 'GOOGL', 'BRK-B', 'JNJ', 'XOM', 'WMT', 'PG']
    
    # 创建策略实例并运行
    strategy = GrahamValueStrategy(symbols)
    results = strategy.run_screening()
    
    # 获取推荐
    strategy.get_recommendations(min_score=3)

这个实现包含了格雷厄姆价值投资的四个核心标准:低市盈率、低市净率、低负债率,以及股价低于净流动资产价值。代码使用yfinance获取实时财务数据,计算各项指标,并给出综合评分。你可以通过修改symbols列表来筛选自己关注的股票。

建议:实际投资前请结合更多基本面分析和风险评估。

回到顶部