【研究】倉位管理大殺器:凱利公式你用對了嗎?

今天我們介紹一個神奇的人,和他神奇的公式。目前網路上傳播較廣的一篇講凱利公式前世今生的文章,個人認為深度不夠,而且思路是有問題的。大家不要看多了走偏路。最近也花了一些力氣做梳理,把這篇分享出來,盡量做到講對,講透,也是提醒各位,低頭挖礦,不要搞錯了挖礦的初衷。

一、故事背景

市場不好的時候,我們總是會猶豫,滿倉?半倉?還是空倉?有沒有一個科學的辦法給出一個標準答案呢?下面來看看倉位管理神器——凱利公式

投資(ji)就是一場賭博。像索普、香農等很多投資大師早期都對研究賭博業的秘密情有獨鍾,科學家們總是希望從理論上找到賭博遊戲的必勝策略,使得一場遊戲中贏的概率遠遠高過輸的概率。

凱利就是這樣一個大師。他是香農(資訊理論創始人)在貝爾實驗室的同事,這個來自德克薩斯州、愛擺弄手槍、喜歡一根接一根抽煙的狂野硬漢,干過很多惡作劇,特別喜歡將填滿塑料的子彈射進他客廳的牆壁里來戲弄家裡暫住的客人。他的研究領域從量子物理學到電視信號解碼,發明了能夠準確模擬人類聲音的電腦設備。最廣為人知的研究貢獻,便是將香農的資訊理論運用到了賽馬賭博中。

凱利用這樣一個精巧簡潔的公式,將資訊理論與賭博之間的本質聯繫揭露出來,告訴我們在有限了解的信息下,如何下注能使得資本增值的速度最大化。

二、賭博怎麼用凱利公式?

最早的凱利公式是運用在賭博遊戲中的,我們先看看賭博情形下凱利公式的特殊形式:

f:下注比例

Pwin:賭贏的概率

Ploss:賭輸的概率(=1-Pwin)

b:賠率,押1賠b(這個賭球的朋友們是不陌生啦)

特殊形式凱利公式的證明過程(此處感謝@程峰的建議)

我們可以做一個簡單的證明。資金曲線asset對f求導,就可以得到特殊形式下的凱利公式。

In[0]:

from sympy import *nf,b,pwin = symbols(f b pwin)n#資金曲線assetnasset = pwin*log(1 + b*f) + (1 - pwin)*log(1-f)n#資金曲線增長最大,即asset對f求導=0時f的值nsolve(diff(asset,f),f)n

Out[0]:

[(b*pwin + pwin - 1)/b]n

舉個簡單的例子

假想一個遊戲。贏的概率是60%,輸的概率40%。入場費隨意交。如果贏了獲得2倍的入場費金額(1賠1),輸則輸掉入場費。小米有100元做本金,請問小米每次給多少入場費,理論上4次遊戲後幾何期望收益能最大?

然後我拿凱利公式算了一下,最佳的策略是每次投剩餘本金的20%。

f = (1×0.6-0.4)/1 = 0.2。

基於上述的例子,做個簡單的蒙特卡洛模擬實驗(進行200次遊戲):

In[1]:

