猜涨跌预测(二):简化版

统计学习领域有一句著名的论断:“All models are wrong, but some are useful”。猜涨跌预测 中使用了 Geometric Brownian 模型来拟合上证指数的走势,颇有一种 钦定 的感觉。本文试图简化强模型假设,使用最简单的两个统计学习中的模型——线性回归(Linear Regression)和逻辑回归(Logistic Regression)来解决猜涨跌预测的问题。

线性回归

模型简介

对于数据 {x1,y1;x2,y2;...;xN,yN}\{x_1, y_1;x_2, y_2;...;x_N, y_N\},线性回归假设 dependent 变量 yy 和 independent 变量 xx 满足如下线性关系

yi=β0+β1xi+εi,i=1,...,Ny_i = \beta_0 + \beta_1 x_i + \varepsilon_i, i=1,...,N

其中 εi\varepsilon_iNN 个独立同分布的残差项,且服从正态分布。

准备数据

我们收集了3月19日之前200个交易日的上证指数的数据: stock_lr.csv 下载地址
其中包含三列数据:上证指数在 9:30 的开盘价格,中午 11:30 的收盘价格,今日收盘价与昨日收盘价之差。我们首先读入数据

1
2
3
4
5
import numpy as np 

with open('stock_lr.csv', 'r') as f:
stock_dataset = np.loadtxt(f, delimiter=',', skiprows=1, usecols=[1,2,3])
stock_dataset[:5].view()

前 5 行的数据如下

1
2
3
4
5
array([[3168.9642, 3167.8272,  -14.31  ],
[3154.6506, 3152.3458, -13.35 ],
[3141.3032, 3146.8495, -6.22 ],
[3135.0821, 3116.5867, -14.62 ],
[3120.4605, 3065.0817, -79.02 ]])

我们将今日收盘价与昨日收盘价之差作为预测目标 yy,今日中午收盘价与今日开盘价之差作为模型特征 xx,建立线性模型

y=β0+β1x+εy = \beta_0 + \beta_1 x + \varepsilon

在 Python 中处理数据

1
2
3
4
x = stock_dataset[:, 1] - stock_dataset[:, 0]
y = stock_dataset[:, 2]
N = len(y)
x = np.reshape(x, (N, 1))

训练模型

为了检验模型是否有效,我们需要将所有数据分为训练集(training set)和测试集(test set)

1
2
3
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=7841)

(如果没有 sklearn 包的话当然是用 pip install sklearn 安装 scikit-learn 包咯)
开始使用 scikit-learn 里面自带的线性模型 LinearRegression 来拟合训练集,并在测试集上验证模型是否有效

1
2
3
4
5
6
7
8
9
from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(x_train, y_train)
train_acc = sum(lr.predict(x_train) * y_train > 0) / len(y_train)
test_acc = sum(lr.predict(x_test) * y_test > 0) / len(y_test)
print('beta_0: {0:.5f}, beta_1: {1:.5f}'.format(lr.intercept_, lr.coef_[0]))
print('training set accuracy: {}'.format(train_acc))
print('test set accuracy: {}'.format(test_acc))

结果

1
2
3
beta_0: 0.94371, beta_1: 1.12510
training set accuracy: 0.78125
test set accuracy: 0.75

解释结果

根据上面的输出,意味着拟合训练集得到的模型结果为

y=0.94371+1.12510x+εy = 0.94371 + 1.12510 x + \varepsilon

根据此模型预测猜涨跌的胜率为:训练集上 78.1% 准确率,测试集上 75% 的准确率。

逻辑回归

模型简介

对于数据 {x1,y1;x2,y2;...;xN,yN}\{x_1, y_1;x_2, y_2;...;x_N, y_N\},(其中 yi{0,1}y_i\in\{0, 1\},i.e. y=0y=0 或者 y=1y=1)逻辑回归就是假设 dependent 变量 yy 和 independent 变量 xx 满足如下概率模型

P(yi=1xi)=11+e(β0+β1xi),i=1,...,NP(y_i=1|x_i) = \frac{1}{1+e^{-(\beta_0 + \beta_1 x_i)}}, i=1,...,N

准备数据

类似的,我们收集了3月19日之前200个交易日的上证指数的数据: stock.csv 下载地址
其中包含三列数据:上证指数昨日收盘价格,中午 11:30 的收盘价格,0 / 1 变量,其中 0 代表今日收盘价与昨日收盘价之差为负数(下跌),1 代表今日收盘价与昨日收盘价之差为正数(上涨)。我们首先读入数据

1
2
3
4
5
import numpy as np 

with open('stock.csv', 'r') as f:
stock_dataset = np.loadtxt(f, delimiter=',', skiprows=1, usecols=[1,2,3])
stock_dataset[:5].view()

前 5 行的数据如下

1
2
3
4
5
array([[3168.9642, 3167.8272,    0.    ],
[3154.6506, 3152.3458, 0. ],
[3141.3032, 3146.8495, 0. ],
[3135.0821, 3116.5867, 0. ],
[3120.4605, 3065.0817, 0. ]])

我们将第三列的0 / 1 变量作为预测目标 yy,今日中午收盘价与昨日收盘价之差作为模型特征 xx,建立 Logistic 模型

P(y=1x)=11+e(β0+β1x)P(y=1|x) = \frac{1}{1+e^{-(\beta_0 + \beta_1 x)}}

在 Python 中处理数据

1
2
3
4
x = stock_dataset[:, 1] - stock_dataset[:, 0]
y = stock_dataset[:, 2]
N = len(y)
x = np.reshape(x, (N, 1))

训练模型

类似的,为了检验模型是否有效,我们需要将所有数据分为训练集(training set)和测试集(test set)

1
2
3
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=7841)

开始使用 scikit-learn 里面自带的线性模型 LogisticRegression 来拟合训练集,并在测试集上验证模型是否有效

1
2
3
4
5
6
7
8
9
from sklearn.linear_model import LogisticRegression

logr = LogisticRegression()
logr.fit(x_train, y_train)
train_acc = logr.score(x_train, y_train)
test_acc = logr.score(x_test, y_test)
print('beta_0: {0:.2f}, beta_1: {1:.2f}'.format(logr.intercept_[0], logr.coef_[0][0]))
print('training set accuracy: {}'.format(train_acc))
print('test set accuracy: {}'.format(test_acc))

结果

1
2
3
beta_0: -0.06806, beta_1: 0.09490
training set accuracy: 0.78125
test set accuracy: 0.725

解释结果

根据上面的输出,意味着拟合训练集得到的模型结果为

P(y=1x)=11+e(0.06806+0.09490x)P(y=1|x) = \frac{1}{1+e^{-(-0.06806 + 0.09490 x)}}

根据此模型预测猜涨跌的胜率为:训练集上 78.1% 准确率,测试集上 72.5% 的准确率。

在线计算

将我们训练的逻辑回归模型在线部署后,大家可以访问 猜涨跌预测 页面,输入今天的上证指数开盘价和中午收盘价,来估计下午收盘后,今天的指数相比于昨天收盘价的涨跌的概率,快去试试吧 ^ ^