第四章:经典量化策略集锦(第七篇:向彼得林奇投资大师学习 PEG选股 )

导语:投资大师彼得·林奇有过一个著名的论断:任何一家公司股票如果定价合理的话,市 


盈率就会与收益增长率相等。本篇内容将为大家讲述彼得·林奇推广的PEG 选股策略。 






一、策略阐述 






彼得·林奇 






    彼得·林奇 (Peter Lynch )生于 1944 年1 月19 日, 是一位卓越的股票投资家和证券投资 


基金经理,  曾被 《时代杂志》评为首席基金经理。1977 年至1990 年, 在彼得·林奇管理麦哲伦 


基金的 13 年间, 基金规模大幅扩增,  由2000 万美元成长至140 亿美元!他对共同基金的贡献, 


就像是乔丹之于篮球,邓肯之于现代舞蹈。他不是人们日常认识中的那种脑满肥肠的商人, 


他把整个比赛提升到一个新的境界,他让投资变成了一种艺术。 






    彼得·林奇一直以他的选股能力而著称,他有一句名言:只要用心对股票做一点点研究, 


普通投资者也能成为股票投资专家,并且在选股方面的成绩能像华尔街的专家一样出色。 






PEG 指标 






         围绕着彼得·林奇的著名论断,我们来谈谈PEG 指标。 


    论断:任何一家公司股票如果定价合理的话,市盈率就会与收益增长率相等。 


     


    了解基础指标:每股收益、市盈率和每股收益增长率。 






    每股收益(EPS) :是税后利润与股本总数的比率。传统的每股收益指标计算公式为:每 


股收益=期末净利润÷期末股份总数。 






    每股收益增长率(G) :论断中的收益增长率指的就是每股收益的增长率,同比增长率= 


{(本期每股收益-上年同期每股收益) /上年同期每股收益的绝对值}*100%。 






    市盈率(PE) :是当前股价与每股收益的比值。市盈率对个股、类股及大盘都是很重要参 


考指标。任何股票若市盈率大大超出同类股票或是大盘,都需要有充分的理由支持,而这往 


往离不开该公司未来盈利率将快速增长这一重点。一家公司享有非常高的市盈率,说明投资 


人普遍相信该公司未来每股盈余将快速成长,以至数年后市盈率可降至合理水平。一旦盈利 


增长不如理想,支撑高市盈率的力量无以为继,股价往往会大幅回落。  






    PEG 指标由上述基础指标演变而来,计算公式为:PEG=PE/G ,其中PE 为市盈率,G 


为每股收益增长率。PE 代表投资者对公司每股收益增长预期,而G 代表公司真实的每股收 


益增长预期。从合理定价的角度看,个股的市盈率与每股收益增长率应该保持相等。如果 


PEG 小于 1,股价是偏低的,反之则偏高。 




----------------------- Page 103-----------------------


彼得·林奇 PEG 选股 






    PEG 选股策略:计算全市场股票的 PEG 指标,按PEG 值从小到大排序,选择前10 只股 


票作为持仓 






    就这么简单吗?不是的,PEG 指标选股具有局限性: 






    1.PEG 指标不合适用于周期性行业选股,因此需要剔除周期性行业内的股票。由于周期 


性行业非常多,本文选取 5 个非周期性行业进行 PEG 选股:食品饮料,医药生物,纺织服 


装,商业贸易,交通运输 。 






    2.价值型股票与成长性股票不同,价值型股票由于其成长空间有限,导致价值型股票的 


PEG 往往会低于 1,以反映低业绩增长的预期。所有直接使用 PEG 指标会出现一边倒现象。 


更何况PEG 选股策略主要意图在于挑选出优质成长股。对于个股是否为成长型股票的定义 


方法并不固定,因此本文采用以下简单粗暴定义(ps: 同学们掌握后可以在此处优化哦!)。 






    3.无法衡量公司的收益增率可持续性,考虑到公司可能出现的扭亏为盈、特殊情况导致 


