克隆策略
In [1]:
import numpy as np
from statsmodels import regression
import statsmodels.api as sm
import matplotlib.pyplot as plt
import math
In [19]:
# 获取一段时间的股票数据
start_date = '2014-01-01'
end_date = '2015-01-01'
asset = DataSource("bar1d_CN_STOCK_A").read('600519.SHA',start_date,end_date,fields=['close']).set_index('date')['close']
benchmark = DataSource("bar1d_index_CN_STOCK_A").read('000300.HIX',start_date,end_date,fields=['close']).set_index('date')['close']
asset.name = '600519.SHA'
benchmark.name = '000300.SHA'

# 计算收益率
r_a = asset.pct_change()[1:]
r_b = benchmark.pct_change()[1:]

# 绘制
r_a.plot(figsize=[9,6])
r_b.plot()
plt.ylabel("Daily Return")
plt.legend();

现在我们可以通过回归求出 alpha($\alpha$) 和beta($\beta$)

In [20]:
X = r_b.values  
Y = r_a.values
x = sm.add_constant(X)
 
def linreg(x,y):
    # 增加一个常数项
    x = sm.add_constant(x)
    model = regression.linear_model.OLS(y,x).fit()
    # 再把常数项去掉
    x = x[:, 1]
    return model.params[0], model.params[1]

alpha, beta = linreg(X,Y)
print('alpha: ' + str(alpha))
print('beta: ' + str(beta))
alpha: 0.0011625393905649976
beta: 0.6729346530041009
In [21]:
X2 = np.linspace(X.min(), X.max(), 100)
Y_hat = X2 * beta + alpha

plt.scatter(X, Y, alpha=0.3) # 画出原始数据散点
plt.xlabel("000300.SHA Daily Return")
plt.ylabel("600519.SHA Daily Return")

 # 增加一条红色的回归直线
plt.plot(X2, Y_hat, 'r', alpha=0.9);

风险暴露

一般而言,beta描述的是持有资产所承担的 系统风险敞口这一概念,用$\beta$表示。 如果一项资产相对沪深300基准指数具有较高的$\beta$暴露水平,那么在市场上涨时,它的表现将会很好,当市场下跌时,它表现很差。 高$\beta$对应于高系统风险(高市场风险),意味着你的投资更具有波动性。

在BigQuant,我们重视尽可能没有系统风险暴露的 市场中性策略。 这意味着策略中的所有回报都在模型的$\alpha$部分,而与市场无关。 因为这意味着该策略与市场系统风险无关,不管是牛市还是熊市,它都具有稳定的业绩表现。 市场中性策略对于拥有大量现金池的机构(银行、保险、公募基金等)最具吸引力。

风险管理

减少因子风险暴露的过程称为 风险管理。对冲是在实践中进行风险管理的最佳方式之一。

通过案例来了解如何做到市场风险对冲的

现在我们已经知道要对冲多少市值,让我们看看它如何影响我们的收益。 我们使用贵州茅台和基准沪深300来构建我们的投资组合,将沪深300的权重设为-$\beta$(由于持有基准空头头寸)

In [22]:
# 构建一个市场中性组合
portfolio = -1*beta*r_b + r_a
portfolio.name = "600519.SHA + Hedge"

# 绘制各自的收益曲线
portfolio.plot(alpha=0.9,figsize=[9,6])
r_b.plot(alpha=0.5);
r_a.plot(alpha=0.5);
plt.ylabel("Daily Return")
plt.legend();

看来组合(贵州茅台+沪深300)的收益和贵州茅台走势相当接近。 我们可以通过计算两者的平均回报率和风险(收益率的标准差)来量化其表现的差异

In [24]:
print("means: ", portfolio.mean(), r_a.mean())
print("volatilities: ", portfolio.std(), r_a.std())
means:  0.0011625392362475395 0.002370904665440321
volatilities:  0.01785176992416382 0.019634943455457687

可以看出,我们以收益率为代价降低了波动,在降低风险的同时,收益也相应降低了。 接下来,我们来检查一下$\alpha$是否与以前一样,而$\beta$已被消除

In [25]:
P = portfolio.values
alpha, beta = linreg(X,P)
print('alpha: ' + str(alpha))
print('beta: ' + str(beta))  # alpha 和以前仍然一样 beta 已经被消除,beta几乎为0
alpha: 0.0011625393770863877
beta: -1.2462353111281077e-09

请注意,我们使用历史数据构建了 市场中性策略。 我们可以通过在不同的时间框架内验证资产和对冲投资组合的$\alpha$和$\beta$值来检查其是否仍然有效

In [27]:
# 得到过去一年得到的alpha 和beta值
start_date = '2014-01-01'
end_date = '2015-01-01'
asset = D.history_data('600519.SHA',start_date,end_date,fields=['close']).set_index('date')['close']
benchmark = D.history_data('000300.SHA',start_date,end_date,fields=['close']).set_index('date')['close']
r_a = asset.pct_change()[1:]
r_b = benchmark.pct_change()[1:]
X = r_b.values
Y = r_a.values
historical_alpha, historical_beta = linreg(X,Y)
print('Asset Historical Estimate:')
print('alpha: ' + str(historical_alpha))
print('beta: ' + str(historical_beta))

# 获取下一年的数据:
start_date = '2015-01-01'
end_date = '2015-06-01'
asset = D.history_data('600519.SHA',start_date,end_date,fields=['close']).set_index('date')['close']
benchmark = D.history_data('000300.SHA',start_date,end_date,fields=['close']).set_index('date')['close']
asset.name = '600519.SHA'
benchmark.name = '000300.SHA'
# 重复前面的过程来计算alpha 和beta值
r_a = asset.pct_change()[1:]
r_b = benchmark.pct_change()[1:]
X = r_b.values
Y = r_a.values
alpha, beta = linreg(X,Y)
print('Asset Out of Sample Estimate:')
print('alpha: ' + str(alpha))
print('beta: ' + str(beta))

# 构建对冲投资组合来计算alpha、beta
portfolio = -1*historical_beta*r_b + r_a
P = portfolio.values
alpha, beta = linreg(X,P)
print('Portfolio Out of Sample:')
print ('alpha: ' + str(alpha))
print ('beta: ' + str(beta))


# 绘制图形
portfolio.name = "600519.SHA + Hedge"
portfolio.plot(alpha=0.9,figsize=[9,6])
r_a.plot(alpha=0.5);
r_b.plot(alpha=0.5)
plt.ylabel("Daily Return")
plt.legend();
Asset Historical Estimate:
alpha: 0.0011625393905649976
beta: 0.6729346530041009
Asset Out of Sample Estimate:
alpha: 0.00020366206079023354
beta: 0.8665529691034388
Portfolio Out of Sample:
alpha: 0.0002036620088790199
beta: 0.1936183130062783

从上图可以看出,对冲后的收益降低了,但波动性也降低了。历史估计出的贝塔值在样本外的一年中是有效的,将资产的贝塔值0.673通过对冲降低到了0.193,也就是说降低了2/3,这样的对冲效果是比较明显的,而且也反映出历史的贝塔值是有效的,当然,要做到更好的效果,可以采取滚动估计贝塔的方法。