本系统参考了 https://github.com/borisbanushev/stockpredictionai 并尝试在A股市场中预测股价。
先写下实现的思路,以后慢慢改。
数据来源:https://tushare.pro/
For more information : https://longfly04.github.io/A-Stock-Prediction-System-with-Deep-Learning/
股票市场是经济的晴雨表,与国民经济发展密切相关,是投资者信心和国家经济发展潜力的象征和标志。从机器学习的视角来看,股票趋势并非没有规律的随机运动,而是受经济政治等多种外界因素和成交量、企业业绩等众多内部因素综合影响的理性市场活动。股市波动瞬息万变,股票市场的预测和分析与投资者利益息息相关。
机器学习总的来说分为监督学习、非监督学习和强化学习。监督学习可分为“回归”和“分类”问题。在回归问题中,我们会预测一个连续值,也就是说我们试图将输入变量和输出用一个连续函数对应起来;而在分类问题中,我们会预测一个离散值,我们试图将输入变量与离散的类别对应起来。但总的来说,监督学习需要样本数据有“标签”,通过大量数据的学习,让模型在过程中发现不同“标签”对应的特征规律。非监督学习中,给定的数据是和监督学习中给定的数据是不一样的,数据点没有相关的标签,算法的目标是以某种方式组织数据,然后找出数据中存在的内在结构。比如聚类,通过找到更简单的方式处理复杂数据,将复杂数据中的隐含结构发掘出来。强化学习是一种学习模型,AlphaGo使用的就是强化学习模型,与监督和非监督学习不同,它并不是通过大量数据学习内部的特征,而是机器自行与外界环境不停的互动,从而产生数据反馈并获得回报,机器会逐渐趋向于奖励并避免惩罚,在这个过程中不断学习适应外界环境,最终得出最好的行动方案。
股市预测任务并非通过单一的机器学习模型就可以实现准确预测,需要综合多种机器学习模型,充分利用非监督学习挖掘特征潜在结构,利用监督模型对所选特征进行精确拟合,最终通过强化学习方式让机器自行探索合适的模型参数,以收益为反馈,训练机器学习模型以达到准确预测股市波动的效果。综合研究和运用机器学习各种模型并应用于股市预测任务,对于准确判断股市趋势,实现投资收益最大化具有十分重要的理论意义,也是人工智能辅助人类决策的必经之路。
准确预测股票市场中包括股票价格指数和股票价格的运行态势,对于政府宏观管理而言,可以在一定层面上监测和引导股票市场的平稳运行,降低市场风险,从而促进实体经济的健康和平稳增长。
在进行股票投资时,投资者会获得与其承担的风险相对应的回报,预期回报率与风险之间是一种正向的互动关系。因此,对股市和个股进行认真的分析才能降低投资风险,获得投资效益。对于投资者而言,算法得出的预测结果对其做出有效的投资策略有着很好的参考价值,这样可以在一定程度上减少股票市场中盲目投资的现象,减少投资者的损失,降低他们的决策成本,对于提高股票市场中投资者的理性程度有很高的现实意义,也满足了市场上的一大需求。
ARIMA模型(英语:AutoregressiveIntegratedMovingAverage model),差分整合移动平均自回归模型,又称整合移动平均自回归模型(移动也可称作滑动),时间序列预测分析方法之一。ARIMA(p,d,q)中,AR是"自回归",p为自回归项数;MA为"滑动平均",q为滑动平均项数,d为使之成为平稳序列所做的差分次数(阶数)。“差分”一词虽未出现在ARIMA的英文名称中,却是关键步骤。ARIMA 模型是在平稳的时间序列基础上建立起来的,因此时间序列的平稳性是建模的重要前提。检验时间序列模型平稳的方法一般采用 ADF 单位根检验模型去检验。当然如果时间序列不稳定,也可以通过一些操作去使得时间序列稳定(比如取对数,差分),然后进行 ARIMA 模型预测,得到稳定的时间序列的预测结果,然后对预测结果进行之前使序列稳定的操作的逆操作(取指数,差分的逆操作),就可以得到原始数据的预测结果。
马尔科夫过程是研究事物状态以及其状态转移规律的理论,适合于时间序列以及空间序列,一个时间与状态都是离散的马尔科夫过程叫做马尔科夫链,也叫马氏链(Markov Chain),马氏链模型是一类描述随机动态系统的模型,其特点是①系统每个时刻所处的状态都是随机的,②从一个时刻到下一个时刻的状态按照一定的概率转移,③下一个时刻的状态只取决于当前时刻的状态和转移概率,与其他时刻状态无关。
支持向量机(SVM)是Vapnik和Cortes于1995年首先提出的,建立在统计学习理论的VC维理论和结构风险最小原理基础上的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势。支持向量机将非线性问题映射到高维空间,引入核函数,解决了非线性分类问题。支持向量回归(SVR)是支持向量机的推广,通过引入ε不敏感损失函数,将问题转化为通过对已知的样本数据学习找到一个拟合函数,对未知的数据进行预测,这个函数f(x)对实际的 值最大偏差为ε,从而构建回归模型。在金融领域的应用中,Trafalis和Ince研究发现SVR的预测精度远高于MLP(多层感知机)和ARIMA(差分滑动平均自回归模型),并且与神经网络相比有更加出色的性能。
XGBoost算法是陈天奇博士于2016年提出的基于回归树的提升算法,在市场价格估计、高能物理事件分类、网络文本分类、客户行为分析等诸多机器学习任务中均表现了出色的性能,并且算法因其高度可扩展性和并行化能力,在大规模数据回归和分类任务上也有着优异的表现。2017年,Ren年将XGBoost与卷积神经网络结合,用于图像分类;同年,Chen将加权的XGBoost模型应用于雷达信号分类并取得了很好的效果。
近年来,深度学习方法在人工智能领域取得了突破性的进展,深度神经网络在图像识别、人脸检测与识别、语音识别、目标捕捉、机器翻译等多个领域都有长足的进步。一方面由于积累的数据量的提高,达到了深度学习所需要的量级,另一方面,机器运算性能的提升,也使深度学习方法有了硬件的基础。深度学习方法可以通过组合浅层次的特征形成更加抽象的高层特征表示,以发现数据的深层次隐含关系,通过多层神经网络的堆叠和激活函数的选取,可以更好地拟合复杂的非线性函数。由于市场规律的复杂性、市场价格的波动性、影响因素的多样性,仅仅依赖传统的策略分析和模型不足以应对这些挑战,而深度学习方法的引入,能够提高对这些问题的解决能力,训练出泛化能力更强的模型,对股票投资来说是具有重要的参考意义。
由于股价数据具有很强的时间关联性,我们自然想到使用LSTM(Long Short-Term Memory)或者GRU(Gated Recurrent Unit)模型挖掘股价数据在时间上的相关性。同时,中国股票市场受政策面影响很大,经济新闻和上市公司财报等文本数据也会成为股价波动的重要原因。目前研究者们普遍在股价数据的时间序列特征和经济金融信息文本特征两个大方面,使用深度学习模型对其进行预测和分析,也有学者综合以上两种特征,构造既包括技术面参数也包括基本面分析的股价特征向量,输入到模型进行学习,均取得了不错的效果,并有多种模型已经使用到荐股软件或者金融领域中。本文作为综述,只简单的介绍模型以及其基本原理,并期待相关模型能在论文和实验中表现出优秀的性能。
1.在股票特征选择上,直接将股票的技术指标或者基本面指标作为训练数据,缺乏对特征的预处理和特征提取,造成特征冗余或者特征属性片面化,不利于模型发现和学习数据特征真实的意义。
2.在模型选择上,普遍应用单一模型进行预测,没有充分运用机器学习多种不同模型的优势,特征选择上按照经验做法或者行业普遍习惯,没有让计算机自主发现特征的规律,参数调优也依靠经验和已有的成功案例,没有让计算机根据预测结果自主探索参数空间的各种可能性。
本系统所要解决的主要问题:
1.国内的研究者主要关注单一模型对股市预测任务的解决能力,国外研究者已经尝试通过多种机器学习模型对美股进行预测,并取得了不错的效果。选题所要解决的主要问题是多种模型之间参数的传递、调试以及全局学习率等参数的设置与调试,并尝试构建超参数空间,将超参数也作为训练数据,将传统机器学习从业者调参的经验通过机器学习的方式固定下来,以便于应对多种复杂的股价波动场景。
2.由于中国股市偏向于政策市场,与美股资本市场有较大区别,所以选题在数据特征选择方面对技术指标和政策面、基本面指标均有涉及,并尝试使用组合的特征向量对模型进行训练,以全面挖掘市场和政策信息对股价的影响。
3.对于基金投资公司和机构投资者而言,持股策略偏向稳重,不会在短期内高频交易,买卖时机更倾向于中长线。选题所选用的数据特征以及预期的预测结果更倾向于为机构投资者这样的用户使用,而不是为散户等高频交易人员使用。当然,模型本身也可以接受每分钟交易情况,并预测一日内股价涨跌,这个目标作为本选题的中长期目标,期待在后期进行实现。
创新点:
1.使用VAE、GAN等非监督生成模型对股价进行预测,而不是传统的非线性回归模型,这在国内的研究领域内还属于未被开垦的荒地。
2.使用DRL深度强化学习调整超参数,控制整体模型,并通过反复迭代逼近真实股价走势,这种方法在机器人控制、自动驾驶领域方兴未艾,AlphaGo、AlphaMaster等围棋人工智能也是基于马尔科夫链蒙特卡洛方法的强化学习模型进行训练的,目前国内外研究者还鲜有在其他领域进行迁移和尝试。选题尝试将其迁移至股价预测模型研究,并作为辅助的调参手段,期待其能自主探索机器学习最优的模型。
股票市场相关理论解读:http://www.iwencai.com/school/article?cateId=533&fcateId=1
趋势理论:http://www.iwencai.com/school/article?cateId=531&fcateId=1
1.市场主体:股票二级市场的投资行为主体分为主力和散户两大类,主力拥有内部消息知情权,在投资上具有先于散户的优势,且主力盈利目的明确;散户以自我为中心,具备一定的交易策略,受政策、消息、新闻事件影响较大。
2.交易规则:股价高低决定于买卖关系,即卖出价<=买入价时,方可成交。如果买入订单数量大于卖出订单数量,即供不应求,则优先成交低价的卖出订单,实时股价随之上涨;如果卖出订单数量大于买入订单数量,即供大于求,则优先成交高价的买入订单,实时股价随之下跌。
3.竞价:实际股票交易过程中,投资者往往选择挂单的形式,即在某一价格上预定买卖订单,待股价涨跌至指定价格时订单成交。所以随着股价波动,在股价水平线上下分别挂有买和卖的订单,由交易所计算机撮合最大的一笔成交订单的股价作为当前的股价成交。也就是说,二级市场交易有趋多特性,尽可能多的促成交易。
4.投资行为:投资行为决定了股票价格,而影响投资行为的因素,除了主力在获取内部信息并制定了投资方案之外,还有外部信息造成的干扰,我们认为:在t时刻之前的信息流作为投资者决策的全部信息来源,信息价值随着delta(t-t0)而逐渐衰减,即历史信息的价值<=实时信息的价值。
5.理性假设:我们认为,投资者都是以营利为目的,不存在损己利他为目的的交易行为,而且投资行为趋向于理性,即投资行为趋向于营利概率大的方向进行实施。
6.风险理论:高风险高回报,存在投资者以冒险精神进行投资,即承担损失以获取长期或者超短期的回报。
刚开始研究这个问题时画的框架图,也成功蒙住了几位导师。随着学习的深入并且经过一系列实验之后,发现这样的系统无法实现自己想要的功能,落入俗套了。
于是,改革开放,更新框架图。
容我喝口水慢慢梳理这个框架。
1.股价的行情信息按照时间跨度进行划分,时间跨度大的有月线、周线行情,时间跨度小的有1分钟、5分钟行情,不过,以上行情信息的基本数据元只是:开盘价、收盘价、最高价、最低价、成交量和成交额这6个基本信息,然后按照时间切片后得到离散的行情。
2.行情信息体现的是市场自由交易的情况,卖家报价,买家出钱,多空博弈,瞬息万变,想要预测市场上投资者的投资意愿是一件几乎不可能的事情,我们只能根据客观的公开的数据来推测投资者会如何行动。所以除了行情信息之外,我们还需要上市公司的财务、经营情况,外部市场的信息,期货、基金等金融衍生物市场信息,现金流方面银行的存贷款利率,借贷利率等等,也就说,我们获取的信息越多元,得到的投资预测越有可能接近市场上投资者真正的投资意愿。
3.基于以上考虑,首先我们要获得股票的行情,以日行情为主,同时我们要获得上市公司财务等基本面数据,外部市场、宏观经济等数据,作为日行情的特征,这样就得到了一个上百维度的股价数据集,通过时间序列模型我们就可以预测未来的股价走势情况。
4.经过试验,以上想法思路是对的,但是有这么几个问题:一是预测得到的结果随着预测时间点的推移误差积累直到模型迅速塌陷,反映了股价模型的参数是随着时间变化的函数,我们无法用一个固定的深度神经网络来预测股价,股价预测模型必须随时间不断变化。 二是在趋势上,虽然可以基本预测出股价走势,但是绝对值数据误差无法避免,必须通过其他方式修正误差。 三是目前没有现成的估价时间预测模型可以直接拿来就用。
5.所以,从自编码器中获得的灵感,我想通过文本序列分析加编码方式,解决股价预测问题。
5.1 框架图内数据特征工程阶段,通过将日线数据和分钟线数据分别处理,得到两个数据集,其中这两个数据集的关系是,1个日线是240个分钟线数据的结果,也就是1天的股价波动体现在240分钟股价波动上。
5.2 日线数据除了行情数据之外,还是有基本面数据、宏观经济数据、外部市场数据等,作为日股价的特征,训练堆叠LSTM网络,预测未来1-10日的股价走势。
5.3 每日的分钟线数据是一个标准的数据集,包括240个时间点,每个时间点都是开盘、收盘、最高、最低、成交量、成交额信息,也就是240 * 6 = 1200维数据。将每日的分钟线数据编码,编码的标签就是1日的行情结果,可以用涨跌额,成交额等等代替。
5.4 每日市场上都会有大量的财经新闻信息,包括非交易日、外部市场的信息都有可能对下一个交易日的行情起作用。说白了,财经信息直接传递到投资者,投资者根据财经信息判断市场走势,并作出自己的投资行动。我们想对每日的财经信息进行信息抽取和归纳,将财经信息这种文本数据映射到一个高维的,我们称之为“投资取向函数”的时变函数上,然后将这个时变函数与每日的分钟行情数据做关联,通过编码映射出一个文本信息——取向函数——股票行情的映射,这个映射的参数是时间t,文本p和相关系数λ,函数的结果就是预测的未来行情。如果我们能够成功学习到这个函数,那么预测股价只需要两步:一是通过长期趋势得到一个结果Z0,二是通过这个函数得到Z1,将这两个结果通过加权系数α,就可以得到最终的股价预测结果。
6.预测长期走势,我们将使用LSTM网络,编码文本信息我们直接使用fine tuning的BERT模型,编码分钟线行情我们准备用WGAN,最后的股价加权直接用普通的全连接层。
7.在这里面,还没有使用RL进行超参数调优,考虑到股价模型是时变模型,我们用Q函数模拟时变函数,进而进一步提高模型拟合股价的能力。
通过tushare获取上证50成分股中部分股票每日成交信息和财务信息,包括:日线行情、资金流向、利润、资产负债情况、现金流量、财务报表等信息。数据的时间跨度为十年,从2008年1月1日至2018年12月31日。同时,获取了这个时间跨度内的宏观经济数据,包括利率、银行间同业拆借利率,民间借贷利率;市场交易数据,包括:沪深港通资金流向、北向资金流入、大宗交易、股票质押回购等信息。数据维度共576维。
StockData类:
1.getStockList():获取股票基本信息:股票列表、上市公司基本信息
2.getStockMarket():获取股票行情:代码、交易日、开盘价、收盘价、最高价、最低价、昨收价、涨跌幅、成交量、成交额
3.getDailyIndicator():获取每日指标:股票代码、交易日期、收盘价、换手率、量比、市盈率、市净率、市销率、总股本、流通股本、市值、流通市值。
4.getStockCurrent():个股资金流向:股票代码、交易日期、小单买入量(手)、小单买入金额(万元)、小单卖出量(手)、小单卖出金额(万元)、中单买入量(手)、中单买入金额(万元)、中单卖出量(手)、中单卖出金额(万元)、大单买入量(手)、大单买入金额(万元)、大单卖出量(手)、大单卖出金额(万元)、特大单买入量(手)、特大单买入金额(万元)、特大单卖出量(手)、特大单卖出金额(万元)、净流入量(手)、净流入额(万元)
StockFinance类:获取财务数据 API参考tushare
1.getProfit():获取上市公司财务利润
2.getBalanceSheet():获取上市公司资产负债表
3.getCashflow():获取上市公司现金流量表
4.getForecast():获取业绩预告数据
5.getExpress():获取上市公司业绩快报
6.getDividend():获取分红送股
7.getFinacialIndicator():获取上市公司财务指标数据
8.getFinacialAudit():获取上市公司定期财务审计意见数据
9.getFinacialMain():获得上市公司主营业务构成,分地区和产品两种方式
Market类:获取市场参考数据
1.getMoneyflow_HSGT():获取沪股通、深股通、港股通每日资金流向数据,每次最多返回300条记录,总量不限制
2.getSecuritiesMarginTrading():获取融资融券每日交易汇总数据
3.getPledgeState():获取股权质押统计数据
4.getRepurchase():获取上市公司回购股票数据
5.getDesterilization():获取限售股解禁
6.getBlockTrade():获取大宗交易
7.getStockHolder():获取上市公司增减持数据,了解重要股东近期及历史上的股份增减变化
Index类:指数
1.getIndexBasic():获取指数基础信息。
2.getIndexDaily():获取指数每日行情,还可以通过bar接口获取。
3.getIndexWeight():获取各类指数成分和权重,月度数据
4.getStockMarketIndex():上证综指指标数据
Futures类:期货
1.getFuturesDaily():获取期货日线
2.getFururesHolding():获取每日成交量
3.getFuturesWSR():获取仓单日报
Interest类:利率
1.getShibor():上海银行间同业拆放利率(Shanghai Interbank Offered Rate,简称Shibor),以位于上海的全国银行间同业拆借中心为技术平台计算、发布并命名,是由信用等级较高的银行组成报价团自主报出的人民币同业拆出利率计算确定的算术平均利率,是单利、无担保、批发性利率。
2.getShiborQuote():Shibor报价数据
3.getShibor_LPR():贷款基础利率(Loan Prime Rate,简称LPR),是基于报价行自主报出的最优贷款利率计算并发布的贷款市场参考利率。目前,对社会公布1年期贷款基础利率。
4.getLibor():Libor(London Interbank Offered Rate ),即伦敦同业拆借利率,是指伦敦的第一流银行之间短期资金借贷的利率,是国际金融市场中大多数浮动利率的基础利率。
5.getHibor():HIBOR (Hongkong InterBank Offered Rate),是香港银行同行业拆借利率。指香港货币市场上,银行与银行之间的一年期以下的短期资金借贷利率,从伦敦同业拆借利率(LIBOR)变化出来的。
6.getWenZhouIndex():温州指数 ,即温州民间融资综合利率指数,该指数及时反映民间金融交易活跃度和交易价格。该指数样板数据主要采集于四个方面:由温州市设立的几百家企业测报点,把各自借入的民间资本利率通过各地方金融办不记名申报收集起来;对各小额贷款公司借出的利率进行加权平均;融资性担保公司如典当行在融资过程中的利率,由温州经信委和商务局负责测报;民间借贷服务中心的实时利率。(可选,2012年开放数据)
7.getGuangZhouIndex():广州民间借贷利率(可选)
News类:获取经济和金融新闻
get_news.py:获取新闻,获取主流新闻网站的快讯新闻数据
1.getNews():新闻资讯数据从2018年10月7日开始有数据 之前没有数据
2.getCompanyPublic():上市公司公告 几乎都是空的
3.getCCTVNews():CCTV 接口限制每分钟100次
特征工程的好坏决定了模型的上限,调参只是逼近这个上限而已。
这个阶段,我计划将收集的数据以每日股价收盘价作为标签,获取技术指标,并作为数据特征。传统技术指标分析主要是针对股价,包括了7日均线,21日均线,MACD平滑异同移动均线,BOLLING布林线等,实际上,股价的波动在影响因素上,取决于非常多的客观交易行为,传统技术指标只是对股价的时间统计特征进行体现,并没有将市场的细节展现出来。本系统我将尝试增加自定义的技术指标,试图追踪交易量、大单买入卖出、换手率等指标的统计特征,并对以上技术指标进行频率分析,以期待获得更多市场行为信息。
基本面分析主要参考上市公司财务数据和公告,但是由于公告涉及到文本分析且数据量较少,这部分仅保留财务数据。另外,宏观经济数据也作为基本面分析的一部分。
特征组合,删除重复特征以及空值处理。由于特征存在大量空值,所以要分情况对空值进行处理,主要的方式是以空值前一日的value填充。即便如此,股价数据集仍然是一个庞大的稀疏矩阵。
在股价趋势预测任务中,暂时不适用于将每日财经新闻进行情感分析并作为事件特征,因为每日新闻数据量较大,对于个股的影响需要提取相关系数矩阵,计算量惊人。考虑到新闻的综合影响会直接体现在交易数据中,所以在技术指标中增加交易数据的统计特征,平衡特征的数量。
概括起来,基本分析主要包括以下三个方面内容:
(1)宏观经济分析。研究经济政策(货币政策、财政政策、税收政策、产业政策等等)、经济指标(国内生产总值、失业率、通胀率、利率、汇率等等)对股票市场的影响。
(2)行业分析。分析产业前景、区域经济发展对上市公司的影响。
(3)公司分析。具体分析上市公司行业地位、市场前景、财务状况。
这里,基本面分析参考的指标主要包括:
外汇 | 期权合约信息 | 期货 | 市场参考数据 | 宏观经济 |
---|---|---|---|---|
外汇基础信息(海外) | 期权合约信息 | 期货合约信息 | 沪深港通资金流向 | 利率数据 |
外汇日线行情 | 期权日线行情 | 期货合约信息 | 沪深股通十大成交股 | shibor利率 |
期货交易日历 | 港股通十大成交股 | shibor报价数据 | ||
期货日线行情 | 融资融券交易汇总 | LPR贷款基础利率 | ||
每日持仓排名 | 融资融券交易明细 | Libor利率 | ||
仓单日报 | 前十大股东 | Hibor利率 | ||
每日结算参数 | 前十大流通股东 | 温州民间借贷利率 | ||
南华期货指数行情 | 龙虎榜每日明细 | 广州民间借贷利率 | ||
期权 | 龙虎榜机构交易明细 | |||
股权质押统计数据 | ||||
股权质押明细数据 | ||||
股票回购 | ||||
概念股分类表 | ||||
概念股明细列表 | ||||
限售股解禁 | ||||
大宗交易 | ||||
股票开户数据 | ||||
股票开户数据(旧) | ||||
股东人数 | ||||
股东增减持 |
技术指标分析是主要的分析手段,技术指标主要包括:
指标 | 格式 | 含义 |
---|---|---|
open | float | 开盘价 |
high | float | 最高价 |
low | float | 最低价 |
close | float | 收盘价 |
pre_close | float | 昨收价 |
change | float | 涨跌额 |
pct_chg | float | 涨跌幅 (未复权,如果是复权请用 通用行情接口 ) |
vol | float | 成交量 (手) |
amount | float | 成交额 (千元) |
close | float | 当日收盘价 |
turnover_rate | float | 换手率(%) |
turnover_rate_f | float | 换手率(自由流通股) |
volume_ratio | float | 量比 |
pe | float | 市盈率(总市值/净利润) |
pe_ttm | float | 市盈率(TTM) |
pb | float | 市净率(总市值/净资产) |
ps | float | 市销率 |
ps_ttm | float | 市销率(TTM) |
total_share | float | 总股本 (万股) |
float_share | float | 流通股本 (万股) |
free_share | float | 自由流通股本 (万) |
total_mv | float | 总市值 (万元) |
circ_mv | float | 流通市值(万元) |
buy_sm_vol | int | 小单买入量(手) |
buy_sm_amount | float | 小单买入金额(万元) |
sell_sm_vol | int | 小单卖出量(手) |
sell_sm_amount | float | 小单卖出金额(万元) |
buy_md_vol | int | 中单买入量(手) |
buy_md_amount | float | 中单买入金额(万元) |
sell_md_vol | int | 中单卖出量(手) |
sell_md_amount | float | 中单卖出金额(万元) |
buy_lg_vol | int | 大单买入量(手) |
buy_lg_amount | float | 大单买入金额(万元) |
sell_lg_vol | int | 大单卖出量(手) |
sell_lg_amount | float | 大单卖出金额(万元) |
buy_elg_vol | int | 特大单买入量(手) |
buy_elg_amount | float | 特大单买入金额(万元) |
sell_elg_vol | int | 特大单卖出量(手) |
sell_elg_amount | float | 特大单卖出金额(万元) |
net_mf_vol | int | 净流入量(手) |
net_mf_amount | float | 净流入额(万元) |
MACD指标又叫指数平滑异同移动平均线,是由查拉尔·阿佩尔(Gerald Apple)所创造的,是一种研判股票买卖时机、跟踪股价运行趋势的技术分析工具。
MACD指标是根据均线的构造原理,对股票价格的收盘价进行平滑处理,求出算术平均值以后再进行计算,是一种趋向类指标。
MACD 指标是运用快速(短期)和慢速(长期)移动平均线及其聚合与分离的征兆,加以双重平滑运算。而根据移动平均线原理发展出来的MACD,一则去除了移动平均线频繁发出假信号的缺陷,二则保留了移动平均线的效果,因此,MACD指标具有均线趋势性、稳重性、安定性等特点,是用来研判买卖股票的时机,预测股票价格涨跌的技术分析指标。
MACD 指标主要是通过EMA、DIF和DEA(或叫MACD、DEM)这三值之间关系的研判,DIF和DEA连接起来的移动平均线的研判以及DIF减去DEM值而绘制成的柱状图(BAR)的研判等来分析判断行情,预测股价中短期趋势的主要的股市技术分析指标。其中,DIF是核心,DEA是辅助。DIF是快速平滑移动平均线(EMA1)和慢速平滑移动平均线(EMA2)的差。BAR柱状图在股市技术软件上是用红柱和绿柱的收缩来研判行情。
MACD在应用上,首先计算出快速移动平均线(即EMA1)和慢速移动平均线(即EMA2),以此两个数值,来作为测量两者(快慢速线)间的离差值(DIF)的依据,然后再求DIF的N周期的平滑移动平均线DEA(也叫MACD、DEM)线。
以EMA1的参数为12日,EMA2的参数为26日,DIF的参数为9日为例来看看MACD的计算过程
1、计算移动平均值(EMA)
12日EMA的算式为
EMA(12)=前一日EMA(12)×11/13+今日收盘价×2/13
26日EMA的算式为
EMA(26)=前一日EMA(26)×25/27+今日收盘价×2/27
2、计算离差值(DIF)
DIF=今日EMA(12)-今日EMA(26)
3、计算DIF的9日EMA
根据离差值计算其9日的EMA,即离差平均值,是所求的MACD值。为了不与指标原名相混淆,此值又名DEA或DEM。
今日DEA(MACD)=前一日DEA×8/10+今日DIF×2/10
计算出的DIF和DEA的数值均为正值或负值。
理论上,在持续的涨势中,12 日EMA线在26日 EMA线之上,其间的正离差值(+DIF)会越来越大;反之,在跌势中离差值可能变为负数(—DIF),也会越来越大,而在行情开始好转时,正负离差值将会缩小。指标MACD正是利用正负的离差值(±DIF)与离差值的N日平均线(N日EMA)的交叉信号作为买卖信号的依据,即再度以快慢速移动线的交叉原理来分析买卖信号。另外,MACD指标在股市软件上还有个辅助指标——BAR柱状线,其公式为:BAR=2×(DIF-DEA),我们还是可以利用BAR 柱状线的收缩来决定买卖时机。
离差值DIF 和离差平均值DEA是研判MACD的主要工具。其计算方法比较烦琐,由于目前这些计算值都会在股市分析软件上由计算机自动完成,因此,投资者只要了解其运算过程即可,而更重要的是掌握它的研判功能。另外,和其他指标的计算一样,由于选用的计算周期的不同,MACD指标也包括日MACD指标、周MACD指标、月MACD指标年MACD指标以及分钟MACD指标等各种类型。经常被用于股市研判的是日MACD指标和周MACD指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。
在实践中,将各点的 DIF和DEA(MACD)连接起来就会形成在零轴上下移动的两条快速(短期)和慢速(长期)线,此即为MACD图。
KDJ指标又叫随机指标,是由乔治·蓝恩博士(George Lane)最早提出的,是一种相当新颖、实用的技术分析指标,它起先用于期货市场的分析,后被广泛用于股市的中短期趋势分析,是期货和股票市场上最常用的技术分析工具。
随机指标KDJ 一般是根据统计学的原理,通过一个特定的周期(常为9日、9周等)内出现过的最高价、最低价及最后一个计算周期的收盘价及这三者之间的比例关系,来计算最后一个计算周期的未成熟随机值RSV,然后根据平滑移动平均线的方法来计算K值、D值与J值,并绘成曲线图来研判股票走势。
随机指标KDJ 是以最高价、最低价及收盘价为基本数据进行计算,得出的K值、D值和J值分别在指标的坐标上形成的一个点,连接无数个这样的点位,就形成一个完整的、能反映价格波动趋势的KDJ指标。它主要是利用价格波动的真实波幅来反映价格走势的强弱和超买超卖现象,在价格尚未上升或下降之前发出买卖信号的一种技术工具。它在设计过程中主要是研究最高价、最低价和收盘价之间的关系,同时也融合了动量观念、强弱指标和移动平均线的一些优点,因此,能够比较迅速、快捷、直观地研判行情。
随机指标KDJ 最早是以KD指标的形式出现,而KD指标是在威廉指标的基础上发展起来的。不过威廉指标只判断股票的超买超卖的现象,在KDJ指标中则融合了移动平均线速度上的观念,形成比较准确的买卖信号依据。在实践中,K线与D线配合J线组成KDJ指标来使用。由于KDJ线本质上是一个随机波动的观念,故其对于掌握中短期行情走势比较准确。
指标KDJ的计算比较复杂,首先要计算周期(n日、n周等)的RSV值,即未成熟随机指标值,然后再计算K值、D值、J值等。以日KDJ数值的计算为例,其计算公式为
n日RSV=(Cn-Ln)÷(Hn-Ln)×100
式中,Cn为第n日收盘价;Ln为n日内的最低价;Hn为n日内的最高价。RSV值始终在1—100间波动。
其次,计算K值与D值:
当日K值=2/3×前一日K值+1/3×当日RSV
当日D值=2/3×前一日D值+1/3×当日K值
若无前一日K 值与D值,则可分别用50来代替。
以9日为周期的KD线为例。首先须计算出最近9日的RSV值,即未成熟随机值,计算公式为
9日RSV=(C-L9)÷(H9-L9)×100
式中,C为第9日的收盘价;L9为9日内的最低价;H9为9日内的最高价。
K值=2/3×前一日 K值+1/3×当日RSV
D值=2/3×前一日K值+1/3×当日RSV
若无前一日K值与D值,则可以分别用50代替。
需要说明的是,式中的平滑因子1/3和2/3是可以人为选定的,不过目前已经约定俗成,固定为1/3和2/3。在大多数股市分析软件中,平滑因子已经被设定为1/3和2/3,不需要作改动。另外,一般在介绍KD时,往往还附带一个J指标。
J指标的计算公式为:
J=3D—2K
实际上,J的实质是反映K值和D值的乖离程度,从而领先KD值找出头部或底部。J值范围可超过100。
J 指标是个辅助指标,最早的KDJ指标只有两条线,即K线和D线,指标也被称为KD指标,随着股市分析技术的发展,KD指标逐渐演变成KDJ指标,从而提高了KDJ指标分析行情的能力。另外,在一些股市重要的分析软件上,KDJ指标的K、D、J参数已经被简化成仅仅一个,即周期数(如日、周、月等),而且,随着股市软件分析技术的发展,投资者只需掌握KDJ形成的基本原理和计算方法,无须去计算K、D、J的值,更为重要的是利用KDJ指标去分析、研判股票行情。
和其他指标的计算一样,由于选用的计算周期的不同,KDJ指标也包括日KDJ指标、周KDJ指标、月KDJ指标年KDJ指标以及分钟KDJ指标等各种类型。经常被用于股市研判的是日KDJ指标和周KDJ指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。
威廉指标WR又叫威廉超买超卖指标,简称威廉指标,是由拉瑞·威廉(Larry William)在1973年发明的,是目前股市技术分析中比较常用的短期研判指标。
威廉指标主要是通过分析一段时间内股价最高价、最低价和收盘价之间的关系,来判断股市的超买超卖现象,预测股价中短期的走势。它主要是利用振荡点来反映市场的超买超卖行为,分析多空双方力量的对比,从而提出有效的信号来研判市场中短期行为的走势。
威廉指标是属于研究股价波幅的技术分析指标,在公式设计上和随机指标的原理比较相似,两者都是从研究股价波幅出发,通过分析一段时间的股票的最高价、最低价和收盘价等这三者关系,来反映市场的买卖气势的强弱,借以考察阶段性市场气氛、判断价格和理性投资价值标准相背离的程度。
和股市其他技术分析指标一样,威廉指标可以运用于行情的各个周期的研判,大体而言,威廉指标可分为日、周、月、年、5 分钟、15分钟、30分钟、60分钟等各种周期。虽然各周期的威廉指标的研判有所区别,但基本原理相差不多。如日威廉指标是表示当天的收盘价在过去的一段日子里的全部价格范围内所处的相对位置,把这些日子里的最高价减去当日收市价,再将其差价除以这段日子的全部价格范围就得出当日的威廉指标。
威廉指标在计算时首先要决定计算参数,此数可以采取一个买卖循环周期的半数。以日为买卖的周期为例,通常所选用的买卖循环周期为8日、14日、28日或56日等,扣除周六和周日,实际交易日为6日、10日、20日或40日等,取其一半则为3日、5日、10日或20日等。
W%R指标的计算主要是利用分析周期内的最高价、最低价及周期结束的收盘价等三者之间的关系展开的。以日威廉指标为例,其计算公式为:
W%R=(Hn—C)÷(Hn—Ln)×100
其中:C为计算日的收盘价,Ln为N周期内的最低价,Hn为N周期内的最高价,公式中的N为选定的计算时间参数,一般为4或14。
以计算周期为14日为例,其计算过程如下:
W%R(14日)=(H14—C)÷(H14—L14)×100
其中,C为第14天的收盘价,H14为14日内的最高价,L14为14日内的最低价。
威廉指标是表示当天的收盘价在过去一段时间里的全部价格范围内所处的相对位置,因此,计算出的W%R值位于0——100之间。越接近0值,表明目前的价位越接近过去14日内的最低价;越接近100值,表明目前的价位越接近过去14日内的最高价,从这点出发,对于威廉指标的研判可能比较更容易理解。
由于计算方法的不同,威廉指标的刻度在有些书中与随机指标W%R 和相对强弱指标RSI一样,顺序是一样的,即上界为100、下界为0。而在我国沪深股市通用的股市分析软件(钱龙、分析家等分析软件系统)中,W%R的刻度与RSI的刻度相反。为方便投资者,这里介绍的W%R的刻度与钱龙(分析家)软件相一致,即上界为0、下界为100。
另外,和其他指标的计算一样,由于选用的计算周期的不同,W%R指标也包括日W%R指标、周W%R指标、月W%R指标和年W%R指标以及分钟W%R指标等各种类型。经常被用于股市研判的是日W%R指标和周W%R指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。
相对强弱指标RSI又叫力度指标,其英文全称为“Relative Strength Index”,由威尔斯·魏尔德﹝Welles Wilder﹞所创造的,是目前股市技术分析中比较常用的中短线指标。
相对强弱指标RSI是根据股票市场上供求关系平衡的原理,通过比较一段时期内单个股票价格的涨跌的幅度或整个市场的指数的涨跌的大小来分析判断市场上多空双方买卖力量的强弱程度,从而判断未来市场走势的一种技术指标。
从它构造的原理来看,与MACD、 TRIX等趋向类指标相同的是,RSI指标是对单个股票或整个市场指数的基本变化趋势作出分析,而与MACD、TRIX等不同的是,RSI指标是先求出单个股票若干时刻的收盘价或整个指数若干时刻收盘指数的强弱,而不是直接对股票的收盘价或股票市场指数进行平滑处理。
相对强弱指标RSI是一定时期内市场的涨幅与涨幅加上跌幅的比值。它是买卖力量在数量上和图形上的体现,投资者可根据其所反映的行情变动情况及轨迹来预测未来股价走势。在实践中,人们通常将其与移动平均线相配合使用,借以提高行情预测的准确性。
相对强弱指标RSI的计算公式有两种
其一:
假设A为N日内收盘价的正数之和,B为N日内收盘价的负数之和乘以(—1)
这样,A和B均为正,将A、B代入RSI计算公式,则
RSI(N)=A÷(A+B)×100
其二:
RS(相对强度)=N日内收盘价涨数和之均值÷N日内收盘价跌数和之均值
RSI(相对强弱指标)=100-100÷(1+RS)
这两个公式虽然有些不同,但计算的结果一样。
以14日RSI指标为例,从当起算,倒推包括当日在内的15个收盘价,以每一日的收盘价减去上一日的收盘价,得到14个数值,这些数值有正有负。这样,RSI指标的计算公式具体如下:
A=14个数字中正数之和
B=14个数字中负数之和乘以(—1)
RSI(14)=A÷(A+B)×100
式中:A为14日中股价向上波动的大小
B为14日中股价向下波动的大小
A+B为股价总的波动大小
RSI 的计算公式实际上就是反映了某一阶段价格上涨所产生的波动占总的波动的百分比率,百分比越大,强势越明显;百分比越小,弱势越明显。RSI的取值介于0— 100之间。在计算出某一日的RSI值以后,可采用平滑运算法计算以后的RSI值,根据RSI值在坐标图上连成的曲线,即为RSI线。
以日为计算周期为例,计算RSI值一般是以5日、10日、14日为一周期。另外也有以6日、12日、24日为计算周期。一般而言,若采用的周期的日数短,RSI指标反应可能比较敏感;日数较长,可能反应迟钝。目前,沪深股市中RSI所选用的基准周期为6日和12日。
和其他指标的计算一样,由于选用的计算周期的不同,RSI 指标也包括日RSI指标、周RSI指标、月RSI指标年RSI指标以及分钟RSI指标等各种类型。经常被用于股市研判的是日RSI指标和周RSI指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。另外,随着股市软件分析技术的发展,投资者只需掌握RSI形成的基本原理和计算方法,无须去计算指标的数值,更为重要的是利用RSI指标去分析、研判股票行情。
CR指标又叫中间意愿指标,它和AR、BR指标又很多相似之处,但更有自己独特的研判功能,是分析股市多空双方力量对比、把握买卖股票时机的一种中长期技术分析工具。
CR指标同AR、BR指标有很多相似的地方,如计算公式和研判法则等,但它与AR、BR指标最大不同的地方在于理论的出发点有不同之处。CR指标的理论出发点是:中间价是股市最有代表性的价格。
为避免AR、 BR指标的不足,在选择计算的均衡价位时,CR指标采用的是上一计算周期的中间价。理论上,比中间价高的价位其能量为“强”,比中间价低的价位其能量为“ 弱”。CR指标以上一个计算周期(如N日)的中间价比较当前周期(如日)的最高价、最低价,计算出一段时期内股价的“强弱”,从而在分析一些股价的异常波动行情时,有其独到的功能。
另外,CR指标不但能够测量人气的热度、价格动量的潜能,而且能够显示出股价的压力带和支撑带,为分析预测股价未来的变化趋势,判断买卖股票的时机提供重要的参考。
由于选用的计算周期不同,CR指标也包括日CR指标、周CR指标、月CR指标、年CR指标以及分钟CR指标等很多种类型。经常被用于股市研判的是日CR指标和周CR指标。虽然它们计算时取值有所不同,但基本的计算方法一样。
以日CR指标为例,其计算公式为:
CR(N日)=P1÷P2×100
式中,P1=∑(H-YM),表示N日以来多方力量的总和
P2=∑(YM-L),表示N日以来空方力量的总和
H表示今日的最高价,L表示今日的最低价
YM表示昨日(上一个交易日)的中间价
CR计算公式中的中间价其实也是一个指标,它是通过对昨日(YM)交易的最高价、最低价、开盘家和收盘价进行加权平均而得到的,其每个价格的权重可以人为地选定。目前比较常用地中间价计算方法有四种:
1、M=(2C+H+L)÷4
2、M=(C+H+L+O)÷4
3、M=(C+H+L)÷3
4、M=(H+L)÷2
式中,C为收盘价,H为最高价,L为最低价,O为开盘价
从四种中间价的计算方法来看,对四种价格的重视程度是不一样的,三种都是选用了收盘价,可见,收盘价在技术分析中的重要性。
和其他技术指标一样,在实战中,投资者不需要进行CR指标的计算,主要是了解CR的计算方法,以便更加深入地掌握CR指标的实质,为运用指标打下基础。
分析股价数据特征,主要对开盘价、收盘价、最高价、最低价、涨跌幅、成交额、换手率、量比、市盈率、市净率、市销率、流通股本、总股本、小、中、大、特大单买入卖出额等特征进行分析,并且对以上特征应用了指数移动平均、差分自相关等数据处理手段。
- 股价、成交量特征
- MACD 异步移动均线
- 布林线和随机指标KDJ
- 开盘价和相关强弱指数RSI
- 威廉指标WR和中间意愿指标CR
- 短线超买超卖指标CCI、成交量变异率VR和波动幅度TR
- 动向指标DMI
- 傅里叶变换和逆变换
- 股价频谱分析
- 收盘价逐日相关性 price correlation
- 特征重要性分析 xgboost回归
- 特征重要性误差分析
我们可以看到,在去除强相关性的特征后,验证集的误差随着训练次数的迭代有所增加,表明模型出现了过拟合。
由于在股价数据中,包含有大量与股价特征强相关的数据,比如开盘价、股价动量(即为前一日的收盘价),股价七日均值等,在使用xgboost进行回归时,这些特征会因强相关特性而独占重要性指标,比如股价动量重要性可达到0.8以上,这样会削弱其他指标的重要性度量。
所以在实际操作中,为了将强相关因素排除,更多的利用其他指标构建股价的特征关系,我们删除了部分特征,并得到了以上特征重要性直方图。以上最重要的特征其重要性也在0.2以下,我们尽可能的实现特征与股价强相关的剥离,并试图发现股价与其他特征的关联。
在训练时,我将训练数据和验证数据比例设置为0.9,但是当我将训练/验证比例设置为0.98时,模型的特征重要性发生了比较明显的变化。在接下来对vae进行训练时,也出现了由于训练/验证比例的变化而造成的结果漂移。
训练模型的数据/验证比例变化会明显的影响结果,这让我很难理解。有可能是模型并没有发现数据的时间序列特性,也可能是特征本身并没有对股价有明显的影响。
我始终反复思考建立股价预测模型的本源是什么:我们想预测一个公司股票的走势,根本目的在于根据交易者以及上市公司本身行为去判断这些行为对股价的影响,以便于提前预测股市未来波动并作出及时的投资策略。一般情况下,投资者会根据股价以及外界信息对投资行为进行执行,上市公司根据法律法规和自身经营情况,对外披露自己的财务、股东、以及盈利情况。这些都是会影响到股价波动的因素。
我们想通过一个模型,在长期对某一只股票的建模基础上,敏感应对以上提到的市场变化,并提前将股价波动预测出来。
我计划首先建立以日交易数据为基础训练集的股价中长期预测模型,这个模型依赖上市公司财务数据、宏观经历数据、以及市场参考数据等,建模更加宏观,忽略每日的波动情况。
在以上基础上,建立以每分钟或者每10分钟交易数据为基础的短期股价预测模型,这个模型更依赖市场随时的变化,以及外界的新闻、突发消息等。期待这个模型能够对当日出现的股价波动和走势进行预判和模拟。
首先,我们需要一些基准模型对股价预测的结果进行评估,除了使用真实的测试数据之外,我们尝试使用几种比较常用的模型对股价进行预测。在特征工程阶段,我们使用了xgboost模型对参数的重要性进行了计算,并找出了25个与股价相关性很高的特征。在模型训练阶段,我们想通过n天的股价训练数据,预测出第n+1天的股价。如果模型的容量足够大,我们甚至可以从n天的股价中预测出n+3、n+7、n+21天的股价波动走势,这样就实现了我们这个项目的最终目的。
我们用监督模型对n+1天的股价进行预测。
1.支持向量机回归模型(SVC)
2.Xgboost集成树模型
3.LSTM网络模型
以上三种模型都是有监督的模型。
其次,我们再尝试使用生成模型对股价进行预测。
1.VAE变分自编码器
2.GAN生成对抗网络
以上两种生成模型本质上都是从高斯分布中采样,并通过模型生成数据样本。如果用贝叶斯理论可以证明其本质上都是一致的,模型都在尝试对真实分布和生成分布的KL散度进行优化和学习。
最后我们想通过DRL对生成模型的参数进行学习,不断尝试优化模型。
TODO
TODO
Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行。Keras 的开发重点是支持快速的实验。能够以最小的时延把你的想法转换为实验结果,是做好研究的关键。
由于本项目基于快速成型的模型搭建原则,所以应用Keras这种高层API更加方便。
允许简单而快速的原型设计(由于用户友好,高度模块化,可扩展性)。 同时支持卷积神经网络和循环神经网络,以及两者的组合。 在 CPU 和 GPU 上无缝运行。
Keras的特征
用户友好。 Keras 是为人类而不是为机器设计的 API。它把用户体验放在首要和中心位置。Keras 遵循减少认知困难的最佳实践:它提供一致且简单的 API,将常见用例所需的用户操作数量降至最低,并且在用户错误时提供清晰和可操作的反馈。
模块化。 模型被理解为由独立的、完全可配置的模块构成的序列或图。这些模块可以以尽可能少的限制组装在一起。特别是神经网络层、损失函数、优化器、初始化方法、激活函数、正则化方法,它们都是可以结合起来构建新模型的模块。
易扩展性。 新的模块是很容易添加的(作为新的类和函数),现有的模块已经提供了充足的示例。由于能够轻松地创建可以提高表现力的新模块,Keras 更加适合高级研究。
基于 Python 实现。 Keras 没有特定格式的单独配置文件。模型定义在 Python 代码中,这些代码紧凑,易于调试,并且易于扩展。
LSTM模型对于时间序列数据的训练来说,具备先天的优势。在本项目中,我借鉴了大神的模型:https://github.com/jaungiers/LSTM-Neural-Network-for-Time-Series-Prediction
模型的预测结果如下:
上图是对股价逐个点进行预测,虽然看上去与实际价格吻合的很好,但是这个结果具有一定的欺骗性,因为模型只需要预测一个点,那么,在下一次预测中,这个预测点实际上就被真实数据取代了,那么模型只需要给出实际误差不是很大的结果就可以莫混过关。
上图是对整个测试序列进行预测,这个结果明显看出,模型并没有学到什么,对于股价波动没有丝毫的敏感性。
上图是以序列为单位进行预测,可以看出虽然在序列的开始节点是比较准确的,但是模型依然对波动不敏感,而且每个序列的第一个点的预测结果跟上面逐个点预测的原因是一样的,再继续使用模型预测波动趋势就会发现模型并没有对股价的涨跌做出反应,这说明模型学习的效果并不理想。
项目使用的是三层叠加的LSTM网络,每层网络100维,最后使用一个全连接层对股价预测输出结果。
我仔细研究了模型思路,发现了一些可以改进的地方:
1.原来的项目中只是仅仅使用了股价的收盘价和成交量为训练数据,只有二维,这显然无法表达股价波动的多种影响因素。我使用了Tushare中获取的股价数据,进行特征整合和去重、特征工程之后,得到了488维的股价数据,也就是说,每一日的股价,伴随有488个不同层面的特征数据对其进行描述。我认为,只有当我们获得了全部数据,才能够真正的发现数据背后的规律。
2.模型使用叠加的LSTM网络可以很好的发现序列数据中的深层结构,但是网络应该将这个序列的结构信息也传递给全连接层,这样才能真正的捕捉时间序列信息,但是原模型并没有将序列整个输出,而仅仅将最后一个 LSTM cell的hidden state输出给全连接层,这样会造成模型学习的知识丢失。
3.由于LSTM网络传递的是三维的数据,在我的实验数据中,数据维度是(2364,50,488),也就是有2364个样本,每个样本有488个特征,以50个时间步为一个训练数据进行训练。这样网络最后输出的结果也是三维的,所以我在Dense层之前添加了一个Flatten层,用来展平三维数据到二维,然后增加了一个Dropout层避免过拟合,这样再输出到Dense层之后,全连接的网络会学习到整个序列在时间上的结构信息,更加有利于准确预测结果。
综上,我修改了原项目中的模型结构和数据结构,主要是增加了新的网络层,并对数据维度进行了扩展,我使用了2008年到2018年十年的股价日收盘价数据进行训练,模型参数总量为169万,预测结果有了很大的提升。
我们可以看到,虽然在股价的绝对值上,预测结果有较大的偏差,但是股价的走势以及每日走势细节。尤其是对股价的剧烈波动都基本能够准确捕捉,可以说模型已经基本学习到了股价波动的趋势。
相比于原模型来说,在以序列为单位进行预测这项任务上,新的模型更能学习到股价趋势。
这个模型只是我实现模型的第一个版本,但是基本可以证明我的思路是正确的,这个版本有一个明显的问题:
我对预测数据的切分,仅仅是按照序列长度进行了等分,相当于模型只是对结果进行了int(test_len/seq_len)个预测,这样的预测很容易受到噪声影响。
所以我又对预测结果进行了改进,借鉴了滑动窗口的思路,将预测结果和滑动窗口结合,对同一个点的结果进行平均,消除噪声的影响。
然后,得到的结果,有那么一点萌 (—.—)
看来时间窗口平滑真的很平滑。
但是不得不说,股价的趋势仍然可以很好的预测出来。如果以这样的预测结果进行量化交易,可以通过对预测值求导的方式,估算出涨跌趋势,从而指导交易。
另外,对于这个模型,还有一个改进的方法。
之前对于训练数据和测试数据,都是在时间窗口内进行的标准化。标准化会对数据的进行重新分布,将数据集的均值和方差都设为标准正态分布。那么问题来了,训练集和测试集实际上每个样本数据都是基于不同的均值和方差的,但是标准化之后它们就具有相同的均值和方差。这样会损失一些信息。如果我们在训练之前,将整个训练集和测试集统一进行一次标准化,使得整体的均值方差保持一致,这样,基于时间的均值和方差序列信息就会更好的保留,并且可能会在一定程度上提高预测的精确度。以上,感觉表述不清,我们用实验来验证一下。
上图是全局标准化之后的结果,我们可以看到,在绝对值上面,相对于窗口标准化的预测结果,股价更加接近于真实数据。在这里我发现应该是窗口预测的原因,两个窗口衔接的位置容易出现比较大的误差。这在实际当中是不可能出现的。于是我又有了一个对窗口衔接处做修正的方案:
上图对窗口的衔接处做了处理,如果前一个窗口的最后一个数据和下一个窗口的第一个数据之间的偏差超过了涨跌停板的限制时,我们人为的将后面一个窗口的数据都修正到涨跌停板的范围内,这样,既不会影响在窗口内模型预测的结果,也使得结果数据更加自然、真实。
上面是全局标准化之后的滑动平均之后的结果,发现也是可以捕获基本的趋势,但是在股价绝对值上面,差别较大。
以上,是基于LSTM网络时间序列预测模型对股价数据的预测情况。基本上,学术和金融界对个这个模型的研究到这里就差不多了。但是我仍然在思考一个问题:
股价预测模型更多的是需要通过历史数据预测未来走势,这并不是简单的时间序列监督学习问题,更多的是将历史数据作为未来股价的特征,并对模型进行训练。虽然LSTM网络就可以捕捉历史信息,但是实际训练时,我们是将每个时间点数据拼接起来作为时间序列,并将这个序列输入模型,预测时,我们也是通过测试集的特征,预测股价这个结果。如果在实际应用中,我并不知道未来一段时间的特征,那我就无法预测未来的股价,我们的模型实际上就没有做到预知未来。
所以,我在思考,有没有可能将未来股价作为标签,现在的数据作为特征,直接在训练数据上就体现出“用过去预测未来”这种理念呢?
带着这个问题,我需要重新规划我的数据集。数据集中,训练集和测试集应该这样划分:
1.过去的数据特征应该可以映射到未来的股价上,即投资者们可能在投资策略和布局上有自己一套计划,这个计划可能短到几天,长到几年,如果我们能够将过去的特征与未来的股价波动构建联系,那么就是说我们发现了众多投资者的策略的规律,这样可以很好的预测未来股价。
2.这种划分还需要避免以下问题,那就是不能够人为的定义训练时间窗口。因为我们的模型的理想状态是通过训练自己发现股票投资者的投资策略和股价的波动的历史原因,而不是我们定义一个时间窗口,单纯以时间窗口的数据进行训练模型。
想破了脑袋,也想不出如何规划这样的训练数据:必须以全部时间步的训练数据为特征,并且标签为未来的未知数据。这样的训练模型,恐怕不是监督学习能搞定的。
综上,我感到监督学习已经无能为力。这是由监督学习的框架和理念决定的,它无法产生新的数据,只能在原有数据上不断近似和逼近。
但是通过使用LSTM模型对高维特征进行分析,我们仍然可以看到,模型能够学习到一些价格波动规律,这就说明股价在一定程度上是可预测的!我们需要综合各种深度学习模型并应用到实际需求当中。监督模型可以挖掘特定的时间序列中特征集合与标签之间的内在联系,无监督模型可以自己去发现样本集的特征、分布等高维的规律,并用编码或者神经网络去表征。我们既需要发现在一段时间内股价与特征之间的关系,也需要发现股价的历史信息中的分布信息等高维信息,并以此为依据去预测未来的股价波动。这是监督模型和非监督模型的结合。
之前,我使用了LSTM模型,以50个交易日为一个period作为训练样本,训练了能够捕捉股价波动趋势的模型,取得了想要的效果。但是模型最大的问题是:
1.股价预测任务不是监督学习任务,我们在无法获得未来股价的特征时,显然也就无法预测未来股价。
2.股价的波动趋势能够被模型学习到,主要原因可能是开盘价、最高最低价等与收盘价强相关的信息作为特征,模型可以比较容易的推测出结果,模型就不需要学习上市公司财报、财务数据等基本面数据或者成交量等技术指标,所以,这个模型可能没有学习到股价的真正特征。
针对以上问题,我也是想破了脑袋叫破了喉咙。决定以四步走的形式,彻底解决这个问题:
1.重新规划训练模型。这一次,我想让模型学习到历史数据对未来股价的影响,也就是说,我能够在只知道现在和历史的成交信息的基础上,预测出未来n-m个交易日的股价。在训练数据上,以n为窗口,1为步长划分数据,在n这个窗口内,取m=λn,λ一般取0.9,也就是说将窗口内m个数据特征作为训练数据,而n-m个标签作为这个窗口训练的标签,这样的话,模型就可以训练出m天的数据对未来n-m股价的映射。仍然通过LSTM网络进行训练和测试。
2.如果步骤1可以得到比较满意的效果,那么说明模型可以学到历史数据对未来股价的影响情况,那么,我们就可以构建一个序列生成模型GAN,以LSTM为生成器,CNN为判别器,同时还对股价特征空间进行编码。
3.在这个基础上,我们再利用Bert模型对市场信息、上市公司财报等数据进行编码和情感分析,可以得到一个关于市场积极程度的编码向量,利用这个编码向量对GAN模型生成向量进行加权,就可以将市场短期的情绪加入到模型生成中,从而训练出既能够把握市场长期趋势,又能够考虑到短期的财经新闻和消息对股价影响的模型。
4.最后,对于多重的模型,我们既要交替训练,又要使用强化学习不同模型loss的权重进行探索和调试,期待最后收敛到一个合理的范围。
以上,就是我目前对于整个系统的全部思路,可以说是一边学习,一边实验,一边调整思路,好在一开始的夙愿和想法的大方向,都没有变,只是在细节和实现路径上,不断的试错和修正。
那么接下来,任何开源的项目都没有做过的模型,就要开始搭建了。
1.本想从数据的组织上解决预测的问题,经过试验后发现自己太天真了。
模型:三层堆叠LSTM,latent_dim=256,return_seq=True,Dropout=0.4 数据:"sequence_length": 100, "train_test_split": 0.9, "predict_window": 0.1,
按照之前的计划,我使用100天的数据作为一个数据窗口,将整个数据集先进行标准化,再进行窗口划分,再按照train_test_split=0.9比例分为训练集和测试集,窗口内,根据predict_window=0.1,将前90个489维的数据作为训练数据,后面10个收盘价作为标签,进行训练,预测时,将预测结果进行拼接,得到股价预测走势图。
Epoch 1/5 2092/2092 [==============================] - 47s 23ms/step - loss: 27.6827 - val_loss: 3.0706
Epoch 2/5 2092/2092 [==============================] - 45s 21ms/step - loss: 2.6332 - val_loss: 2.8802
Epoch 3/5 2092/2092 [==============================] - 45s 22ms/step - loss: 1.7592 - val_loss: 2.7003
Epoch 4/5 2092/2092 [==============================] - 58s 28ms/step - loss: 1.5383 - val_loss: 3.2447
训练情况还可以,训练误差和验证误差都可控,最后由于val_loss升高而earlystop了,但是最后的预测结果出现了很大问题。 上图。
我们可以看到,股价预测结果在一开始还基本捕捉到了走势,但是随着时间的增加,后面的预测结果出现很大的偏差。基本可以说,时间序列预测任务,模型的参数是在不断变化的。里面提到的概念漂移问题在这次实验中体现的很明显。 参考这篇文章,https://zhuanlan.zhihu.com/p/54413813
所谓概念漂移,表示目标变量的统计特性随着时间的推移以不可预见的方式变化的现象,也就是每过一段时间序列的规律是会变化的。所以,在这种情况下,拿全部时间内的数据去训练,就相当于是增加了各种噪声,预测精度是会下降的。所以,一种解决办法是不断的取最新的一阶段内的数据来训练模型做预测。之前做过一个变压器油温预测的数据,实验了用全量数据,一年内的数据,半年,3个月,一个月的数据做训练,其后几天的数据做预测,发现一个月的效果是最好的。那么如果你要问我,怎么判断一个序列是否存在概念漂移,我会告诉你,我也不知道,做实验吧!
本次实验中,由于股价模型的参数不断变化,预测结果在一开始还能基本符合真实数据,随着时间推移逐渐出现了偏差积累的情况。
咋办?
然后我又调整了超参数,将数据窗口拉长,预测窗口压缩,得到的结果.....
数据:"sequence_length": 200, "train_test_split": 0.95, "predict_window": 0.05,
结果嘛,模型直接炸了,验证集误差爆炸了,这说明,增加窗口长度没有任何帮助。那就再减小它。
数据:"sequence_length": 50, "train_test_split": 0.9, "predict_window": 0.1,
结果呢?
我们发现模型普遍在后面的预测结果上出现问题,而一开始的预测结果虽然绝对值偏差较大,但是趋势基本吻合。
这就更加印证了我的判断,股市模型参数是随着时间变化的,无法用一个静态模型预测未来长期的走势,模型必须也要随着时间变化。
这样的话,股价预测这种时间序列预测问题,过于久远的数据其实对未来的预测并没有太大的作用,或者这样理解,对于日线数据预测,有效的预测应该是基于最近n天的数据,而对于月线或者年线预测,有效的可能就是最近n月、n年,这个时间窗口内才对未来的预测有贡献,而历史数据的贡献程度,取决于我们要怎样预测未来,是按照日线收盘价预测还是年线收盘价预测,就是这样。
那么,我们的终极目标是想预测未来几天的股价走势,通过实验证明:一是根据日线数据来进行趋势预测,具体的股价绝对值,我们还需要利用其他数据进行修正。
我们知道,长期股价预测看基本面数据,以上实验就是实现了这个预测,但是结果并不理想,我们转而想要预测短期股价波动。这里,我们计划使用成熟的Bert服务,对财经新闻进行编码并训练,看看财经新闻对股价波动是什么样的影响。
股价走势作为一种时间序列信息,如果我们以1分钟作为周期进行采样的话,那么每日的走势就是一个特征维度为开盘、收盘、最高、最低、成交量5个维度,时间上是240分钟的一个固定的特征集合。交易者进行交易的依据,一部分来自于股价涨或者跌的走势,一部分来自于各个方面的市场消息,所以,我尝试利用Bert模型对财经信息进行训练调优,结合股价1日的交易数据,使用自编码器编码每天的股价走势,用低维度的编码近似反映1个交易日内股价走势,结合生成模型GAN,生成有编码影响的股价走势。
我们想直接使用成熟的bert编码框架,可以将任意长度的中文序列编码为固定长度的编码。这样我们就可以不用考虑Bert模型的实现细节,专注于对于编码之后的向量进行学习和处理。我们直接使用了Bert as service。
感谢:https://github.com/hanxiao/bert-as-service
编码之后的向量进行了归一化,但是我们仍然可以通过可视化的方式看出不同标签下编码的分布,由于编码时768维,我们随机选取2个维度进行可视化。
财经新闻的信息主要有10个标签,分别是: names = ['宏观','行业','公司','数据','市场','观点','央行','其他','焦点','A股']。
随机选取2个维度:
对比多个维度:
我们可以看出,仅仅通过2个维度很难区别不同标签的编码有明显不同,但是同一个标签下的新闻还是有一定的聚类特征,通过这个我们可以推测出,编码在高维空间中有可能会表现更好的区分特性。
还有一个问题需要注意:因为财经新闻发生的时间是随机的,在一个指定的时间段内,我们无法预知新闻编码出现的时间点,这样会对模型数据的特征工程带来一些问题,所以我准备在处理财经新闻数据时,将没有新闻发生的时间点人工填充数据,使用的是高斯噪声数据。通过以上的编码可视化我们可以看出,bert编码的整个分布其实也倾向于高斯噪声,我们使用人工数据不会对模型的学习带来太多负面影响。
利用Keras自带的vae模型,尝试对股价特征进行编码时,出现无法训练,训练loss为负数,验证集loss直接发散的情况。我尝试修改了隐层的参数,用更大维度的隐层编码,发现结果并没有变化。
首先是用训练集/验证集为0.9的情况下对模型进行训练的结果:
训练结果很糟糕,模型没有被训练出来,但是encode的前两个维度貌似有聚集的特征。
然后用训练集/验证集为0.98的情况下对模型进行训练:
验证loss出现很大的波动,而且训练误差为负数,编码反而更加随机。
综合考虑可能有如下原因:
1.股价数据是时间序列数据:原版的变分模型没有对时间序列信息进行编码的能力,仅仅是对图像编码的移植。
2.股价的特征选择问题:一个上市公司的股价波动与其财务、市场信息的关联性较小,特征无法代表股价的走势。
3.模型还没有发现股价走势的深层信息,或者是无法拟合股价的波动特性。
原版的VAE模型是用来处理图像的,主要是用来生成nmist数据集中的手写数字,在直接用于时间序列数据中时,出现很多问题。我想,我们需要修改原本的模型结构,使其能够处理时序数据。
TODO
seq2seq模型是一个比较经典的序列编解码模型,主要用在机器翻译、标题生成、主题归纳等场景,在NLP环境下,语言模型都是离散的向量组成,seq2seq模型捕捉离散向量之间的时序关系并进行编解码,实现对文本的生成。
从另一个角度来看,encoder-decoder模型是有信息瓶颈的,也就是编码的维度,所以本身这个模型无法传递大量的文本信息,在长序列编码场景下,受限于编码的维度所携带的信息受香农定律所限,有可能出现模型的极限。
股价波动本身是市场投资者投资意愿动力学的反应,股价本身具有高度的无自相关性,因果性很难把握和预测,但是大量投资者行为是有统计学规律的,而且主力操作和散户操作所适用的动力学模型是不同的。
我们假设,短期的股市波动主要动因是投资者的投资意愿,投资意愿又来自于市场的风吹草动,财经新闻是一个很好的反应市场投资动向的因素,因为财经新闻涉及面很广,包含有大量有价值的投资信息,投资者可能会根据消息跟风进行投资。
以下是财经新闻部分截取:
10:28新能源汽车股直线拉升,中通客车封涨停,亚星客车大涨7%,北汽蓝谷、泉峰汽车、华菱星马等多只个股走强。
10:23【工信部:将支持有条件的地方建立燃油汽车禁行区试点】工信部答复制定禁售燃油车时间表建议:将支持有条件的地方建立燃油汽车禁行区试点。
10:18【武汉集聚芯片企业突破百家】8月21日,湖北省庆祝新中国成立70周年系列新闻发布会第五场,主题为“武汉——产业之‘芯’、区域之‘心’、动能之‘新’”。会上披露,武汉已集聚芯片企业100余家,一个以芯片设计为引领、芯片制造为核心、封装测试与材料为配套的集成电路产业链正在形成。(湖北日报)
10:03【片仔癀中药饮片因“一般缺陷5项”被福建省药监局勒令整改日前,福建省食药监局公布的“2019年中药饮片质量集中整治(生产环节)专项检查及处理情况公示“显示,,漳州片仔癀药业股份有限公司、福建铭远制药有限公司等企业因生产的中药饮片存在缺陷而被勒令整改。
10:03OLED板块异动,领益智造大涨6%,长信科技涨5%,京东方A、香山股份、深天马A、晶瑞股份、国风塑业集体走强。
10:02啤酒板块拉升,珠江啤酒直线封板,燕京啤酒、兰州黄河、青岛啤酒、惠泉啤酒等纷纷走强。
09:57【基本医疗卫生与健康促进法草案:医疗卫生机构不得对外出租、承包医疗科室】 基本医疗卫生与健康促进法草案明确举办医疗机构应当具备的条件,规定医疗卫生机构不得对外出租、承包医疗科室,非营利性医疗卫生机构不得向出资人分配收益,禁止伪造、变造、买卖、出租、出借医疗机构执业许可证。同时,草案加大对上述违法行为的处罚。(央广)
我们可以看到,财经新闻包含各个投资板块的消息,而且还有对股市波动的描述,虽然是总结性、报道性的新闻,但给投资者以积极或者消极的信号,也是能够反映一部分投资者投资意向的。
我们想通过财经新闻,反映出股市波动,看新闻中有没有可以影响股市波动的因素。
我们将使用seq2seq模型对股价进行建模。首先我们要对财经新闻进行处理,我们使用了bert预训练模型对变长的新闻文本序列编码成一个768维向量,因为新闻发生具有不确定性,所以我们使用一些噪声数据填充新闻序列,之前的可视化结果可以发现bert编码出来之后的结果在空间中具有高斯噪声的特性,所以我们也使用近似的噪声数据填充。
然后我们要划分不同时段的编码样本,由于每天的开盘时间一共只有4个小时,这4个小时内的新闻流是很有参考价值的,我们假设它与实时的股价波动有关联关系,休盘的20个小时,从财经新闻的角度看,也包含一些有价值的信息,但是这时候没有直接的交易,我们假设休盘期的新闻会影响投资者心理,并且最终影响在下一个开盘日的开盘价上,也就是一个昨收盘和今开盘的差别。如果这样的话,我们的模型需要处理两种不同的样本:
1.休盘期新闻编码序列样本和昨收今开的差;
2.开盘期新闻编码序列和股价波动序列。
这样的编解码器需要进行微调,我们以seq2seq编解码器为核心,在解码器段增加额外的网络层以将序列输出转化为标量,并反映在标签信息上。训练时,我们需要划分样本进行训练,对于休盘期新闻,通过间隔等参数,用生成器生成序列和标签,训练m个batch后,再使用 开盘期新闻训练序列标签,这两个训练过程是共享整个编码器和解码器的权重的,这样可使模型尽可能的发现新闻中影响投资者行文的消息。
时序卷积(Temporal Convolutional Networks)模型在许多领域上被证明是可以取代RNN网络的深度模型,相比于传统的RNN模型,时序卷积因其强大的可扩展性、长时依赖性以及可并行能力,使得在大量的任务中表现出比RNN更加优异的性能。
先上图。
如上图可以看到,本系统中使用的网络是一个深度网络,其中大量的卷积层和残差连接构成了这个深度网络的基础。
使用了大概一周的时间系统学习了GAN这个庞大的生成模型体系,这里还是要非常感谢苏神的博客提供的通俗易懂且鞭辟入里的解释。
GAN中的对抗和生成两个模型,看上去只需要将各自的结果进行比较,然后分别根据比较结果优化自己模型,最后实现生成结果与真实结果逐步逼近即可。但实际上,这个过程中包含了非常丰富的数学推导,极其广泛的数理基础以及可以推广到很多方面的应用前景。
目前GAN网络在图像编码和生成方面取得了卓有成效的进展,我们可以看到人脸图片的生成过程,包括从一个男性脸逐渐变成婴儿脸的逐步渐进的变化情况。我们将其理解为,模型学习到了人脸数据集中不同人脸的特征,并将这些特征编码,再将这个编码空间映射到一个高斯分布空间中,确保整个编码空间可以被采样到,这样话,我们就能够通过人工设定采样参数的方式获取到这个编码,从而生成我们想要的人脸图像。这个思路是将人脸特征信息从隐参数空间中挖掘出来,成为一个能被大家所利用的特征,我们就可以使用这个特征空间,来做很多有趣的事情。
作为股价生成任务中的模型,我始终在思考如何将图像处理任务迁移到时间序列模型的生成任务上来,在前人所做的研究中,SeqGAN完成了文本信息的GAN网络,通过LSTM模型作为生成器,CNN网络作为判别器,使用Policy Gradient强化学习算法的loss作为优化对象进行seq to seq的生成任务,取得了一定的成果。但是文本信息生成任务与股价信息生成任务还是有一些区别。主要是问答系统或者翻译系统的seq to seq模型基于的是编码,以编码为传递信息的主要媒介,再看seqGAN模型,也是将这个编码映射到高斯空间,中间也加入了一些便于模型收敛的技巧。而股价模型更多的是通过历史交易数据预测未来,历史数据与未来数据有一定的时间连续性,而且股价特征既有消息面、技术面也有基本面,如何捕捉这些特征并预测未来股价,与传统的文本序列生成模型有很大不同。这也是我始终在纠结和思考的问题。
以上是我在刚刚学习GAN网络的思想的时候提出来的想法,也是照搬了大神的模型思路,但是我注意到一点,目前绝大部分的GAN模型,其生成器和判别器都是相当规模的同样类型的模型,比如目前应用了W散度做L约束的WGAN-div,原文:https://kexue.fm/archives/6139。
它主要使用了两个规模相同但是内部结构相反的CNN网络作为生成器和判别器,再加上使用使用了W散度作为惩罚项,性能上优于基于梯度惩罚的WGAN,在图像生成任务上表现较好。
那么在序列生成任务上,是否也应该在生成器和判别器的规模上进行权衡,尽量做到二者一致。
另外,序列判别器可以视为一个文本分类任务,而序列生成器可以视为一个seq2seq的Decoder,这样的话,二者都使用单层的LSTM网络更容易被我们传统思维接受。
废话不多说,干。
- Keras-rl库
TODO
感谢支持,赚个积分。