关于证券收益分布原因的讨论

之前机器学习帖子中有一个图展示了过去十年HS300每日收益率的分布直方图,看起来是个钟样,可是为什么这个样呢?这引起了我的兴趣,我觉得有必要探究探究原因。


实际上,收益的分布问题是个严肃而有意义的问题。合理的分布假设能告知风险管理要求的极端价格变化的概率估计,期权交易中Black-Scholes期权定价模型假定资产价格对数正态分布, Modern Portfolio Theory中假定收益为正态分布。还有很多著名模型均建立在该问题之上。


要弄清证券收益分布背后的原理,我们可以追溯到概率论中的中心极限定理(Central Limit Theorem),关于变量的分布结论许多都是依赖于分布的具体类型。但是对于中心极限定理,它不但对于任意分布都成立,还特别提示我们:要特别注意正态分布。我们下面看看,中心极限定律是如何说的。


中心极限定律

随机变量$X_1,X_2,…,X_n$是相互独立的随机变量,并有相同的分布(IID, Independent & Identically Distributed)。分布的期望为μ,方差为$σ^2$,μ, σ 都为有限值,且σ ≠ 0。这些随机变量的均值为$\overline{X}$=$\frac{1}{n}$\sum_{i=1}^n X_i$。让$\zeta_n$=$\frac{\overline{X}-μ}{σ/\sqrt{n}}$,那么

$lim_{n \rightarrow +\infty} P(ζ_n≤z)=Φ(z)$

其中$Φ(z)$是标准正态分布的分布函数。

简单来说,我们寻找n个IID随机变量的均值$\overline{X}$。当n趋近无穷时,这个均值(一个新的随机变量)趋近一个正态分布。(实际上这n个IID随机变量的和也服从正态分布)

(通过$ζ_n$的变换,可以从正态分布的$\overline{X}$导出标准正态分布$ζ_n$。)


我们进行一个演示:

下面取n个IID随机变量,让它们都符合λ=1的指数分布,并观察它们均值的分布状况。为得到分布,我们使用随机数生成器,来进行10000次采样。每次实验获得一组随机变量的取值,得到一个均值。总共获得10000个均值。绘制均值分布的直方图。

分三种情况,分别让n等于1,20, 100:

# Central Limit Theory 
# X is exponential distribution with lambda = 1 

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import expon

# Get one sample of (X1 + X2 + ... + XN)/N 
def sample_mean(N):
    # exponential distribution, with lambda = 1 
    one_sample = expon.rvs(scale = 1, size = N)
    return one_sample.mean()

# Increase N: 1, 20 , 1000. 
# Demo of Central Limit Theory in histogram
plt.figure(figsize=(12, 4))
for N, subp in zip([1, 20, 1000], [131, 132, 133]):
    # generate samples 
    all_means = np.array([sample_mean(N) for i in range(10000)])

    # plot figure
    plt.subplot(subp)
    plt.hist(all_means,bins=100,color="red", alpha=0.3)
    plt.title('Central Limit Theory n=%i' % N)
    plt.xlabel('sample means')
    plt.ylabel('Frequency')

plt.tight_layout()

下载.png

在第一种情况下,$\overline{X}$=$X_1/1=X_1$,即$\overline{X}$本身是指数分布。

在第二、三种情况下,均值的分布越来越偏离一个指数分布,分布的形状不断趋近于一个正态分布。

如果你有兴趣,可以测试均值分布等其他分布,你会发现结果一致。


收益分布推导

有了中心极限定理,下面可以以此为基础进行推导了。我们定义收益$R_t$:

$R_t = ln({P_t}/{P_{t-1}})$

这里注意,我们这样定义有别于传统的定义方法,具体原因,这里 有详细的解释。对于某一天的收益而言,它由更小区间时间段的收益累计而成,时间间隔$\Delta=1/T$的变量$ln({P_{t+\Delta}}/{P_{t}})$,这样的小间隔连续复利回报可看做随机变量(无所谓什么分布),对该天收益有:

