单因子PEG选股策略
导语
彼得 林奇的PEG策略:
投资大师彼得·林奇(Peter Lynch)有过一个著名的论断:任何一家公司股票如果定价合理的话,市盈率就会与收益增长率相等
PEG概念解析
- EPS(Earnings Per Share)表示每股收益(一般按年计算)
EPS = \frac{increment per year}{stocknumbers}
- PE(Price to Earning Ratio)表示市盈率,是当前股价(P)相对每股收益(EPS)的比值:
PE = \frac{P}{EPS}
市盈率反映的是股票的投资回报能力,市盈率越低,代表股票的价值越低或者股票的每股收益更高
- G(Growth Rate of Expected Profit)表示企业的收益增长率:
G = \frac{EPS_{this year}-EPS_{last year}}{EPS_{last year}}
- PEG计算公式:
PEG = \frac{PE}{G*100}
将公式变换一下可以得到:
PEG = \frac{1}{100}*P*\frac{EPS_{last year}}{(EPS_{this year}-EPS_{last year})*EPS}
上面的式子表明PEG和股价成正相关,所以PEG越高表明股价有被高估的可能,相反则表明股价有被低估的可能,可以考虑买入
PEG的原理很简单,并不是一个很复杂的策略,市盈率低代表该公司要么股价低要么盈利能力强,而收益增长率高则代表该公司的盈利能力强,如果在这个时候该公司的具有较低的市盈率则表明该公司的股价已经被严重低估,所以按照PEG策略的思想,PEG的值越低越好
PEG策略虽然简单并且比较符合理论情况,但是在实际使用过程中得到的效果并不是十分的出色,这里面主要有两个原因:1.公司的盈利能力不能简单的预测,可能今年公司盈利能力很强,但是第二年公司就出现盈利大幅下滑;2.这个策略只是一个简单的单因子选股择时策略,而且没有仓位控制和止损策略相配合,在市场环境较差的时候公司的基本面并不能和股价相配合,所以该策略对熊市的抵御能力较差
PEG策略源码
import pandas as pd
"""
----------------------------
回测前
----------------------------
"""
def initialize(context):
set_params()
set_variables()
set_backtest()
def set_params():
g.tc = 15
g.num_stocks = 10
def set_variables():
g.days = 0
g.if_trade = False
def set_backtest():
set_option('use_real_price',True)
log.set_level('order','error')
"""
----------------------------
开盘前
----------------------------
"""
def before_trading_start(context):
if g.days%g.tc == 0:
g.if_trade = True
set_slip_fee(context)
g.stocks = get_index_stocks('000300.XHSG')
g.feasible_stocks = set_feasible_stocks(g.stocks,context)
g.days += 1
def set_feasible_stocks(initial_stocks,context):
paused_info = []
current_data = get_current_data()
for i in initial_stocks:
paused_info.append(current_data[i].paused)
df_paused_info = pd.DataFrame({'paused_info':paused_info},index = initial_stocks)
unsuspened_stocks =list(df_paused_info.index[df_paused_info.paused_info == False])
return unsuspened_stocks
def set_slip_fee(context):
set_slippage(FixedSlippage(0))
dt = context.current_dt
if dt>datetime.datetime(2013,1,1)
set_commission(PerTrade(buy_cost=0.0003,sell_cost=0.0013,min_cost=5))
elif dt>datetime.datetime(2011,1, 1):
set_commission(PerTrade(buy_cost=0.001, sell_cost=0.002, min_cost=5))
elif dt>datetime.datetime(2009,1, 1):
set_commission(PerTrade(buy_cost=0.002, sell_cost=0.003, min_cost=5))
else:
set_commission(PerTrade(buy_cost=0.003, sell_cost=0.004, min_cost=5))
"""
----------------------------
每天交易时
----------------------------
"""
#每天回测时做的事情
def handle_data(context,data):
#1.如果当天可以买入则列出待买入的股票和待卖出的股票
#2.进行买入和卖出操作
#3.设置可买入状态为False
if g.if_trade == True:
list_to_buy = stocks_to_buy(context)
list_to_sell = stocks_to_sell(context,list_to_buy)
sell_operation(list_to_sell_ buy_operation(context,list_to_buy)
g.if_trade = False
# 1.获得PEG值列表
# 2.获得买入信号
# 3.获得卖出信号
def get_PEG(context,stock_list):
PEG_query = query(valuation.code,valuation.pe_ratio,indicator,inc_net_profit_year_on_year).filter(valuation.code.in_(stock_list))
df = get_fundamentals(PEG_query)
df_growth = df[(df.pe_ration>0)&df.inc_net_profit_year_on_year>0)]
df_growth.dropna()
series_PE = df_growth.ix[:,'pe_ratio']
series_G = df_growth.ix[:,'inc_net_profit_year_on_year']
series_PEG = series_PE/series_G
series_PEG.index = df_growth.ix[:,0]
df_PEG = pd.DataFrame(series_PEG)
return df_PEG
def stocks_to_buy(context):
list_to_buy = []
df_PEG = get_PEG(context,g.feasible_stocks)
df_sorted_PEG = df_PEG.sort(columns='series_PEG',ascending=[1])
for i in range(g.num_stocks):
if df_sort_PEG.ix[i,0] < 0.5:
list_to_buy.append(df_sort_PEG.index[i])
return list_to_buy
def stocks_to_sell(context,list_to_buy):
list_to_sell=[]
for stock_sell in context.portfolil.positions:
if stock_sell not in list_to_buy:
list_to_sell.append(stock_sell)
return list_to_sell
def sell_operation(list_to_sell):
for stock_sell in list_to_sell:
order_target_value(stock_sell,0)
def buy_operation(context,list_to_buy):
for stock_sell in list_to_buy:
g.capital_unit = context.portfolio.portfolil_value/len(list_to_buy)
for stock_buy in list_to_buy:
order_target_value(stock_buy,g.capital_unit)
"""
----------------------------
每天收盘后
----------------------------
"""
def after_trading_end(context):
return
上面的策略很简单,具体步骤可以看下表:
时间 | 操作1 | 操作2 | 操作3 |
---|---|---|---|
回测前 | 初始化参数 | 初始化变量 | 初始化变量 |
开盘前 | 设置调仓信息 | 设置可选股票 | 设置滑点和手续费 |
交易时 | 获得PEG表 | 获取买入和卖出stock_list | 进行买入和卖出操作 |
收盘后 |