from pandas import DataFramenbase = 100npwin = 0.6nploss = 1-pwinnb = 1nc = 1nrnd_position = 0.25nrnd_position2 = 0.15nkelly_position = (pwin*b - ploss)/bnstopline = 1nprint kelly position is %s%kelly_positionnport_A = DataFrame()nport_B = DataFrame()nport_C = DataFrame()nport_D = DataFrame()n#重複模擬次數nfor i in range(1000): n port1 = [base]n port2 = [base]n port3 = [base]n port4 = [base]n #遊戲進行次數n for step in range(200):n rnd = random.random()n if rnd < pwin:n next_step = bn else:n next_step = -cn if port1[-1] > base*(1-stopline):n port1.append(port1[-1]*(1+next_step))n else:n port1.append(port1[-1])n if port2[-1] > base*(1-stopline):n port2.append(port2[-1]*(1+next_step*kelly_position))n else:n port2.append(port2[-1])n if port3[-1] > base*(1-stopline):n port3.append(port3[-1]*(1+next_step*rnd_position))n else:n port3.append(port3[-1])n if port4[-1] > base*(1-stopline):n port4.append(port4[-1]*(1+next_step*rnd_position2))n else:n port4.append(port4[-1])n port_A[i] = port1n port_B[i] = port2n port_C[i] = port3n port_D[i] = port4nplt.figure(figsize = (8,5))nplt.plot(exp(log(port_A.T).sum()/1000),label = port1:full)nplt.plot(exp(log(port_B.T).sum()/1000),*,label = port2:kelly)nplt.plot(exp(log(port_C.T).sum()/1000),label = port3:0.25)nplt.plot(exp(log(port_D.T).sum()/1000),label = port4:0.15)nplt.legend(loc = 0)nprint n不同組合的幾何期望收益nprint full position %s%exp(log(port_A.T).sum()/1000).iloc[-1]nprint kelly position %s%exp(log(port_B.T).sum()/1000).iloc[-1]nprint position = 0.25 %s%exp(log(port_C.T).sum()/1000).iloc[-1]nprint position = 0.15 %s%exp(log(port_D.T).sum()/1000).iloc[-1]n

Out[1]:

觀察四種操作方式:滿倉下注、按凱利公式下注20%、按25%下注、按15%下注

圖為進行200次遊戲之後幾何期望資金曲線的情況

凱利無疑是增長最快的!

從另一個角度,我們來理解一下

不同賠率下,贏的概率多大我們會選擇入場參與遊戲?

還是上面的遊戲,如果贏的概率40%,輸的概率60%,那麼,期望凈收益就是(1×0.4-0.6)< 0;從概率的角度說,一個期望凈收益為負的遊戲是不值得參與的,求得的f小於0,也就是不下注。

下面看一下不同賠率下一個遊戲賭贏的概率為多少才值得參加?

同樣,用實驗來觀察:

In[2]:

import numpy as npnfrom mpl_toolkits.mplot3d import Axes3Dnb = np.linspace(20,1,20)npwin = np.linspace(0,1,20)nb,pwin = np.meshgrid(b,pwin)nkelly = (b*pwin-(1-pwin))/b*(b*pwin-(1-pwin)>=0)nzero = 0nfig = plt.figure(figsize = (10,6))nax = fig.gca(projection = 3d)nsurf = ax.plot_surface(b,pwin,kelly,rstride=1, cstride=1,cmap = plt.cm.coolwarm)nax.plot_surface((1-pwin)/pwin,pwin,0)nax.set_xlabel(b 賠率)nax.set_ylabel(pwin 贏概率)nax.set_zlabel(kelly 下注比例)nfig.colorbar(surf,shrink = 0.6,aspect = 10)n

Out[2]:

上圖說明兩個問題:

1. 如果一次賭博賠率越大,在贏的概率較小的情況下,凱利公式就開始提示要下注啦。(如圖賠率為20時,只需要10%的贏率就可以入場玩啦)

2. 同一賠率下,凱利公式只有在穩贏(贏概率=100%)時才會支持押下全部本金,否則都是本金的一定比例。也即永遠不會輸完所有的錢。

三、炒股怎麼用凱利公式?

凱利的論文給出的押注策略,神奇之處就在於,當你總是遵循這一準則進行操作,你就能預測接下來發生的事情,你也能清楚的知道你的財富增長速度是在控制住風險情況下最優的結果。

來看看凱利運用他的財富公式,專門成立的hedge fund 的performance~20年15倍,就是辣么厲害。

數據:《財富公式:玩轉拉斯維加斯和華爾街的故事》

那麼問題來了,我們量化炒股如何引入這麼神奇的倉位管理神器?

因為股市的漲跌我們不會一次性賠光本金,所以引入損失率對凱利公式做微調,即更一般性的凱利公式:

f:倉位比例

Pwin:賭贏的概率—股市上漲概率

Ploss:賭輸的概率—股市下跌概率

b:贏錢率(資產從1增加到1+b)

c:損失率(資產從1減少到1-c)

一般性凱利公式的證明過程(再次感謝@程峰的提議,在此加上證明過程)

一次投資過程,壓上總資本(A)的一定比例:f*A。有pwin的概率贏,贏了財富為A*(1+fb),ploss的概率會輸,輸了資本變為A*(1-fc)。N次投資後,總資本函數為:

