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

量化交易吧 /  量化平台 帖子:3354099 新帖:1

Beta对冲与Sector对冲(一)

我太难了发表于:5 月 9 日 19:21回复(1)

最近在打WorldQuant比赛时,注意到它在因子测试时提供了“Market,Sector,Industry”等中性化选项。选择不同的中性化方法得到的结果迥乎不同。我们为什么要对这些因素进行对冲呢?下面这篇文章及它的系列二很好地解答这个问题。

我们为什么要对冲贝塔暴露和部门暴露(一)¶

每当我们拿到一种新的交易策略时,我们需要先考虑其系统性风险的影响。为了获取高于无风险利率的超额收益,策略中必然会存在一定的风险,但坦白地说,系统性风险是一种逻辑谬误。就其性质而言,系统性风险提供了市场上各种股票之间存在的共性,而这些股票是无法被认为是多元化的。因此,我们需要构建一个对冲组合来摆脱这种窘境。

import numpy as npimport matplotlib.pyplot as pltimport pandas as pdfrom sklearn.covariance import LedoitWolfimport seaborn as snsimport statsmodels.api as sm

资产管理的基本法则¶

任何策略价值的主要驱动因素在于它是否提供了令人赞叹的风险调整回报,即夏普比率。夏普比率可以按下面的式子被*为两个组成部分:技能(skill)和宽度(breadth)

$$IR = IC \sqrt{BR}$$

技术上来说,上面的式子其实是信息比率(IR)的定义。但就我们的目的而言,它相当于夏普比率。IR是投资组合的超额收益与其基准的比率,即纯多头投资组合的超额收益与其每单位基准的跟踪误差。然而,在这个公式被给出时,多/空投资很少见。今天,在对冲基金和多头/空头投资领域,我们往往并没有基准,我们追求的是绝对回报。因此在这种情况下,IR等于夏普比率。

等式中,技能(skill)由信息系数(IC)来衡量,它可以用Alphalens包或者聚宽的因子看板功能来观测。信息系数其实是斯皮尔曼秩相关系数的体现,被用于联系你的预测和它的实现。宽度(breadth)的测量取决于期间内“独立*”(independent bets)的次数。也就是说,无论我们采取何种策略,都需要:

  1. *下得准 (高IC)

  2. *下得多

  3. 做“独立*”

如果每次*都是完全独立的,那么宽度就是我们每次*的总和。如果这些*并不是独立的,则有效宽度(effective breadth)则可能比资产总数要小得多得多。让我们先来看看beta暴露和部门(sector)暴露与有效宽度的联系吧。

Beta暴露和部门暴露会使得*间的相关性显著提高。一个投资组合如果具有高beta暴露和部门暴露,它的有效宽度将非常低。为了获得更高的夏普,投资组合也可以具有很高的IC。但是IC并不容易提升,所以人们往往考虑通过对冲beta和部门暴露来提高有效宽度。

预测与*相关性¶

我们将*定义为股票收益残差的预测。这种预测可能是隐含的,比如我们购买一只股票其实就是我们预测它会上涨。那么我们所说的残差是什么呢?不需要任何花哨的数学,这只是意味着对冲后的收益,让我们通过下面三个例子来阐明这点。我们将使用Ledoit-Wolf协方差估计器来估测下面例子里的协方差。为什么我们要使用Ledoit-Wolf而不是典型的样本协方差呢?之后我们会有专题研究来说明。

案例1:没有对冲!¶

如果我们持有一组股票的多头,且并不拥有任何空头头寸,这意味着我们没有任何对冲操作。因此此时残差便是股票收益本身,如下式:

$$r_{resid,i} = r_i$$

让我们来看看这个案例中*的相关性:

tickers = ['WFC', 'JPM', 'USB', 'XOM', 'BHI', 'SLB'] # 我们持有的多头股票historical_prices = get_pricing(tickers, start_date='2015-01-01',end_date='2017-02-22') # 获得价格rets = historical_prices['close_price'].pct_change().fillna(0) # 计算收益lw_cov = LedoitWolf().fit(rets).covariance_ # 计算Ledoit-Wolf协方差def extract_corr_from_cov(cov_matrix):# 做线性回归:d = np.linalg.inv(np.diag(np.sqrt(np.diag(cov_matrix))))corr = d.dot(cov_matrix).dot(d)return corr
fig, (ax1, ax2) = plt.subplots(ncols=2)fig.tight_layout()corr = extract_corr_from_cov(lw_cov)# 绘制价格曲线left = historical_prices['close_price'].plot(ax=ax1)# 绘制协方差热力图right = sns.heatmap(corr, ax=ax2, fmt='d', vmin=-1, vmax=1, xticklabels=tickers, yticklabels=tickers)


*erage_corr = np.mean(corr[np.triu_indices_from(corr, k=1)])print ('*erage pairwise correlation: %.4f' % *erage_corr)

本例中,平均相关系数为 0.5644,可见不对冲的情况下这六次*具有高度的相关性。

案例2:对冲beta¶

在这个案例中,我们假设每一次*都进行过市场对冲(SPY)。此时,残差的计算公式变为:

$$ r_{resid,i} = r_i - \beta_i r_i $$

$\beta_i$ 是股票 $i$ 的贝塔值,由CAPM公式计算而得。而 $r_i$ 是股票 $i$ 的收益率。

