彼得•林奇GARP股票投资策略及源码

1
回复
7418
查看
[复制链接]

196

主题

140

回帖

1444

积分

管理员

积分
1444
来源: 2019-8-15 06:58:12 显示全部楼层 |阅读模式
彼得•林奇被称为全世界最成功的股票投资家和证券投资基金经理之一。在 1997—1990 年这 13年之内,林奇作为麦哲伦基金(Megellan Fund)的基金经理人创造了惊人的业绩——13 年间的平均复利报酬率达 29%并且基金规模由最初的 2000 万美元成长至 140 亿美元。因此,彼得•林奇也被称为“全球最佳选股者”。

19081503.jpg

GARP(Growth at a Reasonable Price)是一种混合的股票投资策略,其产生的基础是成长投资策略和价值投资策略,其核心思想是以较低价格买入成长性较高的股票,该策略的代表人物正是是彼得•林奇。GARP 投资策略包括两方面,利用成长性原理选择股票和对成长性股票进行价值投资。

首先是利用成长性原理选择股票。投资成长股也即投资于处于成长期的好公司。好公司可以通过业务、业绩、管理层来评估。公司有初创期、成长期、成熟期、衰退期四个生命周期,投资成长股在选好公司的前提下需要关注公司所处的发展阶段,即应该投资于处于成长期的公司。

其次是对成长性股票的价值投资。价值投资的核心思想是每一个公司都有其“内在价值”,这种内在价值可以用一定的方法评估和测定,内在价值由公司的基本面因素决定,在一段时期内相对比较稳定,内在价值是价值投资的基础。衡量企业内在价值的方法主要是现金流量折现法,此外还可以用市盈率、市净率等衡量企业的相对价值。股票的价格和供求关系相关,受到人心理因素的影响,总是处于波动状态,这种价格的波动是围绕价值进行的,长期来看是在内在价值回归的。这种波动所带来的机会和风险可以用戴维斯效应来理解。

策略说明:

参考申万研报《申万大师系列价值投资篇之七:彼得.林奇基层调查选股法》,文章【大师系列】彼得.林奇基层调查选股法对大师的思想进行了一些量化。

具体量化了以下5条:

1.公司的资产负债率小于等于 25%

这一条对公司的负债水平做出了要求。较低的资产负债率可以让公司灵活的应对各种突发事件可能对公司带来的冲击。

2.公司每股净现金大于 0

公司的每股现金流为正值,表示公司处于建康的营运状态中,每股收益的含金量很高。

3.当前股价与每股自由现金流量比小于 10(市现率)

这一规则对股票的估值水平提出了要求,并以公司的财务灵活性指标作为估值的基准。

4.在所有股票中取市盈率排倒数30%的股票(首先PE必须大于0)

5.PEG=市盈率/净利润增长率<0.5

这一规则说明市盈率的增长不及盈利的增长,股票价格处于相对低位,体现了彼得.林奇偏好成长兼具价值股票的投资风格。

回测参数声明:

时间:2016-01-01至2018-01-01

调仓频率:1月

基准指数:中证800指数(SHSE.000906)

股票池:中证800指数(SHSE.000906)成分股

滑点:0.0001

手续费:0.0001

数据获取:
19081506.png

可以看出,策略模型时而有效,时而无效,最终没有跑赢基准指数。GARP策略在原来多因子策略的基础上,又加入了因子值域的限制,虽然增加选股的准确性,但也会带来过拟合的问题,我们在本策略中,依然使用彼得林奇的因子及参数设置,这定会造成策略的无效性。但是彼得林奇确实为我们提供了新的选股思路。那么,在A股市场,GARP策略的运用优势究竟有哪些呢?

首先,GARP策略是一种混合偏均衡策略,追求最佳的风险回报比。该策略不仅可以通过价值和成长的相对均衡,规避风格轮换风险;也可以通过个股和行业配置的相对均衡,规避个股风险和行业配置风险。在A股市场,由于基金管理者普遍存在追求“第一”的心理,中小投资者也普遍存在追求“一夜暴富”的心理,显著的羊群效应和股价过度反应导致了A股市场存在着大量错误定价的股票。另一方面,个股的价值回归过程往往也因此异常激烈甚

至矫枉过正。在A股这样高波动的市场之中,GARP策略损有余而补不足,通过自我平衡,以价值标尺筛除了那些泡沫股;又以成长标尺遴选出那些优势股,有效地规避了市场风险。

其次,GARP策略也是一种守正出奇的策略。所谓均衡,不是简单的50对50,而是一种针对市场不同风险收益比率的灵活机动。在多数情况下,“守正”虽然可能是一种常态,但是在成长股泡沫疯狂滋长时,GARP策略可以逐步降低成长股的配置比例;在价值股极度低估时,GARP策略可以逐步加大价值股的配置比例。甚至在极端情况下,GARP策略可以演化为单纯的价值策略或者成长策略。GARP策略正是以守正出奇的方式,试图谋求风险最小情况下的最大投资回报。