凱利公式要做的是使得總資本曲線的幾何收益最大,也就是log(An)/N最大。即log(AN)/N對f求導=0時f的值就是凱利公式了~

仔細想一個問題(挖礦秘籍)

賭博和買股票,贏概率Pwin和輸概率Ploss究竟是什麼?

賭博的時候,Pwin和Ploss是根據遊戲規則算出的概率而定。比如投硬幣(Pwin=Ploss=0.5),或者轉輪盤,撲克等更為複雜的遊戲。

而買股票的過程,是n次離散賭博的過程。當你找到一個有效信號之後進行一次操作(比如有效信號是價格突破5日均線,財務數據好,成交量放大,或者各種金叉死叉等等。。)

假設我們找到了一個有效信號,信號發生時,股價為S。我們提前給定價格S(1+b)和S(1-c)作為信號發生後止盈和止損的邊界,這個時候的Pwin和Ploss應該是基於歷史這個信號的收益情況做數據統計分析勝率(贏概率)和敗率(輸概率)來給出,也即價格觸碰到S(1+b)止盈的概率是Pwin,觸碰到S(1-c)止損的概率是Ploss。

關於信號這部分的可視化的理解,可參見好多凱利公式的文章,但好像沒有說透徹的……。這篇是與JoinQuant的小編討論後發布在JQ社區的一篇文章。

又舉一個簡單例子

有效信號:當前價突破5日均線

統計樣本:100隻相似股票,過去三年有效信號發生了1000次

統計包含:假定上漲20%止盈,下跌20%止損。止盈贏錢的次數57次,止損輸錢的次數43次

對應公式的參數:Pwin=0.57,Ploss=0.43,b=0.20,c=0.20

此時f=Pwin/c – Ploss/b = 0.57/0.20 – 0.43/0.20= 70%

按照我們對某一個有效信號做歷史統計定出來的Pwin,Ploss,b和c來進行模擬的投資組合看看看效果:

In[3]:

from pandas import DataFramenbase = 100npwin = 0.57nploss = 1-pwinnb = 0.2nc = 0.2n# stopline後文會介紹nstopline = 1nrnd_position = 0.6nrnd_position2 = 0.9nkelly_position = (pwin/c - ploss/b)*stoplinenprint kelly position is %s%kelly_positionnport_A = DataFrame()nport_B = DataFrame()nport_C = DataFrame()nport_D = DataFrame()n#重複模擬次數nfor i in range(1000):n port1 = [base]n port2 = [base]n port3 = [base]n port4 = [base]n #投資次數步長n for step in range(500):n rnd = random.random()n if rnd < pwin:n next_step = bn else:n next_step = -cn if port1[-1] > base*(1-stopline):n port1.append(port1[-1]*(1+next_step))n else:n port1.append(port1[-1])n if port2[-1] > base*(1-stopline):n port2.append(port2[-1]*(1+next_step*kelly_position))n else:n port2.append(port2[-1])n if port3[-1] > base*(1-stopline):n port3.append(port3[-1]*(1+next_step*rnd_position))n else:n port3.append(port3[-1])n if port4[-1] > base*(1-stopline):n port4.append(port4[-1]*(1+next_step*rnd_position2))n else:n port4.append(port4[-1])n port_A[i] = port1n port_B[i] = port2n port_C[i] = port3n port_D[i] = port4nplt.figure(figsize = (8,5))nplt.plot(exp(log(port_A.T).sum()/1000),label = port1:full)nplt.plot(exp(log(port_B.T).sum()/1000),label = port2:kelly)nplt.plot(exp(log(port_C.T).sum()/1000),label = port3:position = 0.6)nplt.plot(exp(log(port_D.T).sum()/1000),label = port3:position = 0.9)nplt.legend(loc = 0)nprint n不同組合的幾何期望收益nprint full position %s%exp(log(port_A.T).sum()/1000).iloc[-1]nprint kelly position %s%exp(log(port_B.T).sum()/1000).iloc[-1]nprint position = 0.6 %s%exp(log(port_C.T).sum()/1000).iloc[-1]nprint position = 0.9 %s%exp(log(port_D.T).sum()/1000).iloc[-1]n

