根據多因子模型,或者說alpha策略的開發順序,我們應當是按照:因子--》alpha 模型--》風險模型--》組合構建 這樣幾個模塊來的。今天來說說組合構建這個事。

組合構建是在你有了alpha模型和風險模型之後,也就是說,你現在可以預測股票的收益和股票的風險了。那麼我們怎麼構建組合呢? 大概有這麼幾種方法:

  • 根據alpha模型,選擇前面N個預測收益高的股票,然後權重都是1/N;
  • 市值加權,當然也可以市值平方根或者市值對數加權,都屬於這一類;
  • 使用現代portfolio理論,說白了,就是上優化器。

當然啦,前面這兩種,我們就不說了,實在是easy,但是缺點也很明顯,就是你沒有用完你對收益的預測信息和你對風險的預測。如果你覺得你的預測很爛,那麼其實這樣也無所謂。畢竟,很爛的話,還不如拋硬幣選股配權重,是吧。原理上來講,前兩種其實就是投資者信息較少的一種做法。


1.二次規劃(Quadratic Programming)

一般的二次規劃通用問題是這樣的:

min frac{1}{2}xQx + xc

subject to. Ax leq b

沒見過的同學得補一下了,大致就是說,我們要找到一個x向量,這個向量在上面這個表達式中,滿足subject to的條件,我們叫做約束,同時,在約束的條件下,使上面這個目標函數儘可能小。說白了,就是求x這一個向量。

那麼,我們怎麼把這個用到組合裡面呢?先不急,我們注意上,上面的約束是一個不等式約束,而二次規劃的等式約束,也就是條件是等式,那麼其實這個優化問題是有解析解的。

先不管這個,我們來考慮一下投資的本質。說白了,投資就是風險和收益的權衡,我們希望在最大化收益的情況下,可以使得風險最小。說白了,就是你首先約定一個收益,然後我們要求風險最小。如果熟悉馬科維茲的那套東西,就知道,就是我們的portfolio在有效前沿上。然後在看一下上面的公式,說白了,就是我們可以用等式約束,約束住一個收益,上面min的變成我們的risk。完美!

那麼我們先用等式約束來感受一下吧。

假設我們現在有三個股票,分別叫做s1,s2,s3,然後我們預測他的收益率為u1,u2,u3,分別為0.100162,0.164244,0.182082.

我們當然還預測了risk,但是risk必然是一個matrix,我們假設:

 sum = left( egin{array}{ccc} sigma_{11} & sigma_{12}& sigma_{13} \ sigma_{21} & sigma_{22} & sigma_{23} \ sigma_{31} & sigma_{32} & sigma_{33} end{array} 
ight) = left( egin{array}{ccc} 0.100162 & 0.045864 & 0.005712 \ 0.045864 & 0.210773 & 0.028283 \ 0.005712 & 0.028283 & 0.066884 end{array} 
ight)

那麼到現在,我們對風險的預測和對收益的預測都有了,我們就可以開始用優化器構建組合了。我們要清楚,既然是構建組合,那麼我們的目標就是得到每一個股票的權重,所謂,一開始的x向量,其實就是我們要的答案,股票的權重。然後,既然是投資,要把錢投出去,投多少我們是知道的,我們一般構建的時候都認為是全額投資,也就是說,我們的每一個股票加起來的權重應該是1,沒有錢是放著發黴用的。然後,我們就要選一個收益,然後用優化器構建一個這個收益下風險最小的組合了。我們假設我們的收益要求是0.15.

好了,數據都有了,我們可以把上面這一分析扔到一開始的二次規劃的模型裡面了。

那麼,首先,我們的約束有兩個:

sum(w_i) = 1

sum(w_i * u_i) = 0.15

然後我們的目標函數,也就是風險是:

min wsum w

那麼,寫成優化的形式就是:

min wsum w

subject to. Aw=b

其中,

A = left( egin{array}{ccc} 1 & 1 & 1 \ u_1 & u_2 & u_3 end{array} 
ight)

b = left( egin{array}{ccc} 1\ 0.15 end{array} 
ight)

這樣我們就構建好了我們的優化目標和優化限制了。可以自行百度學習如何對等式約束的二次規劃問題用拉格朗日乘子法求取解析解,這裡筆者直接給出答案,組合權重w向量的解析解是:

w = {sum}^{-1}A^{}(A{sum}^{-1}A^{})^{-1}b


2.第一個等式約束的例子

import numpy as np
cov_matrix = np.matrix([[0.100162,0.045864,0.005712],[0.045864,0.210773,0.028283],[0.005712,0.028283,0.066884]])
A_matrix = np.matrix([[1,1,1],[0.100162,0.164244,0.182082]])
b_matrix = np.matrix([[1],[0.15]])
w = cov_matrix.I * A_matrix.T * (A_matrix * cov_matrix.I * A_matrix.T).I * b_matrix

查看w就可以知道每個股票的權重了,同時也可以(A_matrix * w)[1,0],(w.T * cov_matrix * w)[0,0]兩個語句獲得預期收益率和風險。上面的例子,收益是0.15,風險是0.0425既然,這樣,我們把有效前沿畫出來好了嘍。


3.等式約束的有效前沿

import pandas as pd
%matplotlib inline
cov_matrix = np.matrix([[0.100162,0.045864,0.005712],[0.045864,0.210773,0.028283],[0.005712,0.028283,0.066884]])
A_matrix = np.matrix([[1,1,1],[0.100162,0.164244,0.182082]])
return_list = list()
risk_list = list()
for i in range(1, 300):
up = i/1000.0
b_matrix = np.matrix([[1],[up]])
w = cov_matrix.I * A_matrix.T * (A_matrix * cov_matrix.I * A_matrix.T).I * b_matrix
return_list.append((A_matrix * w)[1,0])
risk_list.append((w.T * cov_matrix * w)[0,0])
plot_df = pd.DataFrame()
plot_df[return] = return_list
plot_df[risk] = risk_list
plot_df.plot.scatter(x=risk, y=return)

有效前沿繪製結果如下:

等式條件的有效前沿

在(下)中,我們將討論不等式約束,例如做空限制,持倉限制等等,然後通過優化器實現組合的構建。

個人blog:lyx的專欄 - CSDN博客


推薦閱讀:
相關文章