目录
Version 1 最简单策略
Version 1.1
Version 1.2
Version 2 综合考察
Version 2.1
Version 3 强化学习RL
RL简介
Gym简介
实现效果
策略:仅考察4.5这一列。
在某一天观察5天后的数据,若上升则买入,下降卖出。
上升/下跌的幅度超过1才视为有变化。
运行结果:
问题/改进方向:
收益曲线不平滑且与均值离散程度较高(但是为什么感觉方差没有很大?)
最大收益与最大亏损相差大。
策略中,是向后参考,但向前参考是否会更符合真实情况?
在1.1的基础上,做出如下修改:
由前向(向未来)参考数据改为后向(向历史)参考数据,符合真实情况。
对2.5/3.5/4.5的数据都进行上述操作,结果画出三张折线图。
改为数据上升卖出,下降买入。
声明:
在买卖操作中,没有进行买卖操作匹配,原因是实质上只对一列的数据进行加减操作,无法很好的规定某次卖出操作一定是跟某次买入操作对应的。因此,这里采取的是一个类似堆栈的实现方式,也就是说,先买先卖。这样的对应方式,对最后的总收益/亏损和均值没有影响,但可能会对极值以及方差造成一定影响。但在这种情形下,先买先卖似乎是最合理的处理方式了。毕竟这不像股票,买卖是同一支股票的一对相反操作。
运行结果:
提升:
改为前向参考之后,收益明显提高。
三个期限的数据都得到了计算,可以互为参考。
问题/改进方向:
收益曲线不平滑且与均值离散程度较高。
最大收益与最大亏损相差大。
求和level中所有负数,再减去所有正数,得到-7576.461,该数据或许视为理论最大收益。
观察4.5/3.5/2.5三列数据得到如下结论:
3.5和2.5的曲线形态类似,而4.5的曲线与前两者区别较大。
90以上的数据均为少数,且出现的时间接近。
经过排序输出后发现,表格中每一列的数据实际上是都同一组数据,只是次序有区别。
策略如下:
由于3.5/2.5两条曲线形态接近,因此将这二者视为一组。
将当天数据与五天前数据进行对比,结果作为判断依据。
认为数据差距σ>=0.1才是有变化。
若3.5/2.5的变化趋势相同,则遵照3.5/2.5的变化确定买卖;否则以4.5的变化为准确定买卖。
策略结果:
根据策略运行结果得出以下结论:
由于将σ变为0.1,为了控制变量,将策略1.2中的相应部分进行修改再运行后得到如下结果:
这时总收益/方差比提高到222,而2.5的总收益/方差比反而有所降低。
综上,若是将总收益/方差比作为评判策略效益的标准,则在情况下的当前策略为目前效益最高的策略。
Reinforcement Learning,强化学习,是机器学习中一种的一种算法。
强化学习与监督学习等算法不同,其针对的主要是决策问题(即怎么做)。
用机器学习中最经典的西瓜案例来对强化学习和监督学习进行比较:
监督学习:
监督学习一般是根据一些特征,最后对结果进行预测。对应西瓜的案例,便是根据色泽、根蒂等西瓜的特征预测一个西瓜会不会是好瓜。
强化学习:
强化学习更加针对如何决策的问题,如果说监督学习的任务是判断一个西瓜是不是好瓜,那强化学习的任务则是研究如何种出好西瓜。
使用强化学习的问题一般包含多步决策过程,过程中包含状态、动作、反馈(奖赏)等,需多次种瓜、在过程中不断摸索、最终得到一个比较好的种瓜策略。
最后,用最简单的话来描述强化学习就是,机器通过在环境中不断尝试,从而学到一个策略,使得长期执行该策略后得到的累积奖赏最大。
Gym是一个开源的、主要用于强化学习的标准API。
Gym通过实现“agent-environment loop”来实现RL。简单来说,就是agent(可以理解为策略)在environment(环境)中执行一些action(通常是传递一些控制输入等给环境)并且observe环境的状态的变化。一次这样的action-observation行为被称为一次timestep。每一次timestep都会根据环境的变化给出reward(奖赏值),而agent的最终目的就是使得总奖赏值最大。
要使用Gym或者运行基于Gym编写的程序,就需要安装Gym环境,但是在windows下直接使用pip安装Gym库好像会出一些奇奇怪怪的问题,所以建议先安装anaconda环境,再在conda环境下安装Gym。关于环境的下载具体可以参考以下两篇博客:
anaconda安装教程
gym安装教程
自定义环境的搭建和使用参考这两篇博客:
gym搭建自己的环境
详细定义自己的myenv.py文件以及算法实现
关于数据集的处理。由于强化学习本身是一个不断根据环境状态和之前执行的步骤进行学习、调整的算法,最后得到一个效益相对最高的策略。但是由于金融数据的特殊性(数据集小、数据具有依赖性等),可能实际上无法根据历史数据得到一个高度可靠的策略。面对这种情况,有两种处理数据集的思路:
第一种思路是不将历史数据划分为训练集和测试集,将所有数据都用于模型的训练和学习。这种思路是基于强化学习任务的最终目的是获得最大总奖赏、因此没必要将本就不多的数据划出一部分进行测试的想法。用于训练算法的数据越多,模型可能遇到的数据变化情况就可能越多,未来数据的特征(即环境特征)此前出现过的可能性就越高,模型适用性就可能更强。但是使用这种思路,需要使用者对算法具有极强的信任,坚定认为得到的策略在未来数据上的表现也会很好。
第二种思路是仍将历史数据划分为训练集和测试集,但可以适度减小测试集的比例。提出这种思路,是考虑到使用者可能对算法没有十足的信心,需要观察训练得到的策略在测试集上的表现才决定是否有必要使用该策略。
在这次任务的要求下,这个策略更大可能是作为一个参考交易建议的提出者,而不是最后是否进行交易的决策者,因此本人建议、也使用的是第一种思路,让策略具有相对更强的普适性。
以上便是对Gym和强化学习概念的一些简要介绍。
基本实现思路
根据强化学习的原理和Gym的结构,需要我们决定的只有以下几个关键点:
状态空间的组成
起初,我将总收益也放进了状态空间,但之后意识到这样其实是没有必要的,因为总收益直接作总奖赏值显然更加合理,将其放入状态空间反而可能成为训练时的噪声(干扰因素)。
由此,状态空间内只需要有各个日期的百分位数,作为agent判断行为的依据即可。
随之而来的是一个新的问题:状态空间内应该有过去多少天内的数据(记为num_ref)、与当日的数据进行对比作为参考依据?由于num_ref直接决定了环境状态空间的大小,且将num_ref作为模型参数在训练过程中更新可能会由于偶然性等因素导致模型失去可靠性,因此在此处还是将num_ref设置为一个超参数,提供了一个接口,可以在环境外、开始训练之前自由设定。
动作空间的组成?如何设置每一种动作的奖赏值?
显然,动作空间里只会有三种动作:买,卖和什么都不做。
“买”操作的奖赏值的设置其实比较令人纠结。如果将当此买入的价格作为“买”操作的reward,则该reward很有可能是负数,可能导致模型会有避免进行买操作的“心理”;为了避免出现上述现象,在此将买操作的reward设置为0。
另一个将买操作的reward设置为0的原因,是在查看训练的loss曲线后得到的结论。
“卖”操作的奖赏值自然是当此卖出得到的收益/亏损。
什么都不做的奖赏值自然是0。
使用什么样的算法?算法中使用什么策略网络?
stable_base line3库中包含了许多强化学习的算法,常用的有DQN、PPO等。不同的算法针对不同的情况效果各有千秋,也是需要不断尝试。当然也可以自己研究、实现一些别的算法,但由于本人能力有限,因此就直接调用stable_base lin3中的算法了。这里使用的是DQN算法(深度Q-learning)。
算法中的策略网络也就是神经网络。到这里,我们就可以发现强化学习实际上还是通过使用神经网络使得模型具有学习能力的。常用的神经网络有全连接神经网络、卷积神经网络等。当数据的特征(如图片等数据集合)不能直接获得、需要进行处理时,适合使用卷积神经网络(CnnPolicy)。当数据特征可以直接提取、并且根据特征可以直接计算值函数时,适合使用全连接神经网络。这里使用的便是全连接神经网络(MlpPolicy)。
与训练相关的一些超参数
与策略网络相关
model = DQN( "MlpPolicy", env=env, learning_rate=1e-3, batch_size=128, buffer_size=500000, learning_starts=0, train_freq=max_line-1-num_ref, # train model frequency target_update_interval=15, # update network interval policy_kwargs={"net_arch": [128, 128, 128]}, # net kwargs verbose=0, tensorboard_log='./tensorboard/MyEnv-v0/' )
其中需要重点关注的是:
train_freq:训练模型的频率,单位是timesteps(每隔train_freq个step对模型进行一次训练)。
learning_rate:学习率,可以认为是用来衡量每次学习对模型影响程度大小的变量。可以是一个确定的值,也可以是一个剩余学习次数与总学习次数的函数。
target_update_interval:更新神经网络的间隔。
policy_kwargs:神经网络的参数,具体指神经网络的层数和每一层的神经元个数(上面代码使用的是一个3层、每层128个神经元的全连接神经网络)。
与训练相关
model.learn(total_timesteps=1000*(max_line-1-num_ref))
total_timesteps:执行step的次数,在这里由于对整个表格遍历一次才算完成一次训练,因此后面要乘上每一次训练的行数。
运行结果
运行结果总结:
由loss曲线可知,模型的学习程度比较可观。
但由总收益曲线可知,学习得到的策略收益并不稳定,虽然最大总收益不错,达到了4000以上,但也有不少次总亏损在2000以上,并且还有相当一部分时候总收益/亏损在0左右。总的来说,目前学习得到的策略的收益情况并没有达到预期。
另一方面,观察方差曲线可知,大部分情况下,方差大于10,也就是说训练得到的策略不仅收益没有保障、还有很大的风险。
总而言之,尽管这确实是一个通过学习得到的策略,但无论是收益还是风险都不尽如人意,还需要进行调参,以期训练出更优秀的策略。
[1] 这一变量今后称作σ。