单季度收益增率高达1000%+现象,我们需要剔除收益增长率超过 40% 的个股,因其增长不 


可持续。 






    成长型股票池:对所有非周期性行业个股,采用净利润复合增长率、销售净利率两个指 


标,选取当季两个指标都在前50%的股票。 






    第一步:获取成长型股票池。 






    第一步:每隔20 个交易 日,获取股票池内个股的 PE 和 G 值,剔除G 大于40 的个股, 


然后计算成长型股票池的PEG 指标。 






    第二步:按PEG 值从小到大排序,选择前5 只股票作为持仓 






    以下为策略实现的基本信息: 


    策略实现难度:3 


    实现过程中所需要用到的API 函数,ps:通过 MindGo 量化交易平台 API 文档快速掌握: 






需要用到的API 函数     功能 






get_industry_stocks 获取行业指数成分股 






get_fundamentals 获取财务数据 




----------------------- Page 104-----------------------


二、代码示意图 




----------------------- Page 105-----------------------


三、编写释义 






    彼得·林奇 PEG 选股核心是获取成长性股票,本篇内容中粗糙定义了成长型股票,建议 


初学者前往研究环境操作,并能在此基础上加入 自己的一些想法。 


         以下是作者实现过程中,研究环境的代码草稿,分享给同学们。 






#=================获取非周期性行业个股 


def non_cyclical_industry(date): 


    #确定申万一级非周期行业 


    non_cyclical_industry_list =['S36',# 申万一级:纺织服装 


                                 'S45',# 申万一级:商业贸易 


                                 'S37',# 申万一级:医药生物 


                                 'S34',# 申万一级:食品饮料 


                                 'S42']# 申万一级:交通运输 


    stock_list=[] 


    #通过行业成分股获取函数,获取到股票池。 


    for i in non_cyclical_industry_list:        


        stk=get_industry_stocks(i,date) 


        for i in stk: 


            stock_list.append(i) 


    return stock_list 


date='20180125' 


stk=non_cyclical_industry(date) 


stock_num = int(len(stk)*0.5) 


#获取净利润增长率和销售毛利率 


q =  


query(valuation.symbol,growth.net_profit_compound_growth_ratio,profit.net_profit_margin_on_sa 


les).filter(valuation.symbol.in_(stk)) 


basic = get_fundamentals(q, date = date) 


for i in ['growth_net_profit_compound_growth_ratio','profit_net_profit_margin_on_sales']: 


    basic = pd.DataFrame(basic).sort_values(by =i, ascending=False) 


    stockmax=list(basic.iloc[:stock_num]['valuation_symbol']) 


    stk=list(set(stk)&set(stockmax)) 


q =  


query(valuation.symbol,valuation.pe_ttm,growth.basic_eps_year_growth_ratio).filter(valuation.sym 


bol.in_(stk)) 


basic = get_fundamentals(q, date = '20180125') 


basic['PEG']=basic['valuation_pe_ttm']/basic['growth_basic_eps_year_growth_ratio'] 


basic = basic[basic['PEG']>0] 


basic = basic[basic['growth_basic_eps_year_growth_ratio']<50] 


basic = pd.DataFrame(basic).sort_values(by ='PEG', ascending=True) 


basic.index=basic['valuation_symbol'] 


del basic['valuation_symbol'] 


basic 




----------------------- Page 106-----------------------


运行结果: 




----------------------- Page 107-----------------------


四、最终结果 






策略回测区间:2014.01.01-2018.01.31 


回测资金:1000000 


回测频率:日级 


回测结果:红色曲线为策略收益率曲线,蓝色曲线为对应的基准指数收益率曲线 






策略源代码: 






import pandas as pd 


import numpy as np 


#==========================初始化函数================================ 


def initialize(account): 


    set_benchmark('399333.SZ')#设置中小板为基准 


    g.day = 0 #记录运行天数 


    g.tradeday = 20 #调仓频率 


    g.stock = [] #储存上期的股票池 


    g.trade = False #是否调仓的开关 


    g.stocknum = 10 #持仓数量 


    pass 


