迈克尔·喜伟收益型投资法

引言

迈克尔·喜伟(Michael Sivy)是美国知名的投资分析师,畅销书 《Michael Sivy’s Rules of Investing: How to pick stocks like a pro》的作者。其对全球股市的预测绩效显著,曾在 1987 年预警美国股市的大崩盘,在 1994 年华尔街空头气氛弥漫时成功预测到了 1995 年至 1999 年美国股市的长牛市。迈克尔·喜伟也是美国著名财经杂志 Money Magazine 的专栏作家,并被认为是该杂志的首席策略分析大师。同时,他也是 TIME 杂志的专栏作家,并对不同类型的投资者的选股策略有着精辟的见解。本篇文章及是对其畅销书《Michael Sivy’s Rules of Investing: How to pick stocks like a pro》中投资理念的提炼。

策略思路

迈克尔·喜伟是价值投资的拥护者,他认为价值收益型的投资者在进行选股时的目标是找出具有以下四个特性的个股:

一、具有高于平均的收益率;
二、具有诱人而可预测的成长率;
三、财务健康;
四、相对低的股价。

从这五个角度出发,我们给出选股的五个指标:
1. 股息率
2. 每股收益增长率
3. 产权比率
4. 流动比率
5. 市盈率

这五个指标共同构建了选股准则,构成了迈克尔·喜伟价值导向选股法则。这五条准则非常清晰明确,均为可直接量化实现的准则。每条准则具有明确的量化描述和判断条件,除个别部分需对中国市场调整外,我们的回测将严格按照这五条准则复制,不存在需主观判断而不能量化的准则。

策略细节

归纳理查马文价值投资策略初始版本,可以大致总结策略衡量的四个方面:
(1)高于平均的收益率:可用股利收益率来衡量股票派息的收益水平;
(2)诱人而可预测的成长率:可以每期的每股收益增长率衡量成长性;
(3)健康的财务:负债与股东权益之比(产权比率)相对较低而流动比率相对较高;
(4)便宜的股价:可用市盈率来衡量股价是否被低估。

其价值选股标准也主要围绕着这几个方面,具体为:

罗伯·瑞克超额现金流选股法则的通用版本:
a) 股息率大于市场平均值;
b) 每股收益增长率大于市场平均值;
c) 负债与股东权益之比(产权比率)小于市场平均值;
d) 流动比率大于市场平均值;
e) 市盈率为正且小于市场平均值。

策略实现

为了比较长期价值投资的效果,我们进行了 3 次回测,回测时长分别为 1 年,5 年,10 年。

(1)迈克尔·喜伟收益型投资法
投资标的:A 股
调仓周期:60 天
回测时间:2016.01.01~2017.01.01
回测时长:1 年

收益曲线

收益归因

业绩分析

从回测结果看,虽然该策略在近一年的回测期中取得了一定的超额收益,但绝对收益率还是很低,更值得注意的是策略的胜率很低,且相对于之前介绍的价值选股法,其超额收益也并不优秀。

(2)迈克尔·喜伟收益型投资法
投资标的:A 股
调仓周期:60 天
回测时间:2014.01.01~2017.01.01
回测时长:3 年

收益曲线

收益归因

业绩分析

当回测时间延长到三年,策略的表现优异了很多。年化收益率到达 44.6%,复合年化收益率 33%,同时胜率达到了 59.5%。

(3)迈克尔·喜伟收益型投资法
投资标的:A 股
调仓周期:60 天
回测时间:2007.01.01~2017.01.01
回测时长:10 年

收益曲线

收益归因

业绩分析

在十年期回测中,我们发现策略的表现优秀。取得了 85.5% 的年华收益和 25.8% 的复合年化收益率,胜率依然保持在将近 60%。

通过以上三次回测,我们可以发现该策略在中长期的投资期限内表现更为优良。这也符合我们对价值投资的一般认识。

小结

迈克尔·喜伟是美国知名的投资分析师,畅销书《Michael Sivy’s Rules ofInvesting: How to pick stocks like a pro》的作者。他对不同类型的投资者的选股策略进行了分析,认为价值收益型的投资者在进行选股时的目标是找出具有以下四个特性的个股:具有高于平均的收益率、具有诱人而可预测的成长率、财务健康和相对低的股价。量化后的迈克尔·喜伟收益型投资法从这四个方面,选取市盈率、产权比率、流动比率、每股收益增长率和股息率 5 个指标进行选股,并以市场均值作为筛选阈值。

从我们的回测结果来看,迈克尔·喜伟收益型投资法表现出了很强的价值投资特性,在短期内表现一般,但是在中长期的投资表现十分亮眼,非常值得我们沿着这五条准则所体现的思路作进一步的优化和探索。

在此我们再次提出两个个简单的优化建议: 一是吸收迈克尔·喜伟收益型投资策略中的投资思维,在原有基础上扩展筛选股的考查纬度、或者调整具体的考核指标,进一步优化考察指标的参数;二是将迈克尔·喜伟收益型投资策略所选出的股票作为股票池,进一步利用其它方法筛选或择时判断。

关于回测平台、历史数据,可以在这里下载:http://www.yunkuanke.com/#/introduce
这个平台的数据都是经过清洗的,而且策略不会外露,有保密系统,还是比较安全的。
想学习更多量化策略,也可以来这里看看:http://www.yunkuanke.com/#/lzClass
想学习更多关于量化投资策略相关内容的,可以关注微信:量化投资与金融科技(微信号:QuantumFintech)
微信二维码:

Code

# -*- coding:utf-8 -*-

from CloudQuant import SDKCoreEngine  # 导入量子金服SDK
from CloudQuant import AssetType
from CloudQuant import QuoteCycle
import numpy as np
import pandas as pd

np.seterr(invalid='ignore')

config = {
'username': username',
'password': 'password',
'rootpath': 'c:/cStrategy',  # 客户端所在路径
'assetType': AssetType.Stock,
'initCapitalStock': 100000000,
'startDate': 20070101,
'endDate': 20170101,
'cycle': QuoteCycle.D,
'strategyName': 'sivy',
'feeRate': 0.001,
'feeLimit': 5,
'stampTaxRate': 0.001,
'dealByVolume': True
}

HOLDING_PERIOD=60

def initial(sdk):
sdk.setGlobal('c',0)

def initPerDay(sdk):
 pass

def strategy(sdk):
count=sdk.getGlobal('c')
if count==0:
PE = sdk.getFactorData('LZ_CN_STKA_VAL_PE')[-1] #  PE
PPD=sdk.getFactorData('LZ_CN_STKA_VAL_PPD')[-1] # 股价/每股派息
DR=1/PPD #股息率
YOYEPS=sdk.getFactorData('LZ_CN_STKA_FIN_IND_YOYEPBASIC')[-1]#每股收益增长率
D2E=sdk.getFactorData('LZ_CN_STKA_FIN_IND_DEBTTOEQUITY')[-1] #产权比率
CURRENT=sdk.getFactorData('LZ_CN_STKA_FIN_IND_CURRENT')[-1] #流动比率
ST = sdk.getFactorData('LZ_CN_STKA_SLCIND_ST_FLAG')[-1]  # ST
STOP = sdk.getFactorData('LZ_CN_STKA_SLCIND_STOP_FLAG')[-1]  # 停牌
stock_list = sdk.getStockList()
stock_list = np.array(stock_list)

condition_DR = DR >= np.nanmean(DR)
condition_EPS=YOYEPS>=np.nanmean(YOYEPS)
condition_D2E=D2E<=np.nanmean(D2E)
condition_CURRENT=CURRENT>=np.nanmean(CURRENT)
condition_PE_1=PE>0
condition_PE_2=PE<=np.nanmean(PE)
condition_ST = ST == 0
condition_STOP = STOP == 0
condition = condition_DR* condition_EPS * condition_D2E * condition_CURRENT * condition_PE_1*condition_PE_2*condition_ST * condition_STOP

stock_pool=stock_list[condition]
print len(stock_pool)
transferPosition(sdk, stock_pool)
count+=1
if count==HOLDING_PERIOD:
count=0
 sdk.setGlobal('c',count)

def transferPosition(sdk,stock_pool):
position = sdk.getPositions()
position_dict = dict([i.code, i.optPosition] for i in position)
stock_to_buy = set(stock_pool) - set(position_dict.keys())
stock_to_sell = set(position_dict.keys()) - set(stock_pool)
if stock_to_sell:
sell_orders = []
for stock in stock_to_sell:
    if stock in quotes.keys():
        price = quotes[stock].current
        volume = position_dict[stock]
        order = [stock, price, volume, -1]
        sell_orders.append(order)
if sell_orders:
    sdk.makeOrders(sell_orders)
    sdk.sdklog("------------------------------------------")
    sdk.sdklog(sdk.getNowDate(),"DATE")
    sdk.sdklog(sell_orders,"SELL")
if stock_to_buy:
available_cash = sdk.getAccountInfo().availableCash
available_cash_one_stock = available_cash / len(stock_to_buy)
buy_orders = []
for stock in stock_to_buy:
    if stock in quotes.keys():
        price = quotes[stock].open
        volume = int(available_cash_one_stock / (price * 100)) * 100
        if volume > 0:
            order = [stock, price, volume, 1]
            buy_orders.append(order)
if buy_orders:
    sdk.makeOrders(buy_orders)
    sdk.sdklog("------------------------------------------")
    sdk.sdklog(sdk.getNowDate(),"DATE")
    sdk.sdklog(buy_orders,'BUY')

def run_all():
config['initial'] = initial
config['strategy'] = strategy
config['preparePerDay'] = initPerDay
# 启动SDK
SDKCoreEngine(**config).run()

if __name__ == '__main__':
run_all()