股票量化交易软件:蒙特卡罗方法在强化学习中的应用

本文讨论了在股票量化交易中,如何通过强化学习改进随机决策森林算法,以减少过度拟合问题,包括功能工程、正则化和创建多个RL代理的方法,以及CRLAgent类的实现和优化过程。
摘要由CSDN通过智能技术生成

前文的简要总结及算法改进方法

在前面的文章中, 赫兹股票量化探讨了随机决策森林算法,提出了一种基于强化学习的简单自学习算法。 概述了这种方法的以下主要优点:

  • 易于开发交易算法和高“学习”速度。强化学习(RL)可以很容易地融入到任何交易EA中,并加速其优化。

同时,这种方法有一个主要缺点:

  • 该算法容易过度优化(过度拟合)。换句话说,它的特点是对结果分布未知的一般情况的泛化较弱。这意味着,它不是在寻找金融工具整个历史时期的真正基本市场模式,而是根据当前市场情况过度拟合,而全球模式仍在受训代理的“理解”的另一面。然而,遗传优化也有同样的缺点,并且在大量变量的情况下工作得更慢。

有两种主要方法可以克服过度拟合:

  • 功能工程, 或者构造属性。这种方法的主要目标是选择这样的特征和一个目标变量,以低误差描述一般情况。换言之,目的是通过使用预测因子枚举的统计和经济计量方法寻找可能的规律。在非平稳市场中,这项任务相当复杂,对于某些策略来说,是不可解决的。然而,赫兹股票量化应该努力选择最佳策略。

  • 使用了正则化通过在应用的算法级别进行修正来粗糙化模型。在上一篇文章中,赫兹股票量化记得在RDF中,参数r是应用于此。正则化允许在训练和测试样本之间实现误差平衡,从而提高模型对新数据的稳定性(如果可能的话)。

强化学习的改进方法

上述技术以原始方式包含在算法中。一方面,通过枚举价格增量和选择几个最佳值来构造属性,另一方面,通过调整r参数来选择新数据上分类错误最小的模型。

此外,还有一个同时创建多个RL代理的新机会,您可以将不同的设置设置设置为,从理论上讲,这将提高模型对新数据的稳定性。模型枚举是使用蒙特卡罗方法(随机抽取标签)在优化器中执行的,而最佳模型则写入文件以供进一步使用。

创建 CRLAgent 基类

为了方便起见,库是基于OOP的,这使得它很容易连接到EA并声明所需数量的RL代理。 在这里,我将描述一些类字段,以便更深入地理解程序中的交互结构。 //+------------------------------------------------------------------+ //|RL 代理的基类 | //+------------------------------------------------------------------+ class CRLAgent { public: CRLAgent(string,int,int,int,double, double); ~CRLAgent(void); static int agentIDs; void updatePolicy(double,double&[]); //在每次交易后更新学习者原则 void updateReward(); //在关闭一个交易后更新收益 double getTradeSignal(double&[]); //从训练好的代理或者随机接收交易信号 int trees; double r; int features; double rferrors[], lastrferrors[]; string Name; 前三种方法用于形成学习者(代理)的政策(策略),更新奖励并接收来自训练有素代理的交易信号。在第一篇文章中对它们进行了详细描述。

定义随机森林设置的辅助字段、属性数(输入)、存储模型错误的数组和代理(代理组)名称将在上进一步声明。

 
 

private: CMatrixDouble RDFpolicyMatrix; CDecisionForest RDF; CDFReport RDF_report; double RFout[]; int RDFinfo; int agentID; int numberOfsamples; void getRDFstructure(); double getLastProfit(); int getLastOrderType(); void RecursiveElimination(); double bestFeatures[][2]; int bestfeatures_num; double prob_shift; bool random; };

进一步阐述了参数化学习策略、随机森林对象和存储错误的辅助对象的保存矩阵。

提供以下静态变量用于存储代理的唯一ID:

 
 

static int CRLAgent::agentIDs=0;

构造函数在开始工作之前初始化所有变量:

 
 

CRLAgent::CRLAgent(string AgentName,int number_of_features, int bestFeatures_number, int number_of_trees,double regularization, double shift_probability) { random=false; MathSrand(GetTickCount()); ArrayResize(rferrors,2); ArrayResize(lastrferrors,2); Name = AgentName; ArrayResize(RFout,2); trees = number_of_trees; r = regularization; features = number_of_features; bestfeatures_num = bestFeatures_number; prob_shift = shift_probability; if(bestfeatures_num>features) bestfeatures_num = features; ArrayResize(bestFeatures,1); numberOfsamples = 0; agentIDs++; agentID = agentIDs; getRDFstructure(); }

在最后,控制权委托给getRDFstructure()方法,执行以下操作:

 
 