Out[3]:

同樣四種倉位操作後的資金曲線來進行比較:

1. 凱利公式下資金曲線增長是最快的。

2. 高於或低於凱利公式的比例資金曲線增長都不是最快的。

再思考一個問題:關於槓桿

再多舉一個例子:f>1

研究不能止步於此啊。很多知道凱利公式的朋友都有的疑問,是凱利計算出來的倉位容易過大。比如一不小心就提示幾倍,幾十倍了。這是什麼情況呢?

比如我們找到一個信號:Pwin=0.7,Ploss=0.3,b=0.20,c=0.20

來看看實驗結果(代碼同上,只修改上述參數)

Out[4]:

f>1了,甚至等於4了,什麼意思!!凱利公式在告訴你這個信號太好了,值得你做4倍的槓桿來操作~!什麼,你說我多加一點好不好,看上圖,加到6倍顯然就挫了。。。

(想知道凱利公式為何能做到幾何期望收益最大化,證明過程戳wiki百科自行科普)

再思考一個止損的問題,stopline不為1

上面槓桿的問題引出其實說明了A股版凱利公式暗含的一個假設

資金可以隨意無摩擦地加槓桿操作,無借貸成本。

什麼意思。一個好的信號,凱利會告訴你在已知風險(Pwin,Ploss,b和c)的情況下,最優的槓桿是多少。你可以毫不猶豫的就按這個槓桿去操作,最大化自己的資金曲線。

那麼真實情況下呢,我們可能不加槓桿,而且也不能承受全部本金損失掉的風險。也就是,我們stopline會小於1,甚至只到30%或者20%。那這時候凱利公式怎麼用?

這裡不做實驗,僅拋個引子。感興趣的朋友可以繼續深入研究,也歡迎與我探討。

A. 靜態止損:即虧損本金的固定數額後撤出投資

kelly_position = (pwin/c - ploss/b)×stopline

stopline應為此時剩餘可承受的損失/本金base。

舉例:base=100元,輸20元止損。initial_stopline = 0.2。假設損失率c = 0.04

第一次,賠了4塊,base=96,stopline = (20-4)/96 = 0.16

第n次,輸輸贏贏後,base = 250,stopline = (150+20)/250 = 0.68

B. 動態止損:即虧損剩餘資金的一定比例後撤出投資

比如動態20%止損。base =100元,賺到200元後,如虧損到160元即止損。

這個具體實驗就留給各位自己研究啦~~

Bonus:小結一下

好啦,少年。真正賺錢的是找有效的因子or信號,使得Pwin儘可能大,b儘可能大。無論是以往大家關注的一些技術指標(各種金叉、死叉)還是量價指標(放量、突破等等)又或者是財務指標,都可以作為一個信號。

統計歷史信號出現時的一個表現,得到這個信號產生的收益的分布。只要這個信號的收益分布正偏一些些,就是純純的Alpha啊。當然這個因子or信號的挖掘,就是作為礦工孜孜不倦追求的終極目標了。當你找到這樣一個神奇的信號,配上凱利公式會讓你的財富增加更快~

好啦,說完啦。挖信號去了~

致謝

本文研究工具為IPython Notebook 2.7。API來自聚寬(JoinQuant),在此表示感謝。

更多擴展可見:好多凱利公式的文章,但好像沒有說透徹的……

關於凱利和他的財富公式,有一本書專門介紹這個。財富公式:玩轉拉斯維加斯和華爾街的故事.PDF,密碼:i8fi。

最後:附上凱利的論文,A New Interpretation of Information Rate

資源共享,是人類進步的推動力

『分享文章+關注公眾號』

回復『大數據書籍』or『量化書籍』領取

更多內容:神秘的寬客們 - 知乎專欄

推薦閱讀:

Quant 應該學習哪些 Python 知識?
一名優秀的 Quant 都需要具備哪些職業素養和技能?
Quant 會有哪些資訊來源?會看哪些博客或者出版物?
Stochastic Calculus 在現實的 Quant 世界中到底可以幹什麼?
軟體工程專業女生想做Quant,本科出國後需要讀那個專業的Phd或master呢?

TAG:宽客Quant | 投资 | 程序化交易 |