tickers = ['WFC', 'JPM', 'USB', 'SPY', 'XOM', 'BHI', 'SLB' ] # 我们持有的多头股票historical_prices = get_pricing(tickers, start_date='2015-01-01',end_date='2017-02-22') # 获取价格rets = historical_prices['close_price'].pct_change().fillna(0) # 计算收益率market = rets[symbols(['SPY'])]stock_rets = rets.drop(symbols(['SPY']), axis=1)residuals = stock_rets.copy()*0for stock in stock_rets.columns:model = sm.OLS(stock_rets[stock], market.values)results = model.fit()residuals[stock] = results.residlw_cov = LedoitWolf().fit(residuals).covariance_ # 计算Ledoit-Wolf协方差
fig, (ax1, ax2) = plt.subplots(ncols=2)fig.tight_layout()corr = extract_corr_from_cov(lw_cov)left = (1+residuals).cumprod().plot(ax=ax1)right = sns.heatmap(corr, ax=ax2, fmt='d', vmin=-1, vmax=1, xticklabels=tickers, yticklabels=tickers)


*erage_corr = np.mean(corr[np.triu_indices_from(corr, k=1)])print ('*erage pairwise correlation: %.4f' % *erage_corr)

本例中,平均相关系数为 0.2256,beta对冲很明显地降低了*间的相关性。不过从热力图上,我们可以看出有几只股票其实具有很高的相关性。让我们来看看如果我们将部门暴露对冲后,相关系数会发生什么事。

案例3:部门对冲¶

部门收益和市场收益是高度相关的。由于多重共线性,我们无法直接使用多元回归。为了对冲市场和给定股票所在的行业部门的影响,我们首先应该先估计市场β残差,然后计算所得残差中的的部门beta。 $$ r_{resid,i} = r_i - \beta_i r_i \\ r_{resid_{SECTOR},i}= r_{resid,i} - \beta_{SECTOR,i}r_{resid,i} $$

$r_{resid, i}$ 是股票收益与市场beta对冲后的残差,$r_{resid_{SECTOR}, i}$ 是上面残差与相关部门对冲后的残差。

tickers = ['WFC', 'JPM', 'USB', 'XLF', 'SPY', 'XOM', 'BHI', 'SLB', 'XLE']historical_prices = get_pricing(tickers, start_date='2015-01-01',end_date='2017-02-22')rets = historical_prices['close_price'].pct_change().fillna(0)# 获得市场行情mkt = symbols(['SPY'])# 获得部门行情sector_1_hedge = symbols(['XLF'])sector_2_hedge = symbols(['XLE'])# 将每只股票分划到它所在的行业部门中sector_1_stocks = symbols(['WFC', 'JPM', 'USB'])sector_2_stocks = symbols(['XOM', 'BHI', 'SLB'])market_rets = rets[mkt]sector_1_rets = rets[sector_1_hedge]sector_2_rets = rets[sector_2_hedge]   stock_rets = rets.drop(symbols(['XLF', 'SPY', 'XLE']), axis=1)residuals_market = stock_rets.copy()*0residuals = stock_rets.copy()*0# 计算部门1基准下的市场betamodel = sm.OLS(sector_1_rets.values, market.values)results = model.fit()sector_1_excess = results.resid# 计算部门2基准下的市场betamodel = sm.OLS(sector_2_rets.values, market.values)results = model.fit()sector_2_excess = results.residfor stock in sector_1_stocks:# 计算部门1股票的市场betamodel = sm.OLS(stock_rets[stock], market.values)results = model.fit()# 计算股票残差+市场对冲residuals_market[stock] = results.resid# 计算部门对冲model = sm.OLS(residuals_market[stock], sector_1_excess)results = model.fit()# 得到最后残差residuals[stock] = results.resid   for stock in sector_2_stocks:model = sm.OLS(stock_rets[stock], market.values)results = model.fit()residuals_market[stock] = results.residmodel = sm.OLS(residuals_market[stock], sector_2_excess)results = model.fit()residuals[stock] = results.resid# 得到残差的协方差lw_cov = LedoitWolf().fit(residuals).covariance_
fig, (ax1, ax2) = plt.subplots(ncols=2)fig.tight_layout()corr = extract_corr_from_cov(lw_cov)left = (1+residuals).cumprod().plot(ax=ax1)right = sns.heatmap(corr, ax=ax2, fmt='d', vmin=-1, vmax=1, xticklabels=tickers, yticklabels=tickers)


本例中,平均相关系数已经降低到了 0.0281,说明我们的对冲确实是有效的!

计算有效宽度¶

本文的此部分基于D*id Buckle的论文"How to calculate breadth: An evolution of the fundamental law of active portfolio management",我们使用下面的式子来对有效宽度建模:

$$BR = \frac{N}{1 + \rho(N -1)}$$

N 是投资组合中的股票数量,$\rho$ 是上面提过的相关系数。

def buckle_BR_const(N, rho):return N/(1 + rho*(N - 1))corr = np.linspace(start=0, stop=1.0, num=500)plt.plot(corr, buckle_BR_const(6, corr))plt.title('Effective Breadth as a function of Forecast Correlation (6 Stocks)')plt.ylabel('Effective Breadth (Number of Bets)')plt.xlabel('Forecast Correlation');


Here we see that in the case of the long-only portfolio, where the *erage correlation is 0.56, we are effectively making only approximately 2 bets. When we hedge beta, with a resulting *erage correlation of 0.22, things get a little better, three effective bets. When we add the sector hedge, we get close to zero correlation, and in this case the number of bets equals the number of assets, 6.

从上面的图中我们看到,在多头投资组合的情况下,平均相关性为0.56,我们实际上大约只有2次*。 当我们对冲beta时,平均相关系数为0.22,情况变得更好,相当于三次有效的*。而当我们采用部门对冲后,我们得到接近于零的相关性。在这种情况下,*数量等于资产数量,即6。

同样的IC下,更多的独立*次数意味着更高的夏普


全部回复

0/140

量化课程

    移动端课程