投资范围包括《财富》杂志每年发布的“美国最佳雇主百强”公司排名,由“Great Place to Work Institute”创建。策略在排名公布后的第一个月(2月1日)构建等权重投资组合,仅做多,并每年根据最新排名重新平衡。

策略概述

投资范围包括在由“美国最佳雇主百强”排名的公司,该排名由“Great Place to Work Institute”每年创建,并在1月中旬左右由《财富》杂志发布。策略在排名公布后的第一个月(即2月1日)构建一个等权重的投资组合,由榜单中的公司组成。策略为只做多,且每年根据排名重新平衡。

策略合理性

该策略基于投资者对具有社会责任的公司价值低估的假设。研究表明,员工满意度高的公司,其生产率更高,员工更愿意在困难时期共同努力。此外,投资者往往更注重对不负责任的公司进行负面筛选,而不是积极关注优秀公司。该策略在36年的样本期中经过多因素模型测试(如Fama-French的六因子模型、Hou等人的q4、q5因子模型,以及AQR的六因子模型),结果表明该策略的阿尔法具有显著性(表6)。该策略不仅在等权重组合中有效,在价值加权组合中也有效,表明其结果并非由微型股主导。

论文来源

Employee Satisfaction and Long-run Stock Returns [点击浏览原文]

<摘要>

经济理论预测,在不存在错误定价的情况下,投资于社会责任企业应具有较低的预期回报。然而,Edmans(2011)的影响性论文表明,“美国最佳雇主百强”公司的投资组合具有显著的Carhart四因子阿尔法。十多年后,我们探讨了这一结果是否(a)适用于样本外,(b)受新发现的因子和特征的驱动,以及(c)是否依赖于经济状况。研究表明,高达22%的Carhart阿尔法可以归因于投资、盈利能力和质量等新发现的因子。然而,使用最先进的因子模型并在1984年至2020年期间进行测试后,等权重的BC投资组合每年能获得2%至2.7%的异常回报。异常回报并非由公司特征、行业构成或微型股驱动,且在样本的几乎所有时期均为正值,尤其是在2000-2002年和2008-2009年的危机期间表现尤为突出。总体而言,研究结果表明股市仍低估了员工满意度,尤其是在“困难时期”其价值最为显著。

回测表现

年化收益率16.07%
波动率17.49%
Beta0.947
夏普比率0.92
索提诺比率0.359
最大回撤N/A
胜率79%

完整python代码

from AlgorithmImports import *
#endregion

class EmployeeSatisfactionFactor(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2000, 1, 1)
        self.SetCash(100_000)
        
        self.tickers_by_year: Dict[int, List[str]] = {}
        
        # download companies employees satisfaction ratings for each year
        csv_string_file: str = self.Download('data.quantpedia.com/backtesting_data/index/employee_satisfaction_top_100.csv')
        lines: List[str] = csv_string_file.split('\r\n')
        
        for line in lines:
            line_split: List[str] = line.split(';')
            date: datetime.date = datetime.strptime(line_split[0], "%d.%m.%Y").date()
            year: int = date.year
            
            # store list of tickers by year
            self.tickers_by_year[date.year] = line_split[1:]
        
        self.leverage: int = 5

        self.current_year: int = -1
        self.selection_flag: bool = False
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.FundamentalSelectionFunction)
        self.Settings.MinimumOrderMarginPortfolioPercentage = 0.
        
        self.long: List[Symbol] = []
        market: Symbol = self.AddEquity('SPY', Resolution.Daily).Symbol
        self.Schedule.On(self.DateRules.MonthStart(market), self.TimeRules.BeforeMarketClose(market), self.Selection)
    
    def Selection(self) -> None:
        # beginning of February rebalance
        if self.Time.month == 2:
            self.selection_flag = True
        
    def OnSecuritiesChanged(self, changes: SecurityChanges) -> None:
        for security in changes.AddedSecurities:
            security.SetFeeModel(CustomFeeModel())
            security.SetLeverage(self.leverage)

    def FundamentalSelectionFunction(self, fundamental: List[Fundamental]) -> List[Symbol]:
        self.current_year = self.Time.year
        
        # rebalance yearly
        if not self.selection_flag or self.current_year - 1 not in self.tickers_by_year:
            return Universe.Unchanged
            
        current_top_companies: List[str] = self.tickers_by_year[self.current_year - 1]
        
        # filter stock symbols from top companies in previous year
        self.long = [x.Symbol for x in fundamental if x.Symbol.Value in current_top_companies]
        
        return self.long

    def OnData(self, slice) -> None:
        # rebalance yearly
        if self.selection_flag == False:
            return
        self.selection_flag = False
        
        # trade execution
        portfolio: List[PortfolioTarget] = [PortfolioTarget(symbol, 1. / len(self.long)) for symbol in self.long if symbol in slice and slice[symbol]]
        self.SetHoldings(portfolio, True)

        self.long.clear()

# Custom fee model
class CustomFeeModel(FeeModel):
    def GetOrderFee(self, parameters):
        fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
        return OrderFee(CashAmount(fee, "USD"))

Leave a Reply

Discover more from Quant Buffet

Subscribe now to keep reading and get access to the full archive.

Continue reading