暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

格雷厄姆法代码回测-价值投资鼻祖

量化分析之路 2020-04-04
886

本杰明•格雷厄姆(BenjaminGraham , 1894^1976年),美国经济学家和投资 思想家,投资大师,〃现代证券分析之父〃,价值投资理论奠基人。

格雷厄姆是巴菲特就读哥伦比亚大学经济学院的硏究生导师,被巴菲特膜拜为其一生的精神导师。

谈到价值投资 就要说市盈率p/e 

市盈率是指股票价格除以每股收益(每股收益,EPS)的比率

举个简单的例子,现在有一家公司叫做北京烤鸭”发行了100股的股票,每张股票的价格是10元。公司去年盈利不错,一年挣了100块钱。

公司的市值=股价×股票数=10×100=1000元;

去年每股盈利=去年盈利÷股票数=100÷100=1/股。这也就很容易计算出北京烤鸭这个公司的市盈率,

P/E=股价÷每股盈利=10÷1=10。也就是说,北京烤鸭这个公司的市盈率是10倍。

我们计算出来了北京烤鸭的市盈率是10倍,那这个数据代表的实质含义是什么呢?

这个数据代表着,我投资10块钱买了这家公司的一张股票,按公司去年的盈利计算,折算到每张股票的利润是1块钱。如果这家公司的所有利润都拿来给股东分红的话,我的这张股票就可以分到1块钱,也就是10年我就可以回本了。

投资的年化收益率刚好是10%,也就是市盈率的倒数。

  企业挣得钱肯定不会都用来给股东分红,还会有部分留作企业发展的资金。应该没有哪个上市公司会把利润100%拿来分红

但这并不影响这个理论(市盈率是投资收益的倒数),因为用作公司发展的部分资金,会促进公司的发展,而公司的发展在长远来看也是会转化成股东的投资收益的

稀释每股收益简单的讲就是上市公司1亿股,去年净利润1000万。每股收益0.1元。今年分红方案为,10送10,就会增加股数,变为2亿股,每股收益就变为0.05元了,这就叫稀释每股收益

PEG指标(市盈率相对盈利增长比率)它弥补了PE对企业动态成长性估计的不足。当时他在选股的时候就是选那些市盈率较低,同时它们的增长速度又是比较高的公司,这些公司有一个典型特点就是PEG会非常低。其计算公式是:PEG=PE/(企业年盈利增长率*100)

PE)仅仅反映了某股票当前价值,PEG则把股票当前的价值和该股未来的成长联系了起来 。比如一只股票当前的市盈率为20倍,其未来5年的预期每股收益复合增长率为20%,那么这只股票的PEG就是1。当PEG等于1时,表明市场赋予这只股票的估值可以充分反映其未来业绩的成长性。

        代码回测 策略步骤,  

        1:得到HS300的股票流通市值    (negMarketValue)

      2:根据流程市值求出流通股  negMarketValue /closePrice

        3:根据公式求出HS300的股票估算成长价值 (value)

     流通股(negMarketValue*稀释每股收益('DilutedEPS'*8.5+2*复合增长率(EGRO

        4 :根据流通市值与成长价值的差 (under_value)

        算出策略的买卖时间 获取收益回测

第一部分 准备部分

import numpy as np
import pandas as pd
import talib


start = '2018-01-01' # 回测起始时间
end = '2020-01-01' # 回测结束时间
universe = set_universe('HS300') # 证券池,支持股票、基金、期货、指数四种资产
benchmark = 'HS300' # 策略参考标准
freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
refresh_rate = 10 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟

# 配置账户信息,支持多资产多账户
accounts = {
'fantasy_account': AccountConfig(account_type='security', capital_base=10000000)
}


##买入卖出阈值
Max_Position = 1000000


def initialize(context):
pass


def handle_data(context):
buy_list = stock_sellection_Graham_growth_stock(context)
trading(buy_list,context)

        
第二部分 筛选股票 当成长价值>流通市值 我们觉得股票被低估

    加入购买备选  

当成长价值<流通市值 我们觉得股票被高估 

 如有持仓 卖出

def  stock_sellection_Graham_growth_stock(context):
'''策略 成长价值 = 当期(正常)利润*(8.5 + 两倍的预期5年增长率)
成长价值> 市值 买入 反之 卖出'''
#获取数据 通用部分
previous_date = context.previous_date
previous_date = previous_date.strftime('%Y%m%d')
account = context.get_account('fantasy_account')
current_universe = context.get_universe( exclude_halt=True)

#获取因子 5年收益增长率 收盘价 稀释每股收益
GGV_EPS_EGRO = DataAPI.MktStockFactorsOneDayGet(tradeDate=previous_date, secID=current_universe, field=['secID','DilutedEPS','EGRO'], pandas='1')
GGV_closePrice =DataAPI.MktEqudGet(secID=current_universe, tradeDate=previous_date, field=['secID','closePrice','negMarketValue'], pandas='1')

GGV_EPS_EGRO = GGV_EPS_EGRO.set_index(['secID'])
GGV_closePrice = GGV_closePrice.set_index(['secID'])


#数据处理部分 #neg 流通市值
GGV_closePrice['Maketable_Volume'] = GGV_closePrice['negMarketValue'] / GGV_closePrice['closePrice'] #流通市值量

GGV_EPS_EGRO['value'] = GGV_closePrice['Maketable_Volume']* GGV_EPS_EGRO['DilutedEPS']*(8.5+2*GGV_EPS_EGRO['EGRO'])

under_value = GGV_EPS_EGRO['value'] - GGV_closePrice['negMarketValue']
buy_list =under_value[under_value>0].index

return list(buy_list)

第三部分 执行买卖

def trading(buy_list,context):
account = context.get_account('fantasy_account')
current_universe = context.get_universe( exclude_halt=True)
security_position = account.get_positions()
cash = account.cash

for sec in current_universe:
if sec not in buy_list and sec in security_position:
account.order_pct_to(sec,0)

d = min(len(buy_list),int(cash)//Max_Position)

for sec in buy_list[:d]:
if sec not in security_position:
account.order(sec,Max_Position/ context.current_price(sec))

我跑了一下较长时间回测  大部跑赢大盘  很牛逼


不过买卖持仓大部分是银行股   大部分人不太喜欢  


文章转载自量化分析之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论