请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3354235 新帖:68

沪深300历史估值低估买入策略

SCSDV_d发表于:5 月 10 日 02:37回复(1)

这是一个根据PE、PB在指数历史低估区间时买入,长期持有,然后在PE、PB处于历史高位时卖出的策略。

这个策略极其简单,适用于大部分宽基指数;

这个策略是跑不赢指数的,但是能让你极其安心的长期持有;

谨记:一切回测有效的策略都是看后视镜开车。回测仅仅是参考,不能预测未来。

谨记:成功概率不能预测,失败风险无法回避,历史周期不断重复,时刻抱有敬畏之心。

指数特点

背靠国运,不死鸟
长期上涨
成本低
不择股
容易量化
大道至简

低估不定期不定额策略
我们的策略制定原则:

可复现、可回测
排除人工干扰,机器拯救人类
落子无悔,买定离手
低估买,高估卖,没有机会不动
资金分为50份分批投入

买入条件
市场出现系统性低估机会可以买入
单一标的PE、PB 处于历史30%以下可以买入
PB处于历史30%以下,且PE<10 或 1/PE<十年期国债利率X2,可以买入

卖出条件
市场出现系统性高估机会可以卖出
单一标的PE、PB 处于历史70%以上可以卖出
1/PE<市场能找到的最小无风险收益率,可以卖出置换

简单持有
不符合买入,也不符合卖出条件,简单持有即可。

若市场利率缓慢下行,可简单买入短债基金持有,其他情况不动。

凯利公式控制仓位
采用银行螺丝钉的方法计算仓位;

策略特点:

这个策略的收益在很多人看来是非常垃圾的,我期望的比较乐观的情况是总资金4%-7%的年化收益

把这个策略看成是一个人的话,他超级胆小,超级吝啬,超级怕死,只有在他的把握非常非常大的时候,才敢抛出仅仅一个筹码。即使是2018年的钻石底,他买入也很少。

这个策略基本上建仓时间在3年以上,什么也不做的时间基本上5年以上。这段时间内,现金可以买入货基打底。所以这个策略的收益你可以再乐观的 3% ;

我相信一个策略带有其人格化,我相信世界上有许多极度胆小,不求暴富,只希望四平八稳取得微小的幸福的人,理所当然应该有这个极度简单,极度保守的策略来服务他们;

再重复说明一下: 这个策略不是为了高收益,不是为了跑赢指数,甚至在3-5年内,不是为了跑赢银行理财;而是让你长期持有!所谓长期,是5年,10年以上;最重要的是安全边际,是控制风险。 这个策略是我以极度保守思考的思路思考之后的结果,我个人有25%的仓位用这个策略慢慢建仓,如果持有现金换成货基,我期待长期年化6%~10%左右。 它是跑不赢指数的。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import bisect

import warnings
warnings.filterwarnings("ignore")

#指定日期的指数PE(市值加权)
def get_index_pe_date(index_code,date):
    stocks = get_index_stocks(index_code, date)
    q = query(valuation).filter(valuation.code.in_(stocks))
    df = get_fundamentals(q, date)
    df = df[df['pe_ratio'] > 0]
    if len(df) > 0:
        #pe = len(df)/sum([1/p if p>0 else 0 for p in df.pe_ratio])
        #pe = df['pe_ratio'].size/(1/df['pe_ratio']).sum()
        pe = df['circulating_market_cap'].sum()/(df['circulating_market_cap']/df['pe_ratio']).sum()
        return pe
    else:
        return float('NaN')

#指定日期的指数PB(市值加权)
def get_index_pb_date(index_code,date):
    stocks = get_index_stocks(index_code, date)
    q = query(valuation).filter(valuation.code.in_(stocks))
    df = get_fundamentals(q, date)
    df = df[df['pb_ratio']>0]
    if len(df)>0:
        #pb = len(df)/sum([1/p if p>0 else 0 for p in df.pb_ratio])
        #pb = df['pb_ratio'].size/(1/df['pb_ratio']).sum()
        pb = df['circulating_market_cap'].sum()/(df['circulating_market_cap']/df['pb_ratio']).sum()
        return pb
    else:
        return float('NaN')
    
#指数历史PEPB
def get_index_pe_pb(index_code):
    start='2011-1-1'
    end = pd.datetime.today();
    dates=[]
    pes=[]
    pbs=[]
    for d in pd.date_range(start,end,freq='W'): #频率为周
        dates.append(d)
        pes.append(get_index_pe_date(index_code,d))
        pbs.append(get_index_pb_date(index_code,d))
    d = {
            'PE' : pd.Series(pes, index=dates),
            'PB' : pd.Series(pbs, index=dates)
        }
    PB_PE = pd.DataFrame(d)
    return PB_PE


all_index = get_all_securities(['index'])
index_choose =['000016.XSHG',                        
               '000300.XSHG',
               '000902.XSHG',
               '000905.XSHG',
               '399106.XSHE',               
               '399316.XSHE',
               
               '000036.XSHG',
               '000037.XSHG',
               '000038.XSHG',
               '000039.XSHG',
               '000158.XSHG'
]


index_choose = [
    '000300.XSHG', # :'沪深300',    #000176.OF 嘉实沪深300增强
    '000905.XSHG', # :'中证500',    #000478.OF 建信中证500增强
    '000919.XSHG', #:'300价值',    #310398.OF 申万沪深300价值
    '000922.XSHG', #:'中证红利',   #100032.OF 富国中证红利
    '399702.XSHE', #:'深证F120',   #070023.OF 嘉实深F120基本面联接
    '399978.XSHE', #:'中证医药100',#001550.OF 天弘中证医药100
    '399812.XSHE',  #:'中证养老'    #000968.OF 广发中证养老指数
    '000932.XSHG', # 中证消费
]

df_pe_pb = pd.DataFrame()
frames =pd.DataFrame()
today = pd.datetime.today()

for code in index_choose:
    index_name = all_index.ix[code].display_name  
    print('正在处理: ', index_name)   
    df_pe_pb = get_index_pe_pb(code)    
    
    results=[]
    pe = get_index_pe_date(code, today)
    q_pes = [df_pe_pb['PE'].quantile(i / 10.0)  for i in range(11)]    
    idx = bisect.bisect(q_pes, pe)
    quantile = idx - (q_pes[idx] - pe) / (q_pes[idx] - q_pes[idx-1])   
    #index_name = all_index.ix[code].display_name
    results.append([index_name,
                    format(pe, '.2f'),
                    format(quantile * 10, '.2f')] + 
                    [format(q, '.2f')  for q in q_pes] + 
                    [df_pe_pb['PE'].count()])
    
    pb = get_index_pb_date(code, today)
    q_pbs = [df_pe_pb['PB'].quantile(i / 10.0)  for i in range(11)] 
    idx = bisect.bisect(q_pbs, pb)
    quantile = idx - (q_pbs[idx] - pb) / (q_pbs[idx] - q_pbs[idx-1])   
    #index_name = all_index.ix[code].display_name
    results.append([index_name,
                    format(pb, '.2f'),
                    format(quantile * 10, '.2f')] + 
                    [format(q, '.2f')  for q in q_pbs] + 
                    [df_pe_pb['PB'].count()])
    
    
    df_pe_pb['10% PE']=q_pes[1]
    df_pe_pb['50% PE']=q_pes[5]
    df_pe_pb['90% PE']=q_pes[9]
    df_pe_pb['10% PB']=q_pbs[1]
    df_pe_pb['50% PB']=q_pbs[5]
    df_pe_pb['90% PB']=q_pbs[9]

    plt.rcParams['font.sans-serif']=['SimHei']
    df_pe_pb.plot(secondary_y=['PB','10% PB','50% PB','90% PB'],
                  figsize=(14,8), title = index_name,
                  style=['k-.', 'k', 'g', 'y', 'r', 'g-.', 'y-.', 'r-.']) 
    
    columns=['名称', '当前估值', '分位点%', '最小估值'] + \
            [format(i * 10, 'd') + '%%' for i in range(1,10)] + \
            ['最大估值' , '数据个数']
    
    df= pd.DataFrame(data = results,
                     index = ['PE','PB'],
                     columns = columns)
    frames = pd.concat([frames, df])

frames  
正在处理:  沪深300
正在处理:  中证500
正在处理:  300价值
正在处理:  中证红利
正在处理:  深证F120
正在处理:  中证医药100指数
正在处理:  中证养老产业指数
正在处理:  中证消费
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
名称 当前估值 分位点% 最小估值 10%% 20%% 30%% 40%% 50%% 60%% 70%% 80%% 90%% 最大估值 数据个数
PE 沪深300 13.31 68.77 8.32 9.21 10.40 11.08 11.70 12.12 12.83 13.37 14.00 14.78 19.41 433
PB 沪深300 1.59 50.40 1.20 1.35 1.41 1.50 1.54 1.59 1.69 1.76 1.89 2.20 2.59 433
PE 中证500 21.30 10.47 15.12 21.19 23.49 24.37 25.52 27.04 31.11 33.30 36.31 38.81 67.82 433
PB 中证500 2.06 13.55 1.50 1.99 2.18 2.26 2.36 2.51 2.67 2.80 2.98 3.63 5.78 433
PE 300价值 9.24 44.10 6.36 6.91 8.20 8.71 9.05 9.52 9.92 10.24 10.80 11.68 14.28 433
PB 300价值 1.14 23.32 0.98 1.07 1.12 1.17 1.23 1.30 1.36 1.43 1.56 1.74 2.16 433
PE 中证红利 8.77 32.36 6.43 6.87 8.01 8.67 9.08 9.39 9.83 10.21 10.63 11.50 14.16 433
PB 中证红利 1.16 30.49 1.00 1.07 1.12 1.16 1.22 1.28 1.36 1.45 1.59 1.79 2.23 433
PE 深证F120 17.30 52.59 12.08 13.86 14.68 15.43 16.17 17.11 17.83 18.80 19.64 21.53 30.04 433
PB 深证F120 2.33 64.91 1.57 1.79 1.89 1.96 2.07 2.19 2.26 2.40 2.54 2.91 3.71 433
PE 中证医药100指数 31.47 30.57 22.67 26.23 28.25 31.40 32.60 33.32 33.90 34.89 35.73 38.33 60.74 422
PB 中证医药100指数 4.04 27.05 3.06 3.62 3.91 4.10 4.19 4.26 4.35 4.44 4.61 5.18 7.61 422
PE 中证养老产业指数 25.41 55.68 17.92 19.86 20.92 22.06 22.92 24.74 25.92 26.57 27.34 28.96 37.64 254
PB 中证养老产业指数 3.35 70.55 2.50 2.73 2.82 2.90 2.94 3.04 3.25 3.34 3.51 3.81 4.84 254
PE 中证消费 31.72 82.86 15.09 16.80 19.44 22.46 23.87 25.25 26.39 28.49 30.61 34.48 45.43 433
PB 中证消费 6.35 92.22 2.76 3.22 3.43 3.62 3.92 4.25 4.74 5.12 5.46 6.07 7.35 433
 

全部回复

0/140

量化课程

    移动端课程