附:GARP股票投资策略源码
  1. # coding=utf-8
  2. from __future__ import print_function, absolute_import, unicode_literals
  3. from gm.api import *
  4. from sklearn import preprocessing

  5. '''
  6. 策略思路:
  7. 1、公司的资产负债率小于等于 25%
  8. 2、公司每股净现金大于 0
  9. 3、当前股价与每股自由现金流量比小于 10(市现率)
  10. 4、在所有股票中取市盈率排倒数30%的股票(首先PE必须大于0)
  11. 5、PEG=市盈率/净利润增长率<0.5
  12. 回测数据:SHSE.000906的成份股
  13. 回测时间:2016-01-01 08:00:00到2018-01-01 16:00:00
  14. '''


  15. def init(context):
  16.     # 每月第一个交易日的09:40 定时执行algo任务
  17.     schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')


  18. def algo(context):
  19.     # 获取上一个交易日的日期
  20.     last_day = get_previous_trading_date(exchange='SHSE', date=context.now)
  21.     # 获取沪深300成份股
  22.     stock800 = get_history_constituents(index='SHSE.000906', start_date=last_day,
  23.                                                 end_date=last_day)[0]['constituents'].keys()
  24.     # 获取当天有交易的股票
  25.     not_suspended = get_history_instruments(symbols=stock800, start_date=last_day, end_date=last_day)
  26.     not_suspended = [item['symbol'] for item in not_suspended if not item['is_suspended']]
  27.     df = get_fundamentals(table='deriv_finance_indicator', symbols=not_suspended, start_date=last_day, end_date=last_day,
  28.                            fields='ASSLIABRT,NCFPS,NPGRT', df=True)
  29.     fin=get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended, start_date=last_day, end_date=last_day,
  30.                            fields='PCLFY,PELFY', df=True)
  31.     df['PCLFY']=fin['PCLFY']
  32.     df['PELFY'] = fin['PELFY']

  33.     # 除去空值
  34.     df = df.dropna()
  35.     df['PEG']=df['PELFY']/df['NPGRT']
  36.     df.index=df.symbol
  37.     del df['symbol'],df['pub_date'],df['end_date']
  38.     print(df)
  39.     # 选出PEG小于0.5的部分
  40.     df = df[df['PEG'] < 0.5]
  41.     # 选出债务总资产比小于0.25的部分
  42.     df = df[df["ASSLIABRT"] < 25]
  43.     # 选出每股净现金大于 0的部分
  44.     df = df[df["NCFPS"] > 0]
  45.     # 选出市盈率大于零的部分
  46.     df = df[df['PELFY'] > 0]
  47.     # 选出市现率小于10的部分
  48.     df = df[df['PCLFY'] < 10]

  49.     print(df)
  50.     # 剔除市盈率较高的股票(即剔除3分位数以后的股票)

  51.     if len(df)<4:
  52.         symbols_pool = list(df.index)
  53.     else:
  54.         df = df[(df['PELFY'] < df['PELFY'].quantile(0.3))]
  55.         symbols_pool = list(df.index)
  56.     print(symbols_pool)
  57.     order_close_all()

  58.     long=len(symbols_pool)
  59.     if long==0:
  60.         return
  61.     # 获取股票的权重
  62.     percent = 1 / long
  63.     # 买在标的池中的股票
  64.     for symbol in symbols_pool:
  65.         order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
  66.                              position_side=PositionSide_Long)
  67.         #print(symbol, '以市价单调多仓到仓位', percent)


  68. if __name__ == '__main__':
  69.     '''
  70.     strategy_id策略ID,由系统生成
  71.     filename文件名,请与本文件名保持一致
  72.     mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
  73.     token绑定计算机的ID,可在系统设置-密钥管理中生成
  74.     backtest_start_time回测开始时间
  75.     backtest_end_time回测结束时间
  76.     backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
  77.     backtest_initial_cash回测初始资金
  78.     backtest_commission_ratio回测佣金比例
  79.     backtest_slippage_ratio回测滑点比例
  80.     '''
  81.     run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',
  82.         filename='GARP.py',
  83.         mode=MODE_BACKTEST,
  84.         token='c395247a76e8a5caeee699d668d6f550213bc418',
  85.         backtest_start_time='2016-01-01 08:00:00',
  86.         backtest_end_time='2018-01-01 16:00:00',
  87.         backtest_adjust=ADJUST_PREV,
  88.         backtest_initial_cash=10000000,
  89.         backtest_commission_ratio=0.0001,
  90.         backtest_slippage_ratio=0.0001)

复制代码


本文来自掘金量化团队



回复

使用道具 举报

95

主题

18

回帖

515

积分

高级会员

积分
515
2019-8-15 08:00:39 来自手机 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
关注微信