【机器学习案例八】股票投资中均线策略的应用

案例背景

数据集 SH50 给出了上证 50 指数从 2005 年 1 月 1 日至 2019 年 5 月10 日的股价数据,包括日期(date)、开盘价(open)、最高价(high)、最低价(low)、收盘价(close)、成交量(vol)。请建立模型对指数未来 5 日走势进行预测,如果未来五天平均价格变化 ≥ 1.5%,则记为“看涨”;未来五天股票平均价格变化 ≤-1.5%,记为“看跌”;其余情况记为“震荡”。根据历史数据预测未来五天股票价格的走势

数据预处理

导入基本库
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt

读取数据
df=pd.read_csv('sh50.csv')
  • 将每天的收盘价进行可视化
close=list(df.close)
plt.plot(close)

在这里插入图片描述

构造label
  • 构造依据
    原始数据中没有看涨或者看跌这样的数据的,需要自己根据历史数据构造,若未来五日的股票的平均价格是当前价格的1.015倍,那么标为看涨股票。若未来五日的股票的平均价格是当前价格的0.985倍,那当前标为看跌。其他情况视为震荡。
  • 定义函数
def make_label(*x):
    labels=[]
    for i in range(len(x)-5):
        if  (sum(x[i+1:i+6])/5.0)/x[i] - 1 > 0.015:
            labels.append('看涨')
        elif (sum(x[i+1:i+6])/5.0)/x[i] - 1 < -0.015:
            labels.append('看跌')
        else:
            labels.append('震荡')
    return labels
  • 将构造的标签添加到原始数据中
labels=make_label(*close)
df=df.iloc[:-5,:]
df['label']=labels

因为最后五天是没有未来五天的数据的,所以构造的标签比总样例少五。所以要将原始数据中最后五天的样例删掉。

构造特征

构造依据

收盘价(成交量)相对于移动平均线的偏离的方式将原始数据集转化为训练模型采用的特征,具体做法为:

  • 以收盘价为基础分别计算5 日移动平均价(MA5)、10 日移动平均价(MA10)、20 日移动平均价(MA20)、60 日移动平均价(MA60)、120 日移动平均价(MA120),然后计算当日收盘价相对于 MA5、MA10、MA20、MA60、MA120 记为 BIAS5、BIAS10、BIAS20、BIAS60、BIAS120;
def make_ma(*x,day):
    ma=[]
    for i in range(len(x)-day+1):
        average=(sum(x[i:i+day]))/int(day)            
        ma.append(average)
    return ma
close=list(df.close)
ma5=make_ma(*close,day=5)
ma10=make_ma(*close,day=10)
ma20=make_ma(*close,day=20)
ma60=make_ma(*close,day=60)
ma120=make_ma(*close,day=120)

bias5=list(np.array(close)[4:]-np.array(ma5))
bias10=list(np.array(close)[9:]-np.array(ma10))
bias20=list(np.array(close)[19:]-np.array(ma20))
bias60=list(np.array(close)[59:]-np.array(ma60))
bias120=list(np.array(close)[119:]-np.array(ma120))
  • 分别计算 5 日、10 日和 20日的移动均量,记为 VOL5、VOL10 和 VOL20,然后计算当日成交量与VOL5、VOL10 和 VOL20 的比值,记为 LB5、LB10 和 LB20;
def make_vol(*x,day):
    vol=[]
    for i in range(len(x)-day+1):
        average=(sum(x[i:i+day]))/int(day)            
        vol.append(average)
    return vol

vol=list(df.vol)
vol5=make_vol(*vol,day=5)
vol10=make_vol(*vol,day=10)
vol20=make_vol(*vol,day=20)

lb5=list(np.array(vol)[4:]/np.array(vol5))
lb10=list(np.array(vol)[9:]/np.array(vol10))
lb20=list(np.array(vol)[19:]/np.array(vol20))
将新特征加入到原始数据集中

新特征中有120天的平均价格,原始数据中的前119天是没有这个数据的,所以要将原始数据中前119天的数据删掉。其他新的属性要需要做对应的删除,保证数据的一致性。

df=df.iloc[119:,:]

df['ma5']=ma5[(len(ma5)-3363):]
df['ma10']=ma10[(len(ma10)-3363):]
df['ma20']=ma20[(len(ma20)-3363):]
df['ma60']=ma60[(len(ma60)-3363):]
df['ma120']=ma120[(len(ma120)-3363):]

df['bias5']=bias5[(len(bias5)-3363):]
df['bias10']=bias10[(len(bias10)-3363):]
df['bias20']=bias20[(len(bias20)-3363):]
df['bias60']=bias60[(len(bias60)-3363):]
df['bias120']=bias120[(len(bias120)-3363):]

df['vol5']=vol5[(len(vol5)-3363):]
df['vol10']=vol10[(len(vol10)-3363):]
df['vol20']=vol20[(len(vol20)-3363):]

df['lb5']=lb5[(len(lb5)-3363):]
df['lb10']=lb10[(len(lb10)-3363):]
df['lb10']=lb20[(len(lb20)-3363):]
构造训练集合测试集
df.drop('date',axis=1,inplace=True)
x=df.drop('label',axis=1)
y=df.label
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 = 1)

普通神经网络

  • 将原始数据标准化
from sklearn.preprocessing import StandardScaler
x_scaler = StandardScaler()  
x1=x_scaler.fit_transform(x)
x_train1,x_test1,y_train,y_test = train_test_split(x1,y,test_size = 0.2,random_state = 1)

-训练模型

from sklearn import neural_network as nn
from sklearn.metrics import accuracy_score

mdl_nn=nn.MLPClassifier(solver='adam', 
                        momentum=0.8,    
                        activation='relu',
                        learning_rate_init=0.0001, 
                        learning_rate='constant',  
                        alpha=0.0001,
                        hidden_layer_sizes=(50,50,50),
                        verbose=True,            
                        batch_size=3363,       
                        max_iter=2000,
                        shuffle=True, 
                        early_stopping=False
                        )
mdl_nn.fit(x_train,y_train)
yhat=mdl_nn.predict(x_train)
ypred=mdl_nn.predict(x_test)
print(mdl_nn.score(x_train,y_train)) 
print(mdl_nn.score(x_test,y_test))  

训练集精度:0.729
测试集精度:0.536

  • 预测结果
predict_=mdl_nn.predict(x_test.iloc[:30,:])
true=y_test[:30]
result=pd.DataFrame({'label':true,'predict':predict_})
result_=[]

for i in range(len(true)):
    if list(true)[i]==predict_[i]:
        result_.append('成功')
    else:
        result_.append('失败')

result['result']=result_

在这里插入图片描述

删除部分特征
df.drop('date',axis=1,inplace=True)
x=df.drop(['open','high','low','change','vol','label'],axis=1)
y=df.label
  • 训练结果
    训练集:0.695910780669145
    测试集:0.5780089153046062
    模型在训练集上的效果下降了,但在测试集的效果增加了。

RandomForestClassifier

用随机森林对数据进行分析
在不调参的情况下,发现无论在训练集还是测试集,随机森林的分类效果都远高于神经网络模型。

from sklearn.ensemble import RandomForestClassifier
rf=RandomForestClassifier()
rf.fit(x_train,y_train)
rf.score(x_train,y_train)
rf.score(x_test,y_test)

训练集精度:0.989
测试集精度:0.645

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值