$ln({P_{t+\Delta}}/{P_t}) + ln({P_{t+2\Delta}}/{P_{t+\Delta}}) + ln({P_{t+3\Delta}}/{P_{t+2\Delta}}) + … + ln({P_{t+T\Delta}}/{P_{t+(T-1)\Delta}})=ln({P_{t+T\Delta}}/{P_{t}})$

$ln({P_{t+T\Delta}}/{P_{t}}) = ln({P_{t+1}}/{P_{t}}) = R_{t+1}$

当T足够大时,每日收益可以看做无数小的交易区间的收益之和,这些和(一个新的变量)的分布,根据中心极限定理,从理论上解释为什么大量日收益服从正态分布。

收益分布验证

根据上面的一番推导,理论上可以说得通了,但是实际情况什么样,这需要动手验证,我们以SP500指数为对象,研究自1993年以来,它的每日收益的分布状况并将分布数据标准化后得到概率密度函数曲线与标准正态分布曲线进行比较。

import numpy as np
import pandas as pd
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from scipy.stats.kde import gaussian_kde

mu = 0
sigma = 1
normaldata = np.linspace(-10,10,1000)
plt.plot(normaldata, mlab.normpdf(normaldata, mu, sigma), 'r--')

df_us_long = get_price('SPY.US', country='us', start_date='1993-01-29', end_date='2015-08-10', frequency='daily')
returns_us_ln = np.log(df_us_long['ClosingPx'] / df_us_long['OpeningPx'])
returns_us_ln_normalized = (returns_us_ln - np.mean(returns_us_ln))/np.std(returns_us_ln)

data = returns_us_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
plt.plot( dist_space, kde(dist_space) )
plt.legend(['Standard normal distribution', 'SPY returns PDF'])
plt.xlabel('Scaled return')
plt.ylabel('PDF')
plt.show()

下载 (1).png

介于底部看得不是很清楚,我们调整后有图:

mu = 0
sigma = 1
normaldata = np.linspace(-10,10,1000)
plt.plot(normaldata, mlab.normpdf(normaldata, mu, sigma), 'r--')
df_us_long = get_price('SPY.US', country='us', start_date='1993-01-29', end_date='2015-08-10', frequency='daily')
returns_us_ln = np.log(df_us_long['ClosingPx'] / df_us_long['OpeningPx'])
returns_us_ln_normalized = (returns_us_ln - np.mean(returns_us_ln))/np.std(returns_us_ln)
data = returns_us_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
plt.plot( dist_space, kde(dist_space) )
plt.legend(['Standard normal distribution', 'SPY returns PDF'])
plt.xlabel('Scaled return')
plt.ylabel('PDF')
plt.ylim(0, 0.01)
plt.show()

下载 (2).png

我们可以看见与标准正态分布比较有明显的尖顶及肥尾现象。可见对于顶部及尾部而言正态分布的假设并不是那么完美,例如1987年10月19,SP500暴跌20.5%,如果我们以20年为观察年限的话,我们可粗略认为每20年出现一次,而如果我们依据正态分布的假设理论计算,结果会是$2×10^{76}$年!

收益分布比较

我们可以将SPY500与HS300收益数据分布进行比较,数据起始时间统一从2005-01-05开始:

import numpy as np
import pandas as pd
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from scipy.stats.kde import gaussian_kde

fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(16, 8))

mu = 0
sigma = 1
normaldata = np.linspace(-10,10,1000)
ax0.plot(normaldata, mlab.normpdf(normaldata, mu, sigma), 'r--')

df_us_short = get_price('SPY.US', country='us', start_date='2005-01-05', end_date='2015-08-10', frequency='daily')
returns_us_ln = np.log(df_us_short['ClosingPx'] / df_us_short['OpeningPx'])
returns_us_ln_normalized = (returns_us_ln - np.mean(returns_us_ln))/np.std(returns_us_ln)

df_cn_short = get_price('CSI300.INDX', country='cn', start_date='2005-01-05', end_date='2015-08-10', frequency='daily')
returns_cn_ln = np.log(df_cn_short['ClosingPx'] / df_cn_short['OpeningPx'])
returns_cn_ln_normalized = (returns_cn_ln - np.mean(returns_cn_ln))/np.std(returns_cn_ln)

data = returns_us_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
ax0.plot( dist_space, kde(dist_space) )

data = returns_cn_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
ax0.plot( dist_space, kde(dist_space) )
ax0.legend(['Standard normal distribution', 'SPY returns PDF', 'HS300 returns PDF'])


ax1.plot(normaldata, mlab.normpdf(normaldata, mu, sigma), 'r--')

data = returns_us_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
ax1.plot( dist_space, kde(dist_space) )

data = returns_cn_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
ax1.plot( dist_space, kde(dist_space) )
ax1.set_ylim((0, 0.01))
ax1.legend(['Standard normal distribution', 'SPY returns PDF', 'HS300 returns PDF'])
<matplotlib.legend.Legend at 0x7f6335553fd0>

下载 (3).png

我们再想想中心极限定理,回过头思考中心极限定理中提到的条件,有如下三个:

1.随机变量必须出自同一分布

2.必须独立

3.有限的均值与方差

而对于实际的金融数据,这三个条件是有回旋余地的,比如,变量可以不是完全独立分布,只要不存在个别变量较其他变量而言会极大程度影响到均值,甚至,变量之间有微弱的关系。事实上,中心极限定律是一个还在积极研究中的领域,而对于收益分布的假设模型后来也有不少学者做了补充与完善,有兴趣可以查阅关于广义的中心极限定理以及稳定分布的论文与资料。

另外一个问题……

在讨论收益问题查阅资料的时候遇到了关于价格分布的讨论,有学者使用中心极限定理给出证明,但我测试了SP500的表现却差距很大,我想原因可能是假设部分存在漏洞或是理论与现实本就存在出入,这里给出证明的过程希望组里大神可以指点一些。


我们用$R_i$代表从第$i-1$天到第$i$天的股票收益,我们有:

$S_1 = S_0(1 + R_1)$

$S_1$代表股票的初始价格,那么$n$天后,有:

$S_n = S_0\prod_{i=1}^n (1 + R_i)$

股票价格由由初始值与根据市场不确定性存在的n个因素共同作用得到,每个因素是一个随机的回报,我们等式两边取对数:

$ln(S_n) = ln(S_0) + \sum_{i=1}^nln(1+R_i)$

再对照中心极限定理,如果每个$R_i$随机,则$ln(1+R_i)$随机,因而$ln(S_n)$为大量随机变量之和,只要$R_i$独立同分布且$ln(1+R_i)$的均值方差有限,根据中心极限定理$ln(S_n)$为正态分布。


以下是使用SP500的数据验证$ln(S_n)$的分布,我想没有其他问题的话,这就是理论与现实的差距吧:

mu = 0
sigma = 1
normaldata = np.linspace(-10,10,1000)
plt.plot(normaldata, mlab.normpdf(normaldata, mu, sigma), 'r--')

df_us_long = get_price('SPY.US', country='us', start_date='1993-01-29', end_date='2015-08-10', frequency='daily')['ClosingPx']
df_us_long_ln = np.log(df_us_long)
df_us_long_ln_normalized = (df_us_long_ln - np.mean(df_us_long_ln))/np.std(df_us_long_ln)

data = df_us_long_ln_normalized
kde = gaussian_kde( data )
dist_space = np.linspace( min(data), max(data), 100 )
plt.plot( dist_space, kde(dist_space) )
plt.legend(['Standard normal distribution', 'SPY prices PDF'])
plt.xlabel('Scaled return')
plt.ylabel('PDF')
plt.show()

下载 (4).png

主要参考:

[1]Wilmott, P 2006 Paul Wilmott on Quantitative Finance, second edition

[2]Mandelbrot, B & Hudson, R 2004 The (Mis)Behaviour of Markets: A Fractal View of Risk, Ruin and Reward. Profile Books

[3]Feller, W 1968 An Introduction to Probability Theory and Its Applications, third edition. John Wiley & Sons Inc, New York