三支股票 A.B和C,請問該如何算出最優的投資組合配比(最大回報,最小風險)?

已知各股的

股價

期望回報率

標準差

兩兩之間的協方差

總投資金額

想求出最大回報 最小風險的組合配比,該怎麼做?就是A B C 各佔多少投資金額的百分比最好?

有人說用excel線性規劃做,實際操作起來不知該從何下手,求助。


看題主的組合才3隻股票就搞得很複雜了。。。

這兩天剛用python做了下投資組合理論的驗證。要是會點編程,別說A、B、C三隻股票了,就是整個上證+深證三千多隻股票也沒問題的。

原文見:【組合管理】——投資組合理論(有效前沿)

源碼都貼上了,現在這時代不會點編程都吃不飽飯了,感興趣的可以搬去用不謝。

------------------------------------------2016.2.26更新----------------------------------------------------

ps:有人問到這個分析是在哪兒做的。我也是對量化策略感興趣,最近用JoinQuant的平台在做些研究,順便分享出來和大家一起交流。

--------------------------------------------------------------------------------------------------------------

正態性檢驗和蒙特卡洛完成投資組合優化

by 陳小米。

最近一直在思考怎樣有效的配置資產組合。 很多時候根據條件選好股票池之後,通常簡單粗暴的等分倉位給每隻股票。 其實,這個過程中有很多可以優化的空間。

下面,給大家分享一下如何運用有效前沿進行資產組合優化。

PART ONE: 正態性檢驗

這部分是附贈福利。只對資產組合優化感興趣的朋友可以直接跳到PART TWO。

(知乎回答字數限制,這部分暫且刪除,感興趣的到原文鏈接自己看哦~)

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]:

&

2.計算不同證券的均值、協方差

每年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]:

3.給不同資產隨機分配初始權重

由於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])

4.計算預期組合年化收益、組合方差和組合標準差

In [106]:

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

5.用蒙特卡洛模擬產生大量隨機組合

進行到此,我們最想知道的是給定的一個股票池(證券組合)如何找到風險和收益平衡的位置。

下面通過一次蒙特卡洛模擬,產生大量隨機的權重向量,並記錄隨機組合的預期收益和方差。

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]:

&

6.投資組合優化1——sharpe最大

建立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

得到的最優組合權重向量為:

In [116]:

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])

7.投資組合優化2——方差最小

接下來,我們通過方差最小來選出最優投資組合。

In [118]:

#但是我們定義一個函數對 方差進行最小化
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])

8.組合的有效前沿

有效前沿有既定的目標收益率下方差最小的投資組合構成。

在最優化時採用兩個約束,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+a3Er3

VAR=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 R

s.t.VAR=LL

w=a1+a2+a3

當然可能這個更好,EE是期望回報,不過計算機不傻,一定能發現是二次規劃的

min VAR

s.t.R=EE

w=a1+a2+a3


隨機算出


還要結合個人的效用來算啊,所以風險偏好也要考慮的


推薦閱讀:

為什麼流通中現金不能創造基礎貨幣?
如何理解「貨幣流通次數」這個概念?在經濟活動中的具體表現是什麼?
能用遊戲中的道具貨幣把遊戲公司買下來嗎?
城市形成的原因是什麼?

TAG:投資 | 理財 | 股票 | 經濟學 | 投資組合 |