三支股票 A.B和C,請問該如何算出最優的投資組合配比(最大回報,最小風險)?
已知各股的
股價期望回報率標準差兩兩之間的協方差總投資金額
想求出最大回報 最小風險的組合配比,該怎麼做?就是A B C 各佔多少投資金額的百分比最好?有人說用excel線性規劃做,實際操作起來不知該從何下手,求助。
看題主的組合才3隻股票就搞得很複雜了。。。這兩天剛用python做了下投資組合理論的驗證。要是會點編程,別說A、B、C三隻股票了,就是整個上證+深證三千多隻股票也沒問題的。原文見:【組合管理】——投資組合理論(有效前沿)源碼都貼上了,現在這時代不會點編程都吃不飽飯了,感興趣的可以搬去用不謝。
------------------------------------------2016.2.26更新----------------------------------------------------
ps:有人問到這個分析是在哪兒做的。我也是對量化策略感興趣,最近用JoinQuant的平台在做些研究,順便分享出來和大家一起交流。--------------------------------------------------------------------------------------------------------------正態性檢驗和蒙特卡洛完成投資組合優化by 陳小米。
最近一直在思考怎樣有效的配置資產組合。 很多時候根據條件選好股票池之後,通常簡單粗暴的等分倉位給每隻股票。 其實,這個過程中有很多可以優化的空間。
下面,給大家分享一下如何運用有效前沿進行資產組合優化。
PART ONE: 正態性檢驗這部分是附贈福利。只對資產組合優化感興趣的朋友可以直接跳到PART TWO。
(知乎回答字數限制,這部分暫且刪除,感興趣的到原文鏈接自己看哦~)該理論基於用均值和方差來表述組合的優劣的前提。將選取幾隻股票,用蒙特卡洛模擬初步探究組合的有效前沿。
通過最大Sharpe和最小方差兩種優化來找到最優的資產組合配置權重參數。
最後,刻畫出可能的分布,兩種最優以及組合的有效前沿。
1.選取幾隻感興趣的股票000413 東旭光電,000063 中興通訊,002007 華蘭生物,000001 平安銀行,000002 萬科A
並比較一下數據(2015-01-01至2015-12-31)
In [102]:stock_set = ["000413.XSHE","000063.XSHE","002007.XSHE","000001.XSHE","000002.XSHE"]
noa = len(stock_set)
df = get_price(stock_set, start_date, end_date, "daily", ["close"])
data = df["close"]
#規範化後時序數據
(data/data.ix[0]*100).plot(figsize = (8,5))
Out[102]:
&
每年252個交易日,用每日收益得到年化收益。
計算投資資產的協方差是構建資產組合過程的核心部分。運用pandas內置方法生產協方差矩陣。
In [103]:returns = np.log(data / data.shift(1))
returns.mean()*252
Out[103]:
000413.XSHE 0.184516
000063.XSHE 0.176790
002007.XSHE 0.309077
000001.XSHE -0.102059
000002.XSHE 0.547441
dtype: float64
In [104]:
returns.cov()*252
Out[104]:
由於A股不允許建立空頭頭寸,所有的權重係數均在0-1之間
In [105]:weights = np.random.random(noa)
weights /= np.sum(weights)
weights
Out[105]:
array([ 0.37505798, 0.21652754, 0.31590981, 0.06087709, 0.03162758])
np.sum(returns.mean()*weights)*252
Out[106]:
0.21622558669017816
In [107]:
np.dot(weights.T, np.dot(returns.cov()*252,weights))
Out[107]:
0.23595133640121463
In [108]:
np.sqrt(np.dot(weights.T, np.dot(returns.cov()* 252,weights)))
Out[108]:
0.4857482232609962
進行到此,我們最想知道的是給定的一個股票池(證券組合)如何找到風險和收益平衡的位置。
下面通過一次蒙特卡洛模擬,產生大量隨機的權重向量,並記錄隨機組合的預期收益和方差。
In [111]:port_returns = []
port_variance = []
for p in range(4000):
weights = np.random.random(noa)
weights /=np.sum(weights)
port_returns.append(np.sum(returns.mean()*252*weights))
port_variance.append(np.sqrt(np.dot(weights.T, np.dot(returns.cov()*252, weights))))
port_returns = np.array(port_returns)
port_variance = np.array(port_variance)
#無風險利率設定為4%
risk_free = 0.04
plt.figure(figsize = (8,4))
plt.scatter(port_variance, port_returns, c=(port_returns-risk_free)/port_variance, marker = "o")
plt.grid(True)
plt.xlabel("excepted volatility")
plt.ylabel("expected return")
plt.colorbar(label = "Sharpe ratio")
Out[111]:
&
建立statistics函數來記錄重要的投資組合統計數據(收益,方差和夏普比)
通過對約束最優問題的求解,得到最優解。其中約束是權重總和為1。
In [115]:def statistics(weights):
weights = np.array(weights)
port_returns = np.sum(returns.mean()*weights)*252
port_variance = np.sqrt(np.dot(weights.T, np.dot(returns.cov()*252,weights)))
return np.array([port_returns, port_variance, port_returns/port_variance])
#最優化投資組合的推導是一個約束最優化問題
import scipy.optimize as sco
#最小化夏普指數的負值
def min_sharpe(weights):
return -statistics(weights)[2]
#約束是所有參數(權重)的總和為1。這可以用minimize函數的約定表達如下
cons = ({"type":"eq", "fun":lambda x: np.sum(x)-1})
#我們還將參數值(權重)限制在0和1之間。這些值以多個元組組成的一個元組形式提供給最小化函數
bnds = tuple((0,1) for x in range(noa))
#優化函數調用中忽略的唯一輸入是起始參數列表(對權重的初始猜測)。我們簡單的使用平均分布。
opts = sco.minimize(min_sharpe, noa*[1./noa,], method = "SLSQP", bounds = bnds, constraints = cons)
opts
Out[115]:
status: 0
success: True
njev: 4
nfev: 28
fun: -1.1623048291871221
x: array([ -3.60840218e-16, 2.24626781e-16, 1.63619563e-01,
-2.27085639e-16, 8.36380437e-01])
message: "Optimization terminated successfully."
jac: array([ 1.81575805e-01, 5.40387481e-01, 8.18073750e-05,
1.03137662e+00, -1.60038471e-05, 0.00000000e+00])
nit: 4
得到的最優組合權重向量為:
opts["x"].round(3)
Out[116]:
array([-0. , 0. , 0.164, -0. , 0.836])
sharpe最大的組合3個統計數據分別為:
In [117]:#預期收益率、預期波動率、最優夏普指數
statistics(opts["x"]).round(3)
Out[117]:
array([ 0.508, 0.437, 1.162])
接下來,我們通過方差最小來選出最優投資組合。
#但是我們定義一個函數對 方差進行最小化
def min_variance(weights):
return statistics(weights)[1]
optv = sco.minimize(min_variance, noa*[1./noa,],method = "SLSQP", bounds = bnds, constraints = cons)
optv
Out[118]:
status: 0
success: True
njev: 7
nfev: 50
fun: 0.38542969450547221
x: array([ 1.14787640e-01, 3.28089742e-17, 2.09584008e-01,
3.53487044e-01, 3.22141307e-01])
message: "Optimization terminated successfully."
jac: array([ 0.3851725 , 0.43591119, 0.3861807 , 0.3849672 , 0.38553924, 0. ])
nit: 7
方差最小的最優組合權重向量及組合的統計數據分別為:
In [119]:optv["x"].round(3)
Out[119]:
array([ 0.115, 0. , 0.21 , 0.353, 0.322])
In [120]:
#得到的預期收益率、波動率和夏普指數
statistics(optv["x"]).round(3)
Out[120]:
array([ 0.226, 0.385, 0.587])
有效前沿有既定的目標收益率下方差最小的投資組合構成。
在最優化時採用兩個約束,1.給定目標收益率,2.投資組合權重和為1。
In [138]:def min_variance(weights):
return statistics(weights)[1]
#在不同目標收益率水平(target_returns)循環時,最小化的一個約束條件會變化。
target_returns = np.linspace(0.0,0.5,50)
target_variance = []
for tar in target_returns:
cons = ({"type":"eq","fun":lambda x:statistics(x)[0]-tar},{"type":"eq","fun":lambda x:np.sum(x)-1})
res = sco.minimize(min_variance, noa*[1./noa,],method = "SLSQP", bounds = bnds, constraints = cons)
target_variance.append(res["fun"])
target_variance = np.array(target_variance)
下面是最優化結果的展示。
叉號:構成的曲線是有效前沿(目標收益率下最優的投資組合)
紅星:sharpe最大的投資組合
黃星:方差最小的投資組合
In [139]:plt.figure(figsize = (8,4))
#圓圈:蒙特卡洛隨機產生的組合分布
plt.scatter(port_variance, port_returns, c = port_returns/port_variance,marker = "o")
#叉號:有效前沿
plt.scatter(target_variance,target_returns, c = target_returns/target_variance, marker = "x")
#紅星:標記最高sharpe組合
plt.plot(statistics(opts["x"])[1], statistics(opts["x"])[0], "r*", markersize = 15.0)
#黃星:標記最小方差組合
plt.plot(statistics(optv["x"])[1], statistics(optv["x"])[0], "y*", markersize = 15.0)
plt.grid(True)
plt.xlabel("expected volatility")
plt.ylabel("expected return")
plt.colorbar(label = "Sharpe ratio")
Out[139]:
&
自問自答,前些天作業終於交上去了!忙完了這一陣子!我就可以接著忙下一陣子了。。。
複習期間來填個坑吧。多圖預警。首先,的確得用 Excel的 solver做。
舉例說明:
第一步: 算出回報期望值和標準差:我的數據取自於TPG,Carsales,以及JBHIFI近十年來在ASX的股價記錄。
第二步: 找出協方差:
因為計算投資組合風險的公式是: 所以得先用十年的股價數據算出相應公司之間的協方差:以上,鋪墊就算完成了!
接下來重點來了: 使用solver線性規劃:
先做一個template出來,類似於這樣
然後!放大招! 規劃求解!!
我這裡取了三個公司回報率的中間值作為一個合理的要求回報率 0.21,這裡你可以隨意設置,合理就行,配比也會隨之改變。
點擊確定! 登登登登!!!下面就是見證奇蹟的時刻!
放大!
至於30組(我做了49組樣本)不同配比的曲線圖我做了下,大概是這樣的:這只是理想情況下的模型,但我想應該還是具有一定的實際意義。
至於中國股市。。感覺搞這些完全沒啥用啊 = = 以上。如果投資是這麼算出來的,巴菲特飯碗早就丟了~
你這樣不好,人家從業人員沒飯吃了。
用python或者excel都可以在MPT理論下比較簡單的解決你提到的最優問題。無非就是用復權後的收盤價,算出收益率,算出方差協方差矩陣(也可不算,但是後續計算量稍大一點),建立好模型之後,然後在約束條件下求解.你提到的「最大回報」如果是在考慮風險下的話,約定個無風險然後求sharpe的最大值就好。
關於回復中提到的做前沿圖像的,我看回復中無論是Python還是excel都在採用約束條件下的最優化求解。其實前沿曲線的表達,只需要確定了兩個線上的組合,就完全可以表達出完整的前沿曲線,不需要再進行過多變動約束條件下的求解,這一點在excel的解決上可以省下一些資源。
用python的回答,基本上和Yves Hilpisch寫的python for finance中用到的方法和思路一致。excel上如果能充分的運用模擬運算表格,效率也不差。如果你數據量和計算量很大,python優勢會強很多很多,就這個列子而言,我在python環境下從數據獲取(6種3年日報價)到十萬種以上情況的模擬結束,也就幾秒鐘。如果在excel下,可能效率要差很多。不過回復中進行了4000次,只要你在excel下有類似wind之類的載入項能讓你快速下載到數據,那麼二者在這個級別下的計算效率基本差不多。
馬可維茲的模型裡面對你這種需求有著經典的分析。
什麼樣的基金投資組合方案好?構建股票基金投資組合方案時要注意哪些?
題主還要給出對於投資者風險偏好,簡單來說就是indifferent curve
數據有沒有更多的假設呢?
沒有就認為一切都是美好的。首先,股價沒什麼用了。
財富w=a1+a2+a3,三個a分別是買各股花的錢。R=E(a1r1+a2r2+a3r3)=a1Er1+a2Er2+a3Er3VAR=var(a1r1+a2r2+a3r3)=a1^2 var(r1)+a1^2 var(r2)+a3^2 var(r3)+a1a2cov(r1,r2)+a3a1cov(r3,r1)+a2a3cov(r2,r3)不能知道你這個市場是不是完備的。
線性規劃的話,LL是你喜歡的方差值,你可以多帶幾個進去,方便畫均值方差的前沿回報,得出來的解不一定是唯一的max Rs.t.VAR=LL w=a1+a2+a3當然可能這個更好,EE是期望回報,不過計算機不傻,一定能發現是二次規劃的
min VARs.t.R=EEw=a1+a2+a3隨機算出
還要結合個人的效用來算啊,所以風險偏好也要考慮的
推薦閱讀:
※為什麼流通中現金不能創造基礎貨幣?
※如何理解「貨幣流通次數」這個概念?在經濟活動中的具體表現是什麼?
※能用遊戲中的道具貨幣把遊戲公司買下來嗎?
※城市形成的原因是什麼?