//+------------------------------------------------------------------+ //|载入学习过的代理 | //+------------------------------------------------------------------+ CRLAgent::getRDFstructure(void) { string path=_Symbol+(string)_Period+Name+"\\"; if(MQLInfoInteger(MQL_OPTIMIZATION)) { if(FileIsExist(path+"RFlasterrors"+(string)agentID+".rl",FILE_COMMON)) { int getRDF; do { getRDF=FileOpen(path+"RFlasterrors"+(string)agentID+".rl",FILE_READ|FILE_BIN|FILE_ANSI|FILE_COMMON); FileReadArray(getRDF,lastrferrors,0); FileClose(getRDF); } while (getRDF<0); } else { int getRDF; do { getRDF=FileOpen(path+"RFlasterrors"+(string)agentID+".rl",FILE_WRITE|FILE_BIN|FILE_ANSI|FILE_COMMON); double arr[2]; ArrayInitialize(arr,1); FileWriteArray(getRDF,arr,0); FileClose(getRDF); } while (getRDF<0); } return; } if(FileIsExist(path+"RFmodel"+(string)agentID+".rl",FILE_COMMON)) { int getRDF=FileOpen(path+"RFmodel"+(string)agentID+".rl",FILE_READ|FILE_TXT|FILE_COMMON); CSerializer serialize; string RDFmodel=""; while(FileIsEnding(getRDF)==false) RDFmodel+=" "+FileReadString(getRDF); FileClose(getRDF); serialize.UStart_Str(RDFmodel); CDForest::DFUnserialize(serialize,RDF); serialize.Stop(); getRDF=FileOpen(path+"Kernel"+(string)agentID+".rl",FILE_READ|FILE_BIN|FILE_ANSI|FILE_COMMON); FileReadArray(getRDF,bestFeatures,0); FileClose(getRDF); getRDF=FileOpen(path+"RFerrors"+(string)agentID+".rl",FILE_READ|FILE_BIN|FILE_ANSI|FILE_COMMON); FileReadArray(getRDF,rferrors,0); FileClose(getRDF); getRDF=FileOpen(path+"RFlasterrors"+(string)agentID+".rl",FILE_WRITE|FILE_BIN|FILE_ANSI|FILE_COMMON); double arr[2]; ArrayInitialize(arr,1); FileWriteArray(getRDF,arr,0); FileClose(getRDF); } else random = true; }

如果启动了EA优化,将检查文件中是否存在在上一个优化程序迭代期间记录的错误。在每次新的迭代中比较模型误差,以便随后选择最小的迭代。

如果在测试模式下启动EA,则从文件中下载经过培训的模型以供进一步使用。此外,模型的最新错误将被清除,并设置等于1的默认值,以便新的优化从零开始。

在优化器中进行下一次运行后,对学习者进行如下培训:

 
 

//+------------------------------------------------------------------+ //|一个代理的学习 | //+------------------------------------------------------------------+ double CRLAgent::learnAnAgent(void) { if(MQLInfoInteger(MQL_OPTIMIZATION)) { if(numberOfsamples>0) { RecursiveElimination();

控制权委托给指定的方法,用于连续选择属性,即价格增量。让赫兹股票量化看它是如何工作的:

 
 

//+------------------------------------------------------------------+ //|矩阵输入的递归特征消除 | //+------------------------------------------------------------------+ CRLAgent::RecursiveElimination(void) { //特征转换,使每两个特征以不同的滞后返回 ArrayResize(bestFeatures,0); ArrayInitialize(bestFeatures,0); CDecisionForest mRDF; CMatrixDouble m; CDFReport mRep; m.Resize(RDFpolicyMatrix.Size(),3); int modelCounterInitial = 0; for(int bf=1;bf<features;bf++) { for(int i=0;i<RDFpolicyMatrix.Size();i++) { m[i].Set(0,RDFpolicyMatrix[i][0]/RDFpolicyMatrix[i][bf]); //用增量填充矩阵(数组零索引价格除以BF移位的价格) m[i].Set(1,RDFpolicyMatrix[i][features]); m[i].Set(2,RDFpolicyMatrix[i][features+1]); } CDForest::DFBuildRandomDecisionForest(m,RDFpolicyMatrix.Size(),1,2,trees,r,RDFinfo,mRDF,mRep); //训练一个随机森林,其中只使用选定的增量作为预测器 ArrayResize(bestFeatures,ArrayRange(bestFeatures,0)+1); bestFeatures[modelCounterInitial][0] = mRep.m_oobrelclserror; //保存 oob 集合上的错误 bestFeatures[modelCounterInitial][1] = bf; //保存增量'延迟' modelCounterInitial++; } ArraySort(bestFeatures); //数组排序 (根据第0维), 这里也就是根据错误 oob ArrayResize(bestFeatures,bestfeatures_num); // 只保留最佳的 bestfeatures_num 属性 m.Resize(RDFpolicyMatrix.Size(),2+ArrayRange(bestFeatures,0)); for(int i=0;i<RDFpolicyMatrix.Size();i++) { // 再次填充矩阵,但是这一次使用最佳属性 for(int l=0;l<ArrayRange(bestFeatures,0);l++) { m[i].Set(l,RDFpolicyMatrix[i][0]/RDFpolicyMatrix[i][(int)bestFeatures[l][1]]); } m[i].Set(ArrayRange(bestFeatures,0),RDFpolicyMatrix[i][features]); m[i].Set(ArrayRange(bestFeatures,0)+1,RDFpolicyMatrix[i][features+1]); } CDForest::DFBuildRandomDecisionForest(m,RDFpolicyMatrix.Size(),ArrayRange(bestFeatures,0),2,trees,r,RDFinfo,RDF,RDF_report); // 根据选定的最佳属性训练随机森林

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值