#==========================盘前运行================================ 


def before_trading_start(account,data): 


    #判断是否调仓 


    if g.day%g.tradeday==0: 


        g.trade=True 


    else: 


        g.trade=False 


    g.day=g.day+1 




----------------------- Page 108-----------------------


#===========================盘中交易============================== 


def handle_data(account, data): 


    if g.trade==True: 


        #获取选股结果 


        needstock_list = peg() 


        #获取上期持仓个股 


        holdstock_list = list(g.stock) 


        #确定本期需要卖出的个股 


        sell_list = list(set(holdstock_list)-set(needstock_list)) 


        #执行卖出操作,运用for 循环,逐个操作。 


        for s in sell_list: 


            order_target(s,0) 


        #确定本期需要买入的个股,其余即为继续持仓的个股 


        buy_list=[] 


        for i in needstock_list: 


            if i in holdstock_list: 


                pass 


            else: 


                buy_list.append(i) 


        #确定可用资金,平分分配至需买入的个股 


        n=len(buy_list) 


        cash=account.available_cash/n 


        #执行买入操作 


        for s in range(0,n,1): 


            stock=list(buy_list)[s] 


            order_value(stock,cash) 


        #操作完毕,将选股结果放到上期股票池储存变量中,以备下次使用。 


        g.stock = frozenset(needstock_list) 


    else: 


        pass 


#===================选股函数================================ 


def peg(): 


    date=get_last_datetime().strftime('%Y%m%d') 


    #获取非周期行业股票。 


    stock_list1=non_cyclical_industry(date) 


    #获取成长型股票池 


    stock_list2=growth_list(stock_list1,date) 


    #获取PEG 最小的 10 只股票 


    q =  


query(valuation.symbol,valuation.pe_ttm,growth.basic_eps_year_growth_ratio).filter(valuation.sym 


bol.in_(stock_list2)) 


    basic = get_fundamentals(q, date = date) 


    basic['PEG']=basic['valuation_pe_ttm']/basic['growth_basic_eps_year_growth_ratio'] 


    basic = basic[basic['PEG']>0] 


    basic = basic[basic['growth_basic_eps_year_growth_ratio']<=40] 


    basic = pd.DataFrame(basic).sort_values(by ='PEG', ascending=True) 


    basic.index=basic['valuation_symbol'] 




----------------------- Page 109-----------------------


    #获取股票的代码 


    needstock_list=[] 


    for s in range(0,g.stocknum,1): 


        needstock_list.append(list(basic.index)[s]) 


    return needstock_list 


#==================获取成长型股票池================== 


def growth_list(stk,date): 


    stock_num = int(len(stk)*0.5) 


    #获取净利润增长率和销售毛利率 


    q = query(valuation.symbol, 


                  growth.net_profit_growth_ratio, 


                  profit.net_profit_margin_on_sales).filter(valuation.symbol.in_(stk)) 


    basic = get_fundamentals(q, date = date) 


    for i in ['growth_net_profit_growth_ratio','profit_net_profit_margin_on_sales']: 


        basic = pd.DataFrame(basic).sort_values(by =i, ascending=False) 


        stockmax=list(basic.iloc[:stock_num]['valuation_symbol']) 


        stk=list(set(stk)&set(stockmax)) 


    return stk 


     


#=================获取非周期性行业个股 


def non_cyclical_industry(date): 


    #确定申万一级非周期行业 


    non_cyclical_industry_list =['S36',# 申万一级:纺织服装 


                                 'S45',# 申万一级:商业贸易 


                                 'S37',# 申万一级:医药生物 


                                 'S34',# 申万一级:食品饮料 


                                 'S42']# 申万一级:交通运输 


    stock_list=[] 


    #通过行业成分股获取函数,获取到股票池。 


    for i in non_cyclical_industry_list:        


        stk=get_industry_stocks(i,date) 


        for i in stk: 


            stock_list.append(i) 


    return stock_list 




----------------------- Page 110-----------------------

你可能感兴趣的:(Python量化投资)