[量化学堂-数学知识]数据集中趋势的度量:平均值

集中趋势
平均值
标签: #<Tag:0x00007f5bffcd3e50> #<Tag:0x00007f5bffcd3590>

(iQuant) #1

导语:本文我们将讨论如何使用平均值来描述一组数据。


克隆策略

算术平均值

算术平均值非常频繁地用于描述一组数据,即“平均值”。 它被定义为观测的总和除以观测个数:

$$\mu = \frac{\sum_{i=1}^N X_i}{N}$$

这里 $X_1, X_2, \ldots , X_N$ 是我们的观测值.

In [1]:
# 两个常用的统计包
import scipy.stats as stats
import numpy as np

# 我们拿两个数据集来举例
x1 = [1, 2, 2, 3, 4, 5, 5, 7]
x2 = x1 + [100]

print('x1的平均值:', sum(x1), '/', len(x1), '=', np.mean(x1))
print('x2的平均值:', sum(x2), '/', len(x2), '=', np.mean(x2))
x1的平均值: 29 / 8 = 3.625
x2的平均值: 129 / 9 = 14.3333333333

我们还可以定义一个加权算术平均值,加权算术平均值计算定义为:

$$\sum_{i=1}^n w_i X_i $$

这里 $\sum_{i=1}^n w_i = 1$. 在通常的算术平均值计算中,对所有的$i$ 都有$w_i = 1/n$.

中位数

顾名思义,一组数据的中位数是当以递增或递减顺序排列时出现在数据中间位置的数字。 当我们有奇数n个数据点时,中位数就是位置(n + 1)/ 2的值。 当我们有偶数的数据点时,数据分成两半,中间位置没有任何数据点; 所以我们将中位数定义为位置n / 2和(n + 2)/ 2中的两个数值的平均值。

数据中位数不容易受极端数值的影响。 它告诉我们处于中间位置的数据。

In [2]:
print('x1的中位数:', np.median(x1))
print('x2的中位数:', np.median(x2))
x1的中位数: 3.5
x2的中位数: 4.0

众数

众数是数据集中出现次数最多的数据点。 它可以应用于非数值数据,与平均值和中位数不同。

In [3]:
# Scipy具有内置的求众数功能,但它只返回一个值,即使两个值出现相同的次数,也是只返回一个值。

print('One mode of x1:', stats.mode(x1)[0][0])

# 因此我们自定义一个求众数的函数
def mode(l):
    # 统计列表中每个元素出现的次数
    counts = {}
    for e in l:
        if e in counts:
            counts[e] += 1
        else:
            counts[e] = 1
            
    # 返回出现次数最多的元素
    maxcount = 0
    modes = {}
    for (key, value) in counts.items():
        if value > maxcount:
            maxcount = value
            modes = {key}
        elif value == maxcount:
            modes.add(key)
            
    if maxcount > 1 or len(l) == 1:
        return list(modes)
    return 'No mode'
    
print('All of the modes of x1:', mode(x1))
One mode of x1: 2
All of the modes of x1: [2, 5]

可以看出,我们自定义的mode函数更加合理.

对于可能呈现不同数值的数据,比如收益率数据,也许收益率数据没有哪个数据点会出现超过一次。在这种情形下,我们可以使用bin值,正如我们构建直方图一样,这个时候我们统计哪个bin里数据点出现次数最多

In [4]:
# 获取收益率数据并计算出mode
start = '2014-01-01'
end = '2015-01-01'
pricing = D.history_data('000002.SZA', fields=['close'], start_date=start, end_date=end)['close']
returns = pricing.pct_change()[1:]
print('收益率众数:', mode(returns))

# 由于所有的收益率都是不同的,所以我们使用频率分布来变相计算mode
 
hist, bins = np.histogram(returns, 20) # 将数据分成20个bin
maxfreq = max(hist)
# 找出哪个bin里面出现的数据点次数最大,这个bin就当做计算出来的mode
print('Mode of bins:', [(bins[i], bins[i+1]) for i, j in enumerate(hist) if j == maxfreq])
收益率众数: [0.0]
Mode of bins: [(-0.0030533790588378878, 0.0055080294609069907)]

确实如此,在收益率数据中,很多数据点都不一样,因此计算众数的方式就显得有失偏颇。我们此时转化了思路,不是计算众数,而是将数据分成很多个组(bin),然后找出数据点最多的组(bin)来代替收益率数据的众数(mode)

几何平均值

虽然算术平均值使用加法,但几何平均值使用乘法:

$$ G = \sqrt[n]{X_1X_1\ldots X_n} $$

该式子等价于: $$ \ln G = \frac{\sum_{i=1}^n \ln X_i}{n} $$

几何平均值总是小于或等于算术平均值(当使用非负观测值时),当所有观测值都相同时,两者相等。

In [ ]:
# 使用Scipy包中的gmean函数来计算几何平均值
print('x1几何平均值:', stats.gmean(x1))
print('x2几何平均值:', stats.gmean(x2))

如果在计算几何平均值的时候遇到负数的观测值,怎么办呢?在资产收益率这个例子中其实很好解决,因为收益率最低为-1,因此我们可以+1将其转化为正数。 因此我们可以这样来计算几何收益率:

$$ R_G = \sqrt[T]{(1 + R_1)\ldots (1 + R_T)} - 1$$
In [ ]:
 
# 在每个元素上增加1来计算几何平均值

ratios = returns + np.ones(len(returns))
R_G = stats.gmean(ratios) - 1
print('收益率的几何平均值:', R_G)

几何平均收益率是将各个单个期间的收益率乘积,然后开n次方,因此几何平均收益率使用了复利的思想,从而克服了算术平均收益率有时会出现的上偏倾向。我们来看下面的例子:

In [ ]:
T = len(returns)
init_price = pricing[0]
final_price = pricing[T]
print('最初价格:', init_price)
print('最终价格:', final_price)
print('通过几何平均收益率计算的最终价格:', init_price*(1 + R_G)**T)

从上例可以看出,几何收益率的优势在于体现了复利的思想,我们知道初始资金和几何收益率,很容易计算出最终资金

调和平均值

调和平均值(harmonic mean)又称倒数平均数,是总体各统计变量倒数的算术平均数的倒数。调和平均值是平均值的一种。 $$ H = \frac{n}{\sum_{i=1}^n \frac{1}{X_i}} $$ 调和平均值恒小于等于算术平均值,当所有观测值相等的时候,两者相等。

应用:调和平均值可以用在相同距离但速度不同时,平均速度的计算;如一段路程,前半段时速60公里,后半段时速30公里〔两段距离相等〕,则其平均速度为两者的调和平均值时速40公里。在现实中很多例子,需要使用调和平均值。

In [ ]:
# 我们可以使用现成的函数来计算调和平均值
print('x1的调和平均值:', stats.hmean(x1))
print('x2的调和平均值:', stats.hmean(x2))

点估计的欺骗性

平均值的计算隐藏了大量的信息,因为它们将整个数据分布整合成一个数字。 因此,常常使用“点估计”或使用一个数字的指标,往往具有欺骗性。 你应该小心地确保你不会通过平均值来丢失数据分布的关键信息,在使用平均值的时候也应该保持警惕。


本文由BigQuant宽客学院推出,版权归BigQuant所有,转载请注明出处。


社区干货与精选整理(持续更新中...)
(xfhbigquant) #2

噢噢 懂了


(NaturalAI) #3

好东西。