用MACD决策树模型预测股票趋势

55beb1de8f2a80aa56819a3b46091672.gif

前言

上回说到,可以用LSTM时序模型来预测股票价格,在股票价格技术分析中,MACD作为一个经典的交易指标,一直指导着买卖时机,这篇我们实现一下在这个指标下的决策树模型,来预测未来的股票走势。

基本概念

MACD指标

MACD(Moving Average Convergence/Divergence),是一种用于股票价格分析的技术指标,由 Gerald Appel 在 1970 年代后期创建。它旨在揭示股票价格趋势的强度、方向、动量和持续时间的变化。

3bfb4ef5f6659c1ffb1a5f20e01d3b1d.png

MACD 指标是根据历史价格数据(通常是收盘价)计算得出的三个时间序列的指标。,即三个 EMA 的时间常数,通常表示为 "MACD( a , b , c )" 。其中 MACD序列是具有特征时间 a(短周期)和 b(长周期)指数移动平均线(EMA) 的差,平均序列是具有特征时间c的MACD序列的 EMA。

这些参数通常以天为单位。最常用的值是 12、26 和 9 天,即 MACD(12,26,9)。与大多数技术指标一样,MACD 也从过去主要基于日线图的技术分析中找到其周期规律。

由于过去的工作周是 6 天,因此 (12, 26, 9) 的周期设置分别代表 2 周、1 个月和 1 周半。现在,当交易周只有 5 天时,也可以相应调整周期参数,比如(10, 20, 7)。但是,最好坚持大多数交易者使用的周期设置,因为基于标准设置的买卖决策会进一步影响价格朝该方向发展。

短期 EMA 比长期 EMA 对近期股票价格变化的反应更快。通过比较不同时期的EMA,MACD序列可以指示股票趋势的变化。据称,背离系列可以揭示股票趋势的微妙变化。

由于 MACD 基于移动平均线,所以它是一个慢速指标滞后指标。作为预测未来价格趋势的指标,MACD 无法直接用于在完全没有规律的区间内交易或者价格不可预测的场合。而且当 MACD 显示趋势时,趋势已经完成或几乎完成。

决策树模型

决策树模型是统计、数据挖掘和机器学习中使用的预测建模方法之一。它使用决策树作为预测模型,在树枝中呈现对历史数据的观察,在叶子中得到预测目标值。

4ed4aeeaace7eecd0d90b75e80490cd0.png

如果目标值可以采用一组离散值的树模型称为分类树;在这些树结构中,叶子代表分类标签,分支代表连词导致这些分类标签的特征。如果目标值可以取连续值(通常是实数)的决策树称为回归树。我们这里预测目标为股票价格,所以采用的就是回归模型。

由于决策树的可理解性和简单性,决策树是最流行的机器学习算法之一。在决策分析中,决策树可用于直观、明确地表示决策和决策制定。

综上所述,MACD是一个平均指标,虽然不适合直接反应出瞬息万变的即时股票价格,但可以用来反应出一段时间的价格背离的程度,接下来我们就用决策树来预测未来一段时间的价格走势。

环境准备

同样先新建一个jupyterNotebook,引入sklearn库。

import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
plt.style.use('fivethirtyeight')

数据准备

获取交易数据

获取2015年以来的历史数据,这里和上一篇类似,就不赘述了。

security = '510300.XSHG'
his_period = 60  # 历史时间
df = get_price(security, start_date="2015-01-05", end_date="2022-1-25", frequency='daily')

计算 EMA

分别计算三个时间参数,虽然现在是5天交易日,但我们仍先采用经典的 MACD(12,26,9),有兴趣可以自行调整参数。

5a9200108651fa8cdf695564a8219cdd.png
ShortEMA = df.close.ewm(span=12, adjust=False).mean()
LongEMA = df.close.ewm(span=26, adjust=False).mean()
MACD = ShortEMA - LongEMA
signal = MACD.ewm(span=9, adjust=False).mean()

可视化一下参数曲线

macd_parameter = (12, 26, 9)
ShortEMA = df.close.ewm(span=macd_parameter[0], adjust=False).mean()
LongEMA = df.close.ewm(span=macd_parameter[1], adjust=False).mean()
MACD = ShortEMA - LongEMA
signal = MACD.ewm(span=macd_parameter[2], adjust=False).mean()
9e72f9b606dcfdf5c0ea1f8b00824a2c.png

将指标数据存入数据集

df['MACD'] = MACD
df['Signal Line'] = signal
df.tail()
f41334fa234bea29950542d25834e8c8.png

获取买卖信号

MACD 交叉指标,当 MACD 跌破信号线时,这是一个看跌信号,表明可能是时候卖出了。相反,当 MACD 升至信号线上方时,该指标发出看涨信号,这表明资产价格可能会出现上行势头。

def buy_sell(signal):
    Buy = []
    Sell = []
    flag = -1
    
    for i in range(0, len(signal)):
        if signal['MACD'][i] > signal['Signal Line'][i]:
            Sell.append(np.nan)
            if flag != 1:
                # 买入信号
                Buy.append(signal['close'][i])
                flag = 1
            else:
                Buy.append(np.nan)
        elif signal['MACD'][i] < signal['Signal Line'][i]:
            Buy.append(np.nan)
            if flag != 0:
                # 卖出信号
                Sell.append(signal['close'][i])
                flag = 0
            else:
                Sell.append(np.nan)
        else:
            Buy.append(np.nan)
            Sell.append(np.nan)
            
    return (Buy, Sell)

将买卖信号汇入数据集

df['Buy_Signal_Price'], df['Sell_Signal_Price'] = buy_sell(df)
df.head()
5380fbd3ba66315ef7bc86fa8fc4fda7.png

可视化买卖信号

period = 500  # 可视化范围
plt.figure(figsize=(16,8))
plt.scatter(df.index[-period:], df['Buy_Signal_Price'][-period:], label="Buy", color='green', marker='^',alpha=1, linewidths=5)
plt.scatter(df.index[-period:], df['Sell_Signal_Price'][-period:], label="Sell", color='red', marker='v',alpha=1, linewidths=5)
plt.plot(df['close'][-period:], label='Close Price', alpha=0.35)
plt.title('Close Prcie Buy & Sell Signals')
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price', fontsize=18)
plt.legend(loc='upper left')
plt.show()
b7a4978c2ea1bc71d036db4de061f3b4.png

图中绿色是买入信号,红色是卖出信号,可以发现大波动时这个指标比较有用,小波动时卖在底部,买在高位的情况也不少,所以不能完全迷信技术指标,实战中还是要结合自己的判断。

决策树回归模型

生成目标值

若我们预测未来60天的走势,就先将收盘数据向上平移一个区间。

# his_period = 60
df['Prediction'] = df[['close']].shift(-his_period)

数据预处理

前面我们可视化买卖信号的时候,采用的是收盘值,为了避免训练数据泄露,对这些数据先进行onehot处理后,作为一组特征汇入数据集。

df['Buy_Signal_Price'][np.invert(df['Buy_Signal_Price'].isna())] = 1
df['Buy_Signal_Price'] = df['Buy_Signal_Price'].fillna(0)

df['Sell_Signal_Price'][np.invert(df['Sell_Signal_Price'].isna())] = 1
df['Sell_Signal_Price'] = df['Sell_Signal_Price'].fillna(0)

划分训练集和测试集

这里我们准备预测未来60天的趋势,所以先将数据集划分为 (2015年 ~ 前60天),然后再将训练集划分为(2015年 ~ 前120天),测试集为(前120天 ~ 前60天),即用最近60天的数据来预测未来60天的走势。

X = np.array(df.drop(['Prediction'],1)[:-his_period])
y = np.array(df['Prediction'][:-his_period])
x_train = X[:-his_period]
x_test = X[-his_period:]
y_train = y[:-his_period]
y_test = y[-his_period:]
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)

输出:(1601, 10) (60, 10) (1601,) (60,)

训练决策树模型

万事具备了,我们使用sklearn库里的DecisionTreeRegressor来建立模型,并用之前划分好的训练集对模型进行训练。

tree = DecisionTreeRegressor(criterion='mse', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1).fit(x_train, y_train)

验证模型效果

将测试集数据导入模型进行预测

prediction = tree.predict(x_test)
print("The model training score is" , tree.score(X, y))

输出:The model training score is 0.9977305489482631

period = 500  # 可视化范围
valid = df[X.shape[0]-his_period:-his_period]
valid['Prediction'] = prediction
plt.figure(figsize=(16,8))
plt.title('Model')
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price', fontsize=18)
plt.plot(df[-period:X.shape[0]-his_period+1]['close'], linewidth=3, color='blue')
plt.plot(valid['close'], linewidth=5, alpha=0.5)
plt.plot(valid['Prediction'], linewidth=2, color='red')
plt.legend(['Train', 'Val', 'Predictions'], loc='lower right')
plt.show()
059cc001ca0c8397714cbfc624ea10c6.png

图中可以看到,该模型预测到在30天左右会发生一次大跳水(只不过没想到现实中会发生的这么快...),然后价格微微反弹逐步回稳。

预测未来趋势

我们重新获取最近60天的数据,导入模型来获得预测值

x_future = np.array(df.drop(['Prediction'], 1)[-his_period:])
prediction = tree.predict(x_future)

plt.figure(figsize=(16,8))
plt.title('Model')
plt.xlabel('Days', fontsize=18)
plt.ylabel('Close Price', fontsize=18)
plt.plot(prediction)
plt.legend(['Predictions'], loc='lower right')
plt.show()
3d3be0fd1e807b881fe922931f257b4b.png

模型显示,未来一个月行情比较平淡,在第二个月里似乎有点机会,那准不准呢?拭目以待吧...

源码下载

7faa0160aa38cab9606be35edcf91060.png

本期相关文件资料,可在公众号“深度觉醒”,后台回复:“trade02”,获取下载链接。

12b615b3a24ba26bda810c735118a8fa.gif

猜你喜欢

转载自blog.csdn.net/weixin_47479625/article/details/122711265