赫茲股票量化交易軟件:蒙特卡羅方法在強(qiáng)化學(xué)習(xí)中的應(yīng)用

前文的簡(jiǎn)要總結(jié)及算法改進(jìn)方法

在前面的文章中, 赫茲股票量化探討了隨機(jī)決策森林算法,提出了一種基于強(qiáng)化學(xué)習(xí)的簡(jiǎn)單自學(xué)習(xí)算法。 ? 概述了這種方法的以下主要優(yōu)點(diǎn):
易于開(kāi)發(fā)交易算法和高“學(xué)習(xí)”速度。強(qiáng)化學(xué)習(xí)(RL)可以很容易地融入到任何交易EA中,并加速其優(yōu)化。
同時(shí),這種方法有一個(gè)主要缺點(diǎn):
該算法容易過(guò)度優(yōu)化(過(guò)度擬合)。換句話說(shuō),它的特點(diǎn)是對(duì)結(jié)果分布未知的一般情況的泛化較弱。這意味著,它不是在尋找金融工具整個(gè)歷史時(shí)期的真正基本市場(chǎng)模式,而是根據(jù)當(dāng)前市場(chǎng)情況過(guò)度擬合,而全球模式仍在受訓(xùn)代理的“理解”的另一面。然而,遺傳優(yōu)化也有同樣的缺點(diǎn),并且在大量變量的情況下工作得更慢。
有兩種主要方法可以克服過(guò)度擬合:
功能工程, 或者構(gòu)造屬性。這種方法的主要目標(biāo)是選擇這樣的特征和一個(gè)目標(biāo)變量,以低誤差描述一般情況。換言之,目的是通過(guò)使用預(yù)測(cè)因子枚舉的統(tǒng)計(jì)和經(jīng)濟(jì)計(jì)量方法尋找可能的規(guī)律。在非平穩(wěn)市場(chǎng)中,這項(xiàng)任務(wù)相當(dāng)復(fù)雜,對(duì)于某些策略來(lái)說(shuō),是不可解決的。然而,赫茲股票量化應(yīng)該努力選擇最佳策略。
使用了正則化通過(guò)在應(yīng)用的算法級(jí)別進(jìn)行修正來(lái)粗糙化模型。在上一篇文章中,赫茲股票量化記得在RDF中,參數(shù)r是應(yīng)用于此。正則化允許在訓(xùn)練和測(cè)試樣本之間實(shí)現(xiàn)誤差平衡,從而提高模型對(duì)新數(shù)據(jù)的穩(wěn)定性(如果可能的話)。
強(qiáng)化學(xué)習(xí)的改進(jìn)方法
上述技術(shù)以原始方式包含在算法中。一方面,通過(guò)枚舉價(jià)格增量和選擇幾個(gè)最佳值來(lái)構(gòu)造屬性,另一方面,通過(guò)調(diào)整r參數(shù)來(lái)選擇新數(shù)據(jù)上分類(lèi)錯(cuò)誤最小的模型。
此外,還有一個(gè)同時(shí)創(chuàng)建多個(gè)RL代理的新機(jī)會(huì),您可以將不同的設(shè)置設(shè)置設(shè)置為,從理論上講,這將提高模型對(duì)新數(shù)據(jù)的穩(wěn)定性。模型枚舉是使用蒙特卡羅方法(隨機(jī)抽取標(biāo)簽)在優(yōu)化器中執(zhí)行的,而最佳模型則寫(xiě)入文件以供進(jìn)一步使用。
創(chuàng)建 CRLAgent 基類(lèi)
為了方便起見(jiàn),庫(kù)是基于OOP的,這使得它很容易連接到EA并聲明所需數(shù)量的RL代理。 在這里,我將描述一些類(lèi)字段,以便更深入地理解程序中的交互結(jié)構(gòu)。 //+------------------------------------------------------------------+ //|RL 代理的基類(lèi) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ class CRLAgent ? { public: ? ? ? ? ? ? ? ? ? ? ?CRLAgent(string,int,int,int,double, double); ? ? ? ? ? ? ? ? ? ? ~CRLAgent(void); ? ?static int ? ? ? ?agentIDs; ? ? void ? ? ? ? ? ? ?updatePolicy(double,double&[]); //在每次交易后更新學(xué)習(xí)者原則 void ? ? ? ? ? ? ?updateReward(); ? ? ? ? ? ? ? ? //在關(guān)閉一個(gè)交易后更新收益 double ? ? ? ? ? ?getTradeSignal(double&[]); ? ? ?//從訓(xùn)練好的代理或者隨機(jī)接收交易信號(hào) int ? ? ? ? ? ? ? trees; ? ?double ? ? ? ? ? ?r; ? ?int ? ? ? ? ? ? ? features; ? ?double ? ? ? ? ? ?rferrors[], lastrferrors[]; ? ?string ? ? ? ? ? ?Name; 前三種方法用于形成學(xué)習(xí)者(代理)的政策(策略),更新獎(jiǎng)勵(lì)并接收來(lái)自訓(xùn)練有素代理的交易信號(hào)。在第一篇文章中對(duì)它們進(jìn)行了詳細(xì)描述。
定義隨機(jī)森林設(shè)置的輔助字段、屬性數(shù)(輸入)、存儲(chǔ)模型錯(cuò)誤的數(shù)組和代理(代理組)名稱(chēng)將在上進(jìn)一步聲明。
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; ?};
進(jìn)一步闡述了參數(shù)化學(xué)習(xí)策略、隨機(jī)森林對(duì)象和存儲(chǔ)錯(cuò)誤的輔助對(duì)象的保存矩陣。 ?
提供以下靜態(tài)變量用于存儲(chǔ)代理的唯一ID:
static int CRLAgent::agentIDs=0;
構(gòu)造函數(shù)在開(kāi)始工作之前初始化所有變量:
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(); ?}
在最后,控制權(quán)委托給getRDFstructure()方法,執(zhí)行以下操作:
//+------------------------------------------------------------------+ //|載入學(xué)習(xí)過(guò)的代理 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ 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; ?}
如果啟動(dòng)了EA優(yōu)化,將檢查文件中是否存在在上一個(gè)優(yōu)化程序迭代期間記錄的錯(cuò)誤。在每次新的迭代中比較模型誤差,以便隨后選擇最小的迭代。
如果在測(cè)試模式下啟動(dòng)EA,則從文件中下載經(jīng)過(guò)培訓(xùn)的模型以供進(jìn)一步使用。此外,模型的最新錯(cuò)誤將被清除,并設(shè)置等于1的默認(rèn)值,以便新的優(yōu)化從零開(kāi)始。
在優(yōu)化器中進(jìn)行下一次運(yùn)行后,對(duì)學(xué)習(xí)者進(jìn)行如下培訓(xùn):
//+------------------------------------------------------------------+ //|一個(gè)代理的學(xué)習(xí) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ double CRLAgent::learnAnAgent(void) ?{ ? if(MQLInfoInteger(MQL_OPTIMIZATION)) { ? ? ?if(numberOfsamples>0) { ? ? ? ? RecursiveElimination();
控制權(quán)委托給指定的方法,用于連續(xù)選擇屬性,即價(jià)格增量。讓赫茲股票量化看它是如何工作的:
//+------------------------------------------------------------------+ //|矩陣輸入的遞歸特征消除 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| //+------------------------------------------------------------------+ CRLAgent::RecursiveElimination(void) { //特征轉(zhuǎn)換,使每?jī)蓚€(gè)特征以不同的滯后返回 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 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]); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//用增量填充矩陣(數(shù)組零索引價(jià)格除以BF移位的價(jià)格) ? ? ? ? ?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); //訓(xùn)練一個(gè)隨機(jī)森林,其中只使用選定的增量作為預(yù)測(cè)器 ? ? ? ? ? ? ?ArrayResize(bestFeatures,ArrayRange(bestFeatures,0)+1); ? ? ?bestFeatures[modelCounterInitial][0] = mRep.m_oobrelclserror; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保存 oob 集合上的錯(cuò)誤 ? ? ? ?bestFeatures[modelCounterInitial][1] = bf; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//保存增量'延遲' ? ? ?modelCounterInitial++; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ?ArraySort(bestFeatures); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//數(shù)組排序 (根據(jù)第0維), 這里也就是根據(jù)錯(cuò)誤 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); ?// 根據(jù)選定的最佳屬性訓(xùn)練隨機(jī)森林