这本书加深了我对股票长期投资方面的认知,作者指出了一些投资陷阱,比如传统观点追求高增长率是合理的,但作者指出这是一件高风险低收益的事。由于作者都是用美股做实验的,出于兴趣,我也测试A股的情况,后面会给出一些A股的测试结果。
纵览全书,全文分为5个部分,前两部分阐述了投资者容易陷入的两个陷阱:追求高增长率和高估新事物,接着说明股东的收益应该来自哪里,然后展望未来,探讨人口危机和未来全球经济强国的转变,最后给出可供参考的投资组合策略。
下面按照书籍顺序摘取了作者的重要思想:
增长率陷阱诱使投资者为那些促进创新并带动经济扩张的产业和公司付出过多的资金。但根据美股过去业绩表明最好的投资往往出现在正在萎缩的产业和发展缓慢的国家。
为什么呢?因为大家都对创新有过高的热情,导致这样的公司往往容易被高估预期,而且在这些产业里只有极少数的大赢家成功了。即使在成功的情况下,创新带来的高收益也容易流向创业者和帮助销售股票的投资银行家等,当然消费者也获得了更好的产品,而非单个投资者。
以美股过去70年为例,石油早期占份额最高,而现在却是科技,也就是说科技是新兴行业,石油是萎缩的行业。但是以IBM和新泽西石油两家公司为例,收益增长率方面IBM过去业绩增长率确实一直高于新泽西石油。但是石油的投资者回报收益过去却超过IBM。原因就是IBM定价太高,而新泽西石油却便宜多了,并且股利率也更高,这样每年用获得的股利再投资,长期就可以获得更高的收益。
作者对过去标普500指数中的股票做了研究,发现以下结论:
以上说明不断追求新兴股票却可能降低投资者的收益率,所以投资者应该慎重。
投资者应该能区分这两个概念:市场价值与投资者收益;市场价值是股票数量*每股价格,投资者收益是每股价格变化加上股利。
对长期投资者来说,股利才是收益的主要来源。从这来说,期间长期持有的股票价格下跌更利于投资者用相同的股利购买到更多的股票。股票的长期收益并不依赖于实际的利润增长情况,而是取决于实际的利润增长与投资者预期的利润增长之间存在的差异。对于获得的股利现金,最好的办法就是再投资,它是熊市保护伞和收益加速器。
作者在研究了多个国家的股票之后,发现股票收益率是稳定的,尽管在经历了恶性通货膨胀,战争,经济大萧条等,所以未来股票收益也是可期待的。
我从baostock抓取了从2007年到2020年的股票情况,用python3.6粗略分析了一下可供大家参考。为什么选择baostock,我看网上说tushare好像要注册,通过积分取数据,对历史数据积分还不太容易得,但是baostock只支持从07年开始的历史数据。
列名 | 含义 |
---|---|
code | 股票代码 |
code_name | 股票名称 |
2007-01-15股价 | 取当天闭盘价格 |
2007-01-15滚动市盈率 | 取当天闭盘滚动市盈率 |
2020-09-22股价 | 取当天闭盘价格 |
2020-09-22滚动市盈率 | 取当天闭盘滚动市盈率 |
股价增长 | (20年股价-07年股价)/07年股价 |
分红回报 | 转送股+分红现金/派息当天股价 |
转送股 | |
投资回报 | 股价增长+分红回报 |
季度利润平均增长率 | %为单位 |
沪深300按照投资回报排序,前20只股票如下:
中证500按照投资回报排序,前20只股票如下:
全部的股票情况可以从以下链接下载:
沪深300:
http://www.offhours365.com/wp-content/uploads/2020/09/hs300_stocks_growth.csv
中证500:
http://www.offhours365.com/wp-content/uploads/2020/09/zz500_stocks_growth.csv
代码如下(代码可能有些空字段处理有问题,欢迎指出):
import baostock as bs
import pandas as pd
def growthYOYNI(id):
total = 0.0
num = 0
qu = 2
ye = 2007
qt = 53
while num < qt:
rs_growth = bs.query_growth_data(code=id, year=ye, quarter=qu)
if rs_growth.error_code != '0':
print(rs_growth.error_msg)
return -1
else:
row = rs_growth.get_row_data()
if len(row)<6:
print('growthYOYNI-{}_{}_{}:{}'.format(id, ye, qu, row))
qt = qt-1
num = num-1
else:
if row[5]=='':
print('growthYOYNI-{}_{}_{}:{}'.format(id, ye, qu, row))
qt = qt-1
num = num-1
else:
total = total + float(row[5])
qu = qu +1
num = num+1
if qu == 5:
qu = 1
ye = ye + 1
return total/qt
def crashinvest_growth(id, rowreturn):
ye = 2007
end = 2020
stnum = 0.0
total = 0.0
while ye <= end:
rs_dividend = bs.query_dividend_data(code=id, year=ye, yearType="report")
if rs_dividend.error_code != '0':
print(rs_dividend.error_msg)
return -1
else:
row = rs_dividend.get_row_data()
if len(row)<14:
ye = ye +1
continue
if row[13]!="":
stnum = stnum+ float(row[13])
total = total+ float(row[13])
if row[9]!="" :
if row[7]!="":
stdata = bs.query_history_k_data_plus(id, "close", row[7])
stdatarow = stdata.get_row_data()
cashst = float(row[9])/float(stdatarow[0])
total = total+cashst
ye = ye +1
rowreturn.append(total)
rowreturn.append(stnum)
return total
lg = bs.login()
print('login respond error_code:'+lg.error_code)
print('login respond error_msg:'+lg.error_msg)
begTime = "2007-01-15"
endTIme = "2020-09-22"
# find zz500 all code and still ok
hs300_stocks = []
rs = bs.query_zz500_stocks(begTime)
while (rs.error_code == '0') & rs.next():
list = rs.get_row_data()
stbs = bs.query_stock_basic(code=list[1])
stbsrow = stbs.get_row_data()
if (stbsrow[5]=='0'):
print(list[1])
else:
row = []
row.append(list[1])
row.append(list[2])
id = list[1]
stdata = bs.query_history_k_data_plus(id, "close,peTTM", begTime)
stdatarow = stdata.get_row_data()
a = float(stdatarow[0])
row.append(stdatarow[0])
row.append(stdatarow[1])
stdata = bs.query_history_k_data_plus(id, "close,peTTM", endTIme)
stdatarow = stdata.get_row_data()
b = float(stdatarow[0])
row.append(stdatarow[0])
row.append(stdatarow[1])
price = (b-a)/a
row.append(price)
crash = crashinvest_growth(id, row)
row.append(price+crash)
row.append(growthYOYNI(id)*100)
hs300_stocks.append(row)
# print(row)
print ("zz500_stocks length : ", len(hs300_stocks))
result = pd.DataFrame(hs300_stocks, columns=('code',
'code_name',
begTime+'股价',
begTime+'滚动市盈率',
endTIme+'股价',
endTIme+'滚动市盈率',
'股价增长',
'分红回报',
'转送股',
'投资回报',
'季度利润平均增长率'))
result.to_csv("zz500_stocks_growth.csv", encoding="gbk", index=False)
print(result)
bs.logout()
沪深300换成函数bs.query_hs300_stocks函数即可