DeepAR股票价格预测,python完整代码实现

1、应用场景
    绝大部分行业场景,尤其是互联网行业,每天都会产生大量的数据。游戏中每时每刻都会产生大量的玩家日志信息;旅游应用中每天有各类酒店各种交通工具的实时价格;涉及供应链和日销量的零售电商,每月都为生产(购进)多少货而发愁;就连生产电子元器件、供电箱等传统生产企业,这些零件每时每刻都会产生大量的数据。而我们称这种不同时间收到的,描述一个或多种特征随着时间发生变化的数据,为时间序列数据(Time Series Data)。
    结合上文中的时间序列数据,我们能够做什么?最显而易见的是,我们可以通过过去产生的时间序列数据,来预测未来。我们可以通过游戏历史的玩家消费时间序列数据,预测该玩家在接下来一周的付费意愿和付费大致金额,从而定制化的推送相关游戏礼包和活动,这通常和传统的用户画像是互补的。
    旅游应用中,利用历史数据对未来酒店、机票的价格进行预测,从而为用户推荐最低价的购买点(例如:提示用户五天后购买会更便宜),这一个小功能就足够获取大量忠实用户并实现变现,而北美已经有网站实现了这个功能来预测机票价格。有了每日销量的历史数据,我们可以预测接下来每天的销量范围,从而更有针对性的进货或者推出折扣促销政策,保证商品的供需平衡。
    某大型供电箱生产销售企业常常头疼于电箱的维修难,维修贵,如果能利用传感器收集上来的历史数据训练出模型,在电箱故障前提前预警,那不论是维修还是提前更换,成本总比电箱彻底不工作后再去维修要少。
    一言以蔽之,时间序列预测就是通过多种维度的数据本身内在与时间的关联特性,其中可能包含季节性、趋势性等等特征,利用历史的数据预测未来的场景,细分场景除了上述所介绍的之外,还有很多很多,由于篇幅关系,这里不做过多的展开介绍。


2、DeepAR简介 
     DeepAR 是一个自回归循环神经网络,使用递归神经网络 (RNN) 结合自回归 AR 来预测标量(一维)时间序列。在很多应用中,会有跨一组具有代表性单元的多个相似时间序列。DeepAR 会结合多个相似的时间序列,例如是不同方便面口味的销量数据,通过深度递归神经网络学习不同时间序列内部的关联特性,使用多元或多重的目标个数来提升整体的预测准确度。
    DeepAR 最后产生一个可选时间跨度的多步预测结果,单时间节点的预测为概率预测,默认输出P10,P50和P90三个值。这里的P10指的是概率分布,即10%的可能性会小于P10这个值。通过给出概率预测,我们既可以综合三个值给出一个值预测,也可以使用P10 – P90的区间做出相应的决策。有关 DeepAR 数学运算背景的更多信息,请参阅DeepAR:概率性预测与自回归递归网络。

3、应用实例
3.1、先安装必要的python依赖(我用的清华源)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ openpyxl,gluonts==0.9.6,mxnet,sqlalchemy,mxnet-mkl,pandas==1.5.3




3.2、完整实现代码
import matplotlib.pyplot as plt
import json
import pickle
import baostock as bs
import os

from gluonts.mx.trainer import Trainer
from gluonts.evaluation.backtest import make_evaluation_predictions
from tqdm.autonotebook import tqdm

from gluonts.dataset.common import ListDataset
from gluonts.evaluation import Evaluator
from gluonts.model.deepar import DeepAREstimator
from pathlib import Path
from gluonts.model.predictor import Predictor

from params import predict_len
from utils.data_dir import root_dir

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"


def mygetstockdata(code):
    rs = bs.query_history_k_data_plus(code,
                                      "date,close,volume,turn",
                                      start_date='2023-01-01',
                                      frequency="d", adjustflag="2")  # frequency="d"取日k线,adjustflag="3"默认不复权
    return rs.get_data()


if __name__ == '__main__':
    liststock = ["sz.300570", "sz.300399", "sz.002162", "sh.600621",
                 "sh.603220", "sh.603161", "sz.002401", "sh.605577"]
    cache_listtrandic_path = f"{root_dir}/data/listtrandic.pkl"
    cache_listtestdic_path = f"{root_dir}/data/listtestdic.pkl"
    if os.path.exists(cache_listtrandic_path):
        with open(cache_listtrandic_path, 'rb') as f:
            listtrandic = pickle.load(f)
        with open(cache_listtestdic_path, 'rb') as f:
            listtestdic = pickle.load(f)
    else:
        listtrandic = []
        listtestdic = []
        lg = bs.login()
        for ite in liststock:
            dd = mygetstockdata(ite)
            trandic = {"start": dd.date[0],
                       "target": list(dd.close),
                       "cat": int(ite.split('.')[1])
                       }
            testdic = {"start": dd.date[0],
                       "target": (dd.close)[:-predict_len],
                       "cat": int(ite.split('.')[1])
                       }
            listtrandic.append(trandic)
            listtestdic.append(testdic)
        os.makedirs(f"{root_dir}/data", exist_ok=True)
        with open(cache_listtrandic_path, 'wb') as f:
            pickle.dump(listtrandic, f)
        with open(cache_listtestdic_path, 'wb') as f:
            pickle.dump(listtestdic, f)
    traindata = ListDataset(listtrandic, freq="1d")
    testdata = ListDataset(listtestdic, freq="1d")
    estimator = DeepAREstimator(prediction_length=predict_len,
                                context_length=60,
                                freq="1d",
                                trainer=Trainer(epochs=20, learning_rate=1e-2, num_batches_per_epoch=300)
                                )
    model_path = Path(f"{root_dir}/data/output_model")
    if os.path.exists(model_path):
        predictor = Predictor.deserialize(model_path)  # 导入训练好的模型
    else:
        predictor = estimator.train(traindata)
        predictor.serialize(model_path)  # 保存训练好的模型
    forecast_it, ts_it = make_evaluation_predictions(
        dataset=testdata,
        predictor=predictor,
        num_samples=100
    )
    print("Obtaining time series conditioning values ...")
    tss = list(tqdm(ts_it, total=len(testdata)))
    print("Obtaining time series predictions ...")
    forecasts = list(tqdm(forecast_it, total=len(testdata)))

    def plot_prob_forecasts(ts_entry, forecast_entry, code, save_image=True):
        plot_length = 200
        prob_intervals = (50.0, 95.0)
        legend = ["True values", "median prediction"] + [f"{k}% prob interval" for k in prob_intervals][::-1]

        ax = plt.gca()
        ts_entry[-plot_length:].plot(ax=ax)
        forecast_entry.plot(prediction_intervals=prob_intervals, color='g')
        ax.axvline(ts_entry.index[-predict_len], color='r', linestyle="dashed")
        plt.legend(legend)
        if save_image:
            plt.savefig(f"{root_dir}/data/output/forecast_{code}.png")
            plt.close()
        else:
            plt.show()
    for i in range(len(tss)):
        plot_prob_forecasts(tss[i], forecasts[i], liststock[i])

    # 输出预测结果
    testdata_predict = predictor.predict(testdata)
    prediction = next(testdata_predict)
    print(prediction.mean)
    prediction.plot(output_file=f'{root_dir}/data/output/graph.png')
    # 评价指标
    evaluator = Evaluator(quantiles=[0.5, 0.90])
    agg_metrics, item_metrics = evaluator(iter(tss), iter(forecasts), num_series=8)
    print(json.dumps(agg_metrics, indent=4))

    # 未来预测
    # insert_into_daily_predict(day, code, name, price)

最新代码放到gitee上了,感兴趣的可以直接用,stock_predict: 股票预测、推荐、量化等

参考资料:

教程 | 如何使用 DeepAR 进行时间序列预测?

Deepar - 知乎

【时序】DeepAR 概率预测模型论文笔记

你可能感兴趣的:(Python日常,python)