量化投资常用的统计学知识及Python实现
统计学作为量化投资中的重要工具,在投资决策、风险管理、策略评估等方面发挥着至关重要的作用。在这篇文章中,我们将重点介绍在量化投资中常用的一些统计学知识,并给出对应的Python实现。
Python拥有丰富的数据处理和科学计算库,如NumPy、Pandas、SciPy、Statsmodels、Scikit-learn等,使得它成为量化投资领域的首选编程语言。本文将阐述在量化投资中常用的统计学知识,并通过Python代码的形式,展示如何实现这些统计学计算。你会看到使用Python中现成的库,很容易就能实现这些计算。
本节需要用到numpy、pandas、scipy、statsmodels这几个库,需要先导入这些库:
import numpy as np
import pandas as pd
from scipy import stats
import statsmodels.api as sm
01
最大值、最小值、绝对值
在一组数据中,最大的那个数就是最大值,最小的那个数就是最小值。一个数的绝对值是该数值去掉负号后的数。
- 用numpy库计算最大值、最小值和绝对值
data = [5, -3, 9, 0, -6]
max_value = np.max(data) # 计算最大值
min_value = np.min(data) # 计算最小值
abs_value = np.abs(data) # 计算绝对值 - 用pandas库计算
data = pd.Series([5, -3, 9, 0, -6])
max_value = data.max() # 计算最大值
min_value = data.min() # 计算最小值
abs_value = data.abs() # 计算绝对值
02
和、积
求和:将一组数值全部加起来的结果称为求和。
求积:将一组数值全部相乘的结果称为求积。
累和:将一组数值按照顺序逐个相加的结果。例如,对于数列[1, 2, 3, 4, 5],其累和是[1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5],即[1, 3, 6, 10, 15]。
累积:将一组数值按照顺序逐个相乘的结果。例如,对于数列[1, 2, 3, 4, 5],其累积是[1, 12, 123, 1234, 12345],即[1, 2, 6, 24, 120]。
- 用numpy库进行计算
data = [1, 2, 3, 4, 5]
sum_value = np.sum(data) # 计算求和
product = np.prod(data) # 计算积
cumulative_sum = np.cumsum(data) # 计算累和
cumulative_product = np.cumprod(data) # 计算累积 - 用pandas库计算
data = pd.Series([1, 2, 3, 4, 5])
sum_value = data.sum() # 计算求和
product = data.prod() # 计算积
cumulative_sum = data.cumsum() # 计算累和
cumulative_product = data.cumprod() # 计算累积
用累积计算可以将策略的日收益率序列转化为累计净值序列,举例如下:
daily_return = pd.Series([0.01, 0.012, -0.02, 0.014, 0.016, 0.021]) # 策略日收益率序列
accumulated_net = (daily_return + 1).cumprod() # 策略累计净值序列
03
中位数和分位数
1.中位数
中位数是一组数据的中心点,它将数据集分为两个等量的部分。在排序后的数据集中,如果数据点的数量是奇数,那么中位数就是中间的数;如果数据点的数量是偶数,那么中位数就是中间两个数的平均值。例如,对于数列[1, 3, 5, 7, 9],其中位数是 5。
在Python中,我们可以使用numpy包的median函数来计算中位数。例如:
data = [1, 3, 5, 7, 9]
median = np.median(data) # 计算中位数
也可以用pandas库计算中位数:
data = pd.Series([1, 3, 5, 7, 9])
median = data.median() # 计算中位数
2.分位数
分位数是对数据集进行分割的数值点,将数据集的所有数据点分为几个等份。例如,四分位数将数据集分为四等份,其中第一个四分位数(25%分位数)是将最小25%的数据点与其余数据分开的点,第二个四分位数(50%分位数,也就是中位数)将最小的50%的数据点与其余数据分开,第三个四分位数(75%分位数)将最小的75%的数据点与其余数据分开。
在Python中,我们可以使用numpy包的quantile函数来计算分位数。例如:
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
q1 = np.quantile(data, 0.25) # 第一个四分位数
q2 = np.quantile(data, 0.50) # 第二个四分位数,也是中位数
q3 = np.quantile(data, 0.75) # 第三个四分位数
也可以用pandas库计算分位数:
data = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
q1 = data.quantile(0.25) # 第一个四分位数
q2 = data.quantile(0.50) # 第二个四分位数,也是中位数
q3 = data.quantile(0.75) # 第三个四分位数
04
平 均 数
量化投资中经常用到以下几种平均数:
- 算术平均数(Arithmetic Mean)
算术平均数是所有数据值的总和除以数据值的数量。用Python的numpy库和pandas库计算算术平均数的代码如下:
data = [1, 2, 3, 4, 5]
#使用numpy计算算术平均数
mean_np = np.mean(data)
#使用pandas计算算术平均数
data_pd = pd.Series(data)
mean_pd = data_pd.mean()
- 几何平均数(Geometric Mean)
几何平均数是所有数据值乘积的n次方根,其中n是数据值的数量。几何平均数常用于计算比率和增长率。我们可以通过scipy库的gmean函数来计算:
data = [1, 2, 3, 4, 5]
gmean = stats.gmean(data) - 移动平均数
移动平均数是时间序列数据的一种平均数,它计算了每个滚动时间窗口的平均值。在量化投资中可以用移动平均数来计算均线值。我们可以使用pandas库的rolling函数计算移动平均数:
data = pd.Series([1, 2, 3, 4, 5])
rolling_mean = data.rolling(window=3).mean()
这里,参数window决定了滚动窗口的大小。函数返回的是移动平均数的序列。 - 指数平均数(Exponential Moving Average,EMA)
指数平均数是时间序列数据的一种平均数,它给近期的数据赋予更大的权重。在pandas库中,我们可以使用ewm函数计算指数平均数:
data = pd.Series([1, 2, 3, 4, 5])
ema = data.ewm(span=3, adjust=False).mean()
这里,参数span决定了平滑的程度。函数返回的是指数平均数的序列。
05
相关系数
相关系数是一种统计度量,用于衡量两个数值变量间的线性关系强度和方向。相关系数的值范围为-1到1。如果相关系数为正数,表示两个变量之间存在正向的线性关系;如果相关系数为负数,表示两个变量之间存在负向的线性关系;如果相关系数为0,表示两个变量之间没有线性关系。
在Python中,可以使用numpy和pandas库来计算相关系数。
- 使用numpy计算相关系数
x = np.array([1, 2, 3, 4, 5])
y = np.array([1, 3, 5, 2, 4])
correlation = np.corrcoef(x, y)[0, 1] # 计算相关系数
这段代码计算了向量x和向量y的相关系数。np.corrcoef返回的是一个相关系数矩阵,我们只需要取第1行第2列或第2行第1列的元素,即为x和y的相关系数。 - 使用pandas计算相关系数
df = pd.DataFrame({‘x’: [1, 2, 3, 4, 5], ‘y’: [1, 3, 5, 2, 4]})
correlation = df[‘x’].corr(df[‘y’]) # 计算相关系数
这段代码创建了一个包含两列(’x’和’y’)的DataFrame,然后计算了这两列的相关系数。df[‘x’].corr(df[‘y’])会返回x和y的相关系数。
06
方差和标准差
方差和标准差用于衡量数据集的离散程度或波动性。
方差是衡量一组数值的离散程度,或者说,它是衡量数据点与均值之间差异的平方的平均值。方差越大,数据点的离散程度就越高;方差越小,数据点就越接近均值。
标准差是方差的平方根。与方差一样,标准差也可以衡量数据的离散程度。但是,由于标准差的单位与原数据的单位相同(而方差的单位为原数据单位的平方),在许多情况下,标准差比方差更容易理解和解释。
在量化投资中经常用标准差来衡量风险程度,收益率序列的标准差越大,说明收益的波动性越大,风险越高。
在Python中,可以使用numpy和pandas库来计算方差和标准差。
- 使用numpy计算方差和标准差
data = [1, 2, 3, 4, 5]
variance = np.var(data) # 计算方差
std_dev = np.std(data) # 计算标准差 - 使用pandas计算方差和标准差
data_pd = pd.Series([1, 2, 3, 4, 5])
variance = data_pd.var() # 计算方差
std_dev = data_pd.std() # 计算标准差
注意,pandas和numpy在计算方差时使用的公式稍有不同。numpy默认使用总体方差公式,即平方和除以数据点的数量,而pandas默认使用样本方差公式,即平方和除以(数据点的数量-1)。这就是为什么相同的数据在numpy和pandas中得到的方差值不同的原因。如果我们想要得到和pandas相同的结果,我们可以在numpy的var函数中设置ddof参数为1,即np.var(data, ddof=1)。同样,对于标准差,我们也可以在numpy的std函数中设置ddof参数为1,即np.std(data, ddof=1),来得到和pandas相同的结果。
07
偏度和峰度
偏度是统计数据分布对称性的度量。正偏度表示数据偏向左(或者说偏向小值),负偏度表示数据偏向右(或者说偏向大值)。偏度为0表示数据两侧的分布对称。
峰度是描述数据分布形状的统计量,特别是描述分布尾部的形状。正峰度表示数据分布比正态分布更陡峭/尖锐,负峰度表示数据分布比正态分布更平坦。峰度为0表示数据分布的形状与正态分布相同。
在Python中,我们可以使用scipy库和pandas库来计算偏度和峰度。
1.使用scipy库计算
data = [1, 2, 3, 4, 5]
skewness = stats.skew(data) # 计算偏度
kurt = stats.kurtosis(data) # 计算峰度
2.使用pandas库计算
data_pd = pd.Series([1, 2, 3, 4, 5])
skewness = data_pd.skew() # 计算偏度
kurt = data_pd.kurt() # 计算峰度
注意,scipy库的kurtosis函数计算的是Excess Kurtosis,即与正态分布相比的峰度。而pandas库的kurt函数计算的是Fisher’s Kurtosis,即真实的峰度值。这就是为什么相同的数据,在scipy和pandas中得到的峰度值不同的原因。
08
线性回归
线性回归在量化投资中的应用很广泛,比如它可以用来预测未来的价格或收益、构建风险模型、构建因子、构建交易策略等等。
在Python中,我们可以使用statsmodels库来实现线性回归。以下是一个例子:
#生成一些样本数据
np.random.seed(0)
X = np.random.rand(100)
Y = 3 * X + np.random.randn(100)
#添加常数列,因为statsmodels的线性回归默认不包含截距项
X = sm.add_constant(X)
#建立并拟合模型
model = sm.OLS(Y, X)
results = model.fit()
#打印回归结果
print(results.summary())
这个程序首先生成一些随机的X(自变量序列)和Y(因变量序列),然后用线性回归模型拟合X和Y。最后,打印出回归结果,如下:

statsmodels的summary方法打印出了很多回归结果,以下是一些主要的回归结果的含义:
coef:这是回归系数,表示X每变动一个单位,Y预期的变动量。在以上的例子中,有两个回归系数——一个是常数项(const),一个是x1。const即是回归方程的截距,x1即是回归方程的斜率。
std err:这是回归系数的标准误差,表示估计的不确定性。标准误差越大,估计的不确定性越高。
t:这是t统计量,等于回归系数除以标准误差。绝对值越大,表示回归系数越显著。
P>|t|:这是t统计量的p值,表示回归系数为0的假设是否可以被拒绝。p值越小,表示回归系数越显著。
R-squared:这是决定系数,表示X可以解释Y变动的比例。越接近1,表示模型的解释能力越强。
F-statistic和Prob (F-statistic):这是F统计量和它的p值,用来测试模型中所有的回归系数是否同时为0。p值越小,表示模型至少有一个系数是显著的。
发布者:爱吃肉的小猫,转载请注明出处:https://www.95sca.cn/archives/45458
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!