"最小二乘法"( Ordinary Least Square,记 OLS)是单一方程线性回归模型最常见、最基本的估计方法。
import pandas as pd
df = pd.read_excel('./数据/上证指数与沪深300.xlsx')
df['日期'] = pd.to_datetime(df['日期']) # 将字符串转为日期格式
df.head()
日期 | hs300 | sz | |
---|---|---|---|
0 | 2018-01-02 | 4087.4012 | 3348.3259 |
1 | 2018-01-03 | 4111.3925 | 3369.1084 |
2 | 2018-01-04 | 4128.8119 | 3385.7102 |
3 | 2018-01-05 | 4138.7505 | 3391.7501 |
4 | 2018-01-08 | 4160.1595 | 3409.4795 |
df.describe() # 描述性统计
hs300 | sz | |
---|---|---|
count | 460.000000 | 460.000000 |
mean | 3664.266460 | 2930.237842 |
std | 333.651406 | 243.874533 |
min | 2964.842100 | 2464.362800 |
25% | 3364.816625 | 2746.438775 |
50% | 3762.250200 | 2917.781900 |
75% | 3897.218650 | 3095.709675 |
max | 4389.885300 | 3559.465300 |
import matplotlib
import matplotlib.pyplot as plt
from pylab import mpl
# 防止图形中文文字乱码
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 以黑体的字体显示中文
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
plt.figure(figsize=(9,6)) # 设置图形大小
plt.title('两指数走势图', fontsize=14) # 标题,fontsize 为字体大小
# 常见线的属性有:color, label, linewidth, linestyle, marker 等
plt.plot(df['日期'], df['hs300'], color='blue', label='沪深 300 指数')
plt.plot(df['日期'], df['sz'], color='red', label='上证指数')
plt.legend(fontsize=14) # 显示上面的 label
plt.xticks(fontsize=14) # x轴文字设置
plt.yticks(fontsize=14)
plt.xlabel('日期', fontsize=14)
plt.ylabel('指数值', fontsize=14)
# plt.axis([0, 2*np.pi, -1, 1]) #设置坐标范围 axis([xmin,xmax,ymin,ymax])
# plt.ylim(-1,1) #仅设置 y 轴坐标范围
plt.show()
plt.figure(figsize=(9,6))
plt.scatter(x=df['sz'], y=df['hs300'], c='b', marker='o')
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('两指数散点图', fontsize=14)
plt.xlabel('上证指数', fontsize=14)
plt.ylabel('沪深300指数', fontsize=14)
plt.grid()
总体模型为:yi=β1xi1+β2xi2+⋯+βKxiK+εi(i=1,⋯,n)
其中 n 为样本容量,解释变量 xik 的第一个下标表示第 i 个“观测值”,而第二个下标则表示第 k 个解释变量(k=1,⋯,K),共有 K个 解释变量。如果有常数项,则通常令第一个解释变量为单位向量,即 xi1=1
为了更简洁地表达,下面引入矩阵符号。把方程(1)的所有解释变量和参数都写成向量,记第 i 个观测数据为xi≡(xi1,xi2⋯xiK)′,β≡(β1,β2⋯βK)′,则方程(1)为:
yi=x′iβ+εi(i=1,⋯,n)
E(εi|X)=E(εi|x1,⋯,xn)=0(i=1,⋯,n)
Var(ε|X)=E(εε′|X)=σ2In=(σ20⋱0σ2)
假定待估计方程为:hs300=c+sz。其中 c 为常数项
import numpy as np
n = df.shape[0] # 样本容量
beta = np.array(df['sz']).reshape(n,1)
c = np.ones((n,1)) # 常数项
X = np.hstack((c,beta)) # hstack()在行上合并,vstack()在列上合并
y = np.array(df['hs300']).reshape(n,1)
b = np.linalg.inv(X.T @ X) @ X.T @ y
print('OLS估计值为:\n',b)
OLS估计值为: [[-124.69031687] [ 1.29305435]]
e = y - X @ b
对于扰动项方差σ2=Var(εi),由于总体扰动项 ε 不可观测,而样本残差 e 可以近似地看成是 ε 的实现值,故使用以下统计量作为对方差 σ2 的估计: s2≡1n−Kn∑i=1e2i
K = X.ndim
SSE = e.T @ e
s2 = SSE/(n-K)
import math
s = math.sqrt(s2)
print('平方和:', SSE)
print('扰动项方差', s2)
print('扰动项标准差', s)
平方和: [[5453855.41555515]] 扰动项方差 [[11907.98125667]] 扰动项标准差 109.12369704454952
Varb = s2 * np.linalg.inv(X.T @ X)
print('协方差矩阵:\n', Varb)
协方差矩阵: [[ 3.77128774e+03 -1.27819004e+00] [-1.27819004e+00 4.36206925e-04]]
由于 bk−βkSE(bk)∼t(n−K),根据 tα/2 得: P{−tα/2<bk−βkSE(bk)<tα/2}=1−α
from scipy. stats import t
alpha = 0.05 # 置信度
nu = max(0,n-K) # 自由度
tval = t.ppf(1-alpha/2,nu) # 逆函数值
SE_b = np.sqrt(np.diag(Varb)).reshape(K,1)
bint = np.hstack((b-tval*SE_b,b+tval*SE_b))
print('95% 置信区间:\n', bint)
95% 置信区间: [[-245.37220852 -4.00842522] [ 1.25201092 1.33409777]]
t_stat = b/SE_b
t_p = 2*(1-t.cdf(abs(t_stat),n-K))
print('t检验为:\n', t_stat)
print('\n')
print('p值为:\n', t_p)
t检验为: [[-2.0304294 ] [61.91138223]] p值为: [[0.0428902] [0. ]]
根据样本信息对总体进行推断,有可能犯错误。特别地,在进行假设检验时,可能犯两类性质不同的错误。
第Ⅰ类错误:虽然原假设为真,但却根据观测数据做出了拒绝原假设的错误判断,即“弃真”。
第Ⅱ类错误:虽然原假设为假(替代假设为真),但却根据观测数据做出了接受原假设的错误判断,即“存伪”。
由于在进行假设检验时,通常知道第Ⅰ类错误的发生概率,而不知道第Ⅱ类错误的发生概率。因此,如果拒绝原假设,可以比较理直气壮,因为知道犯错误的概率就是显著性水平(比如5%);另一方面,如果接受原假设,则比较没有把握,因为我们通常并不知道第Ⅱ类错误的发生概率(可能很高)。
import statsmodels.api as sm
# sm.add_constant(data, prepend=False)
mod = sm.OLS(y, X)
res = mod.fit()
res.summary() # 展示估计结果
Dep. Variable: | y | R-squared: | 0.893 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.893 |
Method: | Least Squares | F-statistic: | 3833. |
Date: | Sun, 31 May 2020 | Prob (F-statistic): | 1.20e-224 |
Time: | 17:10:48 | Log-Likelihood: | -2810.3 |
No. Observations: | 460 | AIC: | 5625. |
Df Residuals: | 458 | BIC: | 5633. |
Df Model: | 1 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | -124.6903 | 61.411 | -2.030 | 0.043 | -245.372 | -4.008 |
x1 | 1.2931 | 0.021 | 61.911 | 0.000 | 1.252 | 1.334 |
Omnibus: | 61.627 | Durbin-Watson: | 0.010 |
---|---|---|---|
Prob(Omnibus): | 0.000 | Jarque-Bera (JB): | 83.387 |
Skew: | 1.031 | Prob(JB): | 7.81e-19 |
Kurtosis: | 2.692 | Cond. No. | 3.55e+04 |
res.params # 获取估计参数值
array([-124.69031687, 1.29305435])
res.bse # 获取标准差
array([6.14108113e+01, 2.08855674e-02])
resid = res.resid # 获取残差
print(resid[:5]) # 只打印前五个
[-117.4758394 -120.35744134 -124.40507098 -122.27638992 -123.79246764]
res.cov_params() # 获取协方差矩阵
array([[ 3.77128774e+03, -1.27819004e+00], [-1.27819004e+00, 4.36206925e-04]])
res.f_test("x1 = 0") # Wald检验
<class 'statsmodels.stats.contrast.ContrastResults'> <F test: F=array([[3833.01924991]]), p=1.195406827896976e-224, df_denom=458, df_num=1>
plt.figure(figsize=(9,6))
plt.scatter(x=df['sz'], y=df['hs300'], c='b', marker='o')
plt.plot(df['sz'], res.params[0]+res.params[1]*df['sz'], '-r', lw=2.5)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('线性拟合示意图', fontsize=14)
plt.xlabel('上证指数', fontsize=14)
plt.ylabel('沪深300指数', fontsize=14)
plt.grid()
function [B,resid,siga2,bint,cov_matrix,t,t_p] = OLS_regress(Y,X)
%输入变量:
%Y - 被解释变量
%X - 解释变量
%输出变量:
% B - 待估计参数beta
% resid - 残差
% siga2 - 残差方差
% bint - 95%置信区间序列
% cov_matrix - 协方差矩阵
% 1.求OLS估计量B
B = inv(X'*X)*X'*Y;
% 2.计算协方差矩阵
resid = Y - X*B; %残差
[n,K] = size(X);
siga2 = sum(resid.^2)/(n-K);
cov_matrix = siga2*inv(X'*X);
% 3.t检验
t = B./sqrt(diag(cov_matrix));
t_p = 2*(1-tcdf(abs(t),n-K));
% 4.计算95%置信区间
alpha = 0.05; %置信度
nu = max(0,n-K); %自由度
tval = tinv(1-alpha/2,nu);
se = sqrt(diag(cov_matrix));
bint = [B-tval*se, B+tval*se];
% 1.载入数据
data = xlsread('./数据/hourse.xlsx');
f1 = data(:,2); f2 = data(:,3); e = data(:,6);
% 2.作线性回归 f1=e
[B,BINT,R,RINT,STATS] = regress(f1,e);
% 3.作线性回归 f1=c+e
[B,BINT,R,RINT,STATS] = regress(f1,[ones(length(f1),1),e]);
% 4.作线性回归 f1=c+f2+e
[B,BINT,R,RINT,STATS] = regress(f1,[ones(length(f1),1),f2,e]);