“构建一个涵盖多个资产类别的投资池,使用ETF或指数基金跟踪每个类别的表现。通过动量和估值排名,调整收益率以获得更准确的度量,并根据排名和权重策略进行投资组合定位。”
资产类别:债券、股票、REITs | 地区:全球 | 频率:每月 | 市场:ETF、基金、期货 | 关键词:价值、动量
策略概述
构建一个包含多种资产类别的投资池,包括股票、债券和现金,覆盖全球不同地区。使用ETF或指数基金跟踪每个资产类别,基于价格序列进行动量排名,并通过调整后的收益率指标进行估值排名(例如股票的市盈率E/P、债券的到期收益率YTM,并进行特定调整以获得更精确的收益率)。根据12个月和1个月的动量以及估值对资产进行排名,动量权重为25%,估值权重为50%。策略将投资于排名前四分位的资产,同时做空排名后四分位的资产,以优化投资组合的表现。
策略合理性
学术研究广泛证明了价值和动量策略的有效性,指出它们能够显著提高投资组合的盈利能力。通过将这些策略应用于多个资产类别,而不仅仅局限于单一类别,投资策略的稳健性和有效性得到进一步提升。这种跨资产类别的应用不仅拓宽了投资视野,还引入了多样化的层次,有助于降低风险、稳定回报,从而优化整体投资策略。
论文来源
Global Tactical Cross-Asset Allocation: Applying Value and Momentum Across Asset Classes [点击浏览原文]
- David Blitz, 新加坡Robeco量化投资
- Pim van Vliet, 新加坡Robeco量化投资
<摘要>
本文探讨了在多个资产类别中应用全球战术资产配置(GTAA)策略的效果。与单一资产类别的市场择时和类似资产的战术配置相比,现有文献中对该主题的关注较少。我们的主要发现是,动量和价值策略应用于跨越12个资产类别的GTAA可以带来统计上和经济上显著的异常回报。基于动量和价值信号构建的前四分位多头和后四分位空头组合,在1986年至2007年期间的年化回报超过9%。该表现随着时间的推移保持稳定,且在样本外时期也同样存在,足以抵消实践中的交易成本。回报无法通过隐含的贝塔敞口或Fama-French和Carhart对冲因子来解释。我们认为,金融市场可能由于“聪明资金”不足而无法消除错误定价效应,导致了宏观效率低下。

回测表现
| 年化收益率 | 11.9% |
| 波动率 | 10.0% |
| Beta | -0.07 |
| 夏普比率 | -0.10 |
| 索提诺比率 | -0.009 |
| 最大回撤 | 17.3% |
| 胜率 | 53% |
完整python代码
from AlgorithmImports import *
import data_tools
from typing import List, Tuple, Dict
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Indicators import RollingWindow
class ValueMomentumAcrossAssets(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetCash(100000)
self.assets = [
('SPY', 'SP500_EARNINGS_YIELD_MONTH', data_tools.QuantpediaMonthlyData, 0, True),
('MDY', 'MID_CAP_PE', data_tools.QuantpediaPERatio, 0, True),
('IYR', 'REITS_DIVIDEND_YIELD', data_tools.QuantpediaPERatio, -2, False),
('EWU', 'United Kingdom', None, 0, True),
('EWJ', 'Japan', None, 0, True),
('EEM', 'EMERGING_MARKET_PE', data_tools.QuantpediaPERatio, -1, True),
('LQD', 'ML/AAAEY', data_tools.QuandlAAAYield, -2, False),
('HYG', 'ML/USTRI', data_tools.QuandlHighYield, -6, False),
('CME_TY1', 'US10YT', data_tools.QuantpediaBondYield, -1, False),
('EUREX_FGBL1', 'DE10YT', data_tools.QuantpediaBondYield, -1, False),
('SGX_JB1', 'JP10YT', data_tools.QuantpediaBondYield, -1, False),
('BIL', 'IR3TIB01USM156N', data_tools.QuantpediaMonthlyData, 0, False)
]
self.SetWarmUp(252)
self.leverage = 5
self.quantile = 4
self.data = {}
for symbol, _, data_type, _, _ in self.assets:
if data_type:
self.AddData(data_type, symbol, Resolution.Daily)
else:
self.AddEquity(symbol, Resolution.Daily).SetLeverage(self.leverage)
self.Settings.MinimumOrderMarginPortfolioPercentage = 0.0
self.last_month = -1
def OnData(self, data):
if self.IsWarmingUp:
return
current_month = self.Time.month
if current_month == self.last_month:
return
self.last_month = current_month
performance_1m = {}
performance_12m = {}
valuation = {}
for symbol, yield_symbol, data_type, yield_adj, reverse_flag in self.assets:
if symbol not in self.data:
self.data[symbol] = RollingWindow[float](252)
if symbol in data:
self.data[symbol].Add(data[symbol].Price)
# Calculate performance and valuation
for symbol in self.data:
if self.data[symbol].IsReady:
price_series = [x for x in self.data[symbol]]
performance_1m[symbol] = price_series[0] / price_series[21] - 1
performance_12m[symbol] = price_series[0] / price_series[-1] - 1
# Add your valuation calculation here based on the asset type
# Implement ranking and portfolio construction logic here
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters: OrderFeeParameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))
