量化交易軟件:經(jīng)驗(yàn)?zāi)B(tài)分解法介紹

簡介
赫茲量化在實(shí)踐中必須處理的所有真實(shí)過程都很復(fù)雜,作為一項(xiàng)原則,包含大量的分量。例如天氣。在分析降水圖時(shí),我們應(yīng)記住,它們表示各種各樣的過程的互動(dòng),例如季節(jié)變換、全球變暖/變冷過程、洋流變化、氣旋和反氣旋的動(dòng)態(tài)、排放到大氣中的二氧化碳的量、太陽活動(dòng)周期等,內(nèi)容不勝枚舉。
因此很難分析此類圖,因?yàn)槠浞至吭谙嗷プ饔脮r(shí)會(huì)遮擋我們要識(shí)別的規(guī)律或讓規(guī)律扭曲。這樣會(huì)讓人有理由出現(xiàn)將考慮的過程分解為單個(gè)分量并單獨(dú)分析每個(gè)分量的想法。分析單個(gè)分量并研究它們已經(jīng)為當(dāng)前過程做出的貢獻(xiàn)有助于我們更好地了解正在進(jìn)行的過程,并提高預(yù)測可靠性。
在討論有關(guān)交易的各種信息時(shí)也不例外,包括依據(jù)大量不同因素形成的貨幣報(bào)價(jià)。這是很自然地期待預(yù)先分解為單個(gè)分量能夠大大促進(jìn)它們的進(jìn)一步分析的原因。
術(shù)語“分解”在形式上指將一個(gè)復(fù)合過程或復(fù)合材料分解為單獨(dú)的組成部分。但是在與不同過程分析、信號(hào)分析、各種序列分析有關(guān)的很多領(lǐng)域中,此術(shù)語長期以來具有更為廣闊的含義,通常不是指分解為實(shí)際的初始組成部分,而是指分解為在形成初始數(shù)據(jù)時(shí)實(shí)際上并不存在的某些函數(shù)。這些函數(shù)是在數(shù)據(jù)分解過程中人工形成的,但是盡管它們是“人工”的,它們也能更加深入地分析數(shù)據(jù),有助于識(shí)別隱藏的形態(tài)。
在市場分析中使用的大量方法或明或暗都可歸于從分析過程中挑選某些分量的方法,即分解法。讓赫茲量化簡要地回顧一下這些方法。
1. 分解
在實(shí)踐中,有很多各種各樣的分解法可應(yīng)用到考慮的給定序列。這些方法可能有不同的基本數(shù)學(xué)或經(jīng)驗(yàn)方法,不同的復(fù)雜程度和不同的應(yīng)用領(lǐng)域。
例如,即使一個(gè)基本市場分析在一定程度上也可被視為一種分解法。此分析處理一組直接影響市場狀況的初始事件產(chǎn)生的影響。換言之,所分析的市場過程被暗中分解為若干組成該過程的事件。
以后將不觸及與基本分析有關(guān)的問題。赫茲量化假定有關(guān)過程的任何進(jìn)一步的信息都不可用;我們擁有的僅是表示給定過程的行為的一個(gè)序列。
可以用常見的方法將一個(gè)序列分解為幾個(gè)組成部分,以之說明最簡單的分解例子。例如,赫茲量化為任意貨幣對(duì)在圖表上標(biāo)繪移動(dòng)平均線 (MA)。然后從初始序列中減去生成的曲線。這樣一來,我們將得到初始序列的兩個(gè)組成部分,MA 曲線和殘數(shù)。相同的步驟,僅使用較長周期的移動(dòng)平均線,在應(yīng)用到獲得的殘數(shù)時(shí),將產(chǎn)生三個(gè)組成部分 - 兩條 MA 曲線和變換的殘數(shù)。如您所見,可以使用任何可用的方式安排分解過程。要點(diǎn)在于此類過程的結(jié)果的屬性。
在著名的分解和頻譜分析方法中,傅里葉變換特別值得在這里提及。傅里葉變換屬于使用固定諧波基函數(shù)的正交變換類。傅里葉變換結(jié)果可表示為初始過程分解為具有固定頻率和幅度的諧函數(shù)。注意,有兩點(diǎn)對(duì)我們特別重要。
第一點(diǎn),變換始終依據(jù)一個(gè)固定的、預(yù)先設(shè)定的正交函數(shù)基進(jìn)行。即變換基不取決于所變換的序列的性質(zhì)。
第二點(diǎn),生成的諧分量的幅度和頻率值是恒定的。即它們的值在整個(gè)初始序列中都保持不變。這意味著如果給定初始序列的性質(zhì)在所考慮的區(qū)間內(nèi)出現(xiàn)變化,則這種變化將不會(huì)在變換結(jié)果中反映出來。在此情況下,獲得的結(jié)果將僅反映過程的某個(gè)平均狀態(tài),因?yàn)榇俗儞Q依據(jù)初始數(shù)據(jù)的靜態(tài)假設(shè)。
為了避免與初始序列的非靜態(tài)性有關(guān)的約束,赫茲量化可以將傅里葉變換轉(zhuǎn)換為小波變換。小波變換,與傅里葉變換類似,以固定的函數(shù)基進(jìn)行分解。與傅里葉變換不同,此基是預(yù)設(shè)的,即應(yīng)選擇在變換中使用的小波。
此外,與傅里葉變換相比,從小波變換生成的每一個(gè)分量都有確定其隨時(shí)間而變換的比例和水平的參數(shù),這樣解決了與所分析的過程可能具有的非靜態(tài)性有關(guān)的問題。
傅里葉變換和小波變換都被廣泛認(rèn)可,因?yàn)槭褂贸浞纸⒌臄?shù)學(xué)技能和可用的有效實(shí)施算法。此外,兩種變換都似乎特別通用,能夠成功應(yīng)用于不同的領(lǐng)域。
但是出于實(shí)踐目的,最好使用不僅能夠處理非靜態(tài)過程,還能使用按初始數(shù)據(jù)確定的自適應(yīng)變換基的變換。此類變換確實(shí)存在,以下將對(duì)其進(jìn)行簡要介紹,從而說明本文的主題。
2. 經(jīng)驗(yàn)?zāi)B(tài)分解
經(jīng)驗(yàn)?zāi)B(tài)分解 (EMD) 作為 希爾伯特-黃變換 (HHT) 的基礎(chǔ)部分被提出來??梢赃@么說,希爾伯特-黃變換分為兩個(gè)階段進(jìn)行。首先,使用 EMD 算法獲得本質(zhì)模態(tài)函數(shù) (IMF)。
接著,在第二階段,通過對(duì)上一步獲得的結(jié)果應(yīng)用希爾伯特-黃變換得到初始序列的瞬時(shí)頻率譜。HHT 能夠獲得非線性和非靜態(tài)序列的瞬時(shí)頻率譜。之后,可以使用經(jīng)驗(yàn)?zāi)B(tài)分解處理這些序列。
然而,本文將不介紹使用希爾伯特變換標(biāo)繪瞬時(shí)頻率譜。赫茲量化將僅著重于 EMD 算法。
與前面提及的傅里葉變換和小波變換相比,EMD 將任何給定數(shù)據(jù)分解為本質(zhì)模態(tài)函數(shù) (IMF),這些函數(shù)在分析上未被設(shè)定,而是由所分析的序列單獨(dú)確定。在這種情況下,基函數(shù)從輸入數(shù)據(jù)自適應(yīng)地直接得出。從 EMD 生成的 IMF 應(yīng)滿足以下要求:
IMF 極值的數(shù)量(最大值和最小值的數(shù)量之和)與零穿越的數(shù)量必須相等或最多相差 1;
在 IMF 的任意點(diǎn),局部最大值定義的包絡(luò)線的平均值和局部最小值定義的包絡(luò)線的平均值應(yīng)等于零。
分解生成一系列的頻率分階 IMF 分量。每個(gè)后面的 IMF 包含比前面的 IMF 更小的頻率振蕩。盡管“頻率”這一術(shù)語在運(yùn)用到 IMF 時(shí)并不十分正確,但它可能最適合用于定義 IMF 的性質(zhì)。本質(zhì)在于盡管 IMF 是振蕩性質(zhì),但其幅度和頻率可以沿時(shí)間軸變化。
單獨(dú)依據(jù)描述對(duì) EMD 算法執(zhí)行結(jié)果進(jìn)行可視化非常困難,因此讓我們繼續(xù)其軟件實(shí)施,這樣讓我們有機(jī)會(huì)了解算法的特點(diǎn)。
3. EMD 算法
黃鍔 (Norden E. Huang)提出的算法以產(chǎn)生序列的局部最大值和最小值所定義的平滑包絡(luò)線,接著從初始序列減去這些包絡(luò)線的平均值為基礎(chǔ)。這要求識(shí)別所有局部極值,然后用三次樣條曲線進(jìn)一步將這些極值連接起來,以生成上下包絡(luò)線。
標(biāo)繪包絡(luò)線的過程如圖 1 所示:

編輯
圖 1. 描繪包絡(luò)線和它們的平均值
圖 1 用細(xì)藍(lán)線給出了所分析的序列。分別用紅色和藍(lán)色表示序列的最大值和最小值。用綠色給出包絡(luò)線。
依據(jù)兩條包絡(luò)線計(jì)算平均值,并在圖 1 中以虛線表示。從初始序列中進(jìn)一步減去這樣計(jì)算出來的平均值。
以上步驟生成所需經(jīng)驗(yàn)函數(shù)的首次逼近提取。為了獲得最終的 IMF,應(yīng)再次識(shí)別新的最大值和最小值并重復(fù)以上所有步驟。此次重復(fù)的過程稱為篩選。重復(fù)篩選過程,直到滿足某個(gè)給定的停止標(biāo)準(zhǔn)。篩選停止標(biāo)準(zhǔn)的選擇是影響最終分解結(jié)果的要點(diǎn)之一。我們將在遲些時(shí)候討論這個(gè)問題。
如果成功完成篩選過程,則我們將獲得第一個(gè) IMF??梢酝ㄟ^從原始信號(hào)減去先前提取的 IMF,再一次重復(fù)上述過程而獲得下一 IMF。這樣一直繼續(xù)到提取完所有 IMF 為止。篩選過程通常在殘數(shù)只包含不超過兩個(gè)極值時(shí)停止。
可以看到,描述的經(jīng)驗(yàn)?zāi)B(tài)分解過程并不是基于嚴(yán)格的數(shù)學(xué)計(jì)算,但是真正基于經(jīng)驗(yàn),正如其名。盡管黃鍔提出的以上算法簡單明了,仍然有幾點(diǎn)可被視為其弱點(diǎn)。
有關(guān)此主題的不同文章提供了對(duì)其弱點(diǎn)的詳細(xì)說明,以及對(duì)黃鍔的算法進(jìn)行現(xiàn)代改進(jìn)的方式。本文將不著重于對(duì)此方法進(jìn)行的可能現(xiàn)代改進(jìn),但是將簡單地說明創(chuàng)建其軟件實(shí)施的嘗試。以下簡單地介紹實(shí)施的特征。
4. CEMDecomp 類
實(shí)施 EMD 算法的 CEMDecomp 類是依據(jù)研究希爾伯特-黃變換和經(jīng)驗(yàn)?zāi)B(tài)分解的互聯(lián)網(wǎng)文章創(chuàng)建的。實(shí)施的算法在本質(zhì)上與黃鍔最初提出的算法非常類似,沒有包含任何重大修改。
以下是源代碼的一個(gè)片斷,可以在本文末尾的 CEMDecomp.mqh 文件中找到。
//------------------------------------------------------------------------------------ // The Empirical Mode Decomposition (EMD). //------------------------------------------------------------------------------------ class CEMDecomp:public CObject ?{ public: ?int ? ? N; ? ? ? ? ? ? ? ? // Input and output data size ?double ?Mean; ? ? ? ? ? ? ?// Mean of input data ?int ? ? nIMF; ? ? ? ? ? ? ?// IMF counter ?int ? ? MaxIMF; ? ? ? ? ? ?// Maximum number of IMF ?int ? ? MaxIter; ? ? ? ? ? // Maximum number of iterations ?int ? ? FixedIter; ? ? ? ? // 0-variable number of sifting iterations; ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 1-always ten sifting iterations. ?double ?IMFResult[]; ? ? ? // Result private: ?double ?X[]; ?double ?Imf[]; ?double ?XMax[]; ? ? ? ? ? ?// x of local maxima ?double ?YMax[]; ? ? ? ? ? ?// y of local maxima ?double ?XMin[]; ? ? ? ? ? ?// x of local minima ?double ?YMin[]; ? ? ? ? ? ?// y of local minima ?double ?EnvUpp[]; ? ? ? ? ?// Upper envelope ?double ?EnvLow[]; ? ? ? ? ?// Lower envelope ?double ?Eps; ? ? ? ? ? ? ? // Accuracy comparison of floating-point numbers ?double ?Tol; ? ? ? ? ? ? ? // Accuracy of calculation IMF public: ? ?void ? ?CEMDecomp(void); ?int ? ? Decomp(double &y[]); ? ? ? ? ?// Decomposition ?void ? ?GetIMF(double &x[], int nn); ?// Get IMF number nn private: ?int ? ? arrayprepare(void); ?void ? ?extrema(double &y[],int &nmax,double &xmax[],double &ymax[], int &nmin,double &xmin[],double &ymin[]); ?int ? ? SplineInterp(double &x[],double &y[],int n,double &x2[], double &y2[],int btype=0); ?};
讓我們看一看在 CEMDecomp 類中聲明的公共變量和方法。
N 是序列中元素的數(shù)量。變量 N 的值在調(diào)用 Decomp() 方法之后生成,等于輸入序列的長度。提取的 IMF 將具有相同的大小。
Mean 是輸入序列的平均值。值在調(diào)用 Decomp() 方法之后生成。
nIMF 是 IMF 計(jì)數(shù)器。在調(diào)用 Decomp() 之后,它包含提取的 IMF 的數(shù)量加 2。因此,這個(gè)值指出使用 GetIMF() 方法可以讀取多少分量。這就是說,索引為 0 的分量將始終包含從中減去其平均值的初始序列,索引為 nIMF 的分量將包含分解的殘數(shù)。
MaxIMF 是 IMF 的最大允許數(shù)量。當(dāng) IMF 的數(shù)量達(dá)到 MaxIMF 值時(shí),輸入序列分解為單個(gè)的 IMF 將停止。此變量的值可在調(diào)用 Decomp() 方法之前設(shè)置。默認(rèn)值為 16。
MaxIter 是在篩選過程中允許的最大迭代次數(shù)。如果篩選過程的迭代次數(shù)達(dá)到此值,則不管是否獲得需要的精確度,篩選都會(huì)停止。此變量的值可在調(diào)用 Decomp() 方法之前設(shè)置。默認(rèn)值為 2000。
FixedIter 是一個(gè)標(biāo)記,在篩選中設(shè)置一個(gè)停止標(biāo)準(zhǔn)。如果 FixedIter 的值為零,則在達(dá)到給定精確度時(shí),每個(gè) IMF 的篩選過程就會(huì)停止。對(duì)不同 IMF 的提取而言,實(shí)現(xiàn)給定精確度所需的迭代次數(shù)可能有所不同。如果 FixedIter 設(shè)置為 1,則 IMF 會(huì)在 10 次迭代內(nèi)被提取出來。此變量的值可在調(diào)用 Decomp() 方法之前設(shè)置。默認(rèn)值為 0。
Decomp(double &y[]) 是主要的類方法,執(zhí)行分解。它以輸入?yún)?shù)的形式接收到一個(gè)包含輸入數(shù)據(jù)的數(shù)組的引用 。在成功完成時(shí),變量 N 將等于輸入數(shù)組的長度。提取的 IMF 將具有相同的大小。變量 Mean 將等于輸入序列的平均值,變量 nIMF 將等于可用 GetIMF() 方法讀取的分量的數(shù)量。
GetIMF(double &x[], int nn) 用于確保訪問用 Decomp() 方法獲得的結(jié)果。用 nn 設(shè)定數(shù)量的分量,這些分量會(huì)被復(fù)制到數(shù)組,而數(shù)組的地址會(huì)作為一個(gè)輸入?yún)?shù)傳遞。這就是說,索引為 0 的分量將始終包含從中減去其平均值的初始序列,索引為 nIMF 的分量將包含分解的殘數(shù)。如果作為參數(shù)傳遞的數(shù)組長度小于生成的分量的長度,則會(huì)按數(shù)組長度允許的情況填充數(shù)組。
可以用以下例子來說明 CEMDecomp 類的使用:
#include "CEMDecomp.mqh" //------------------------------------------------------------------------------------ // Script program start function //------------------------------------------------------------------------------------ void OnStart() ?{ ?int n,ret; ?double yy[],imf2[]; ? ?n=400; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// Input sequence length ?ArrayResize(yy,n); ? ? ? ? ? ? ? ? ? ? ? ? // Array of input data ?ArrayResize(imf2,n); ? ? ? ? ? ? ? ? ? ? ? // Array for reading the results ? ?CopyOpen(_Symbol,PERIOD_CURRENT,0,n,yy); ? ? ?// Generation of input data ? ?CEMDecomp *emd=new CEMDecomp(); ? ? ? ? ? // Creation of the CEMDecomp class instance ?ret=emd.Decomp(yy); ? ? ? ? ? ? ? ? ? ? ? // Decomposition of the input sequence ? ?if((ret==0)&&(emd.nIMF>3)) ? ? ? ? ? ? ? ?// If there is no error and the sufficient ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// number of components was extracted, ? ?emd.GetIMF(imf2,2); ? ? ? ? ? ? ? ? ? ? // copy component number 2 into ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// array imf2[]. ?delete(emd); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// Deletion of the CEMDecomp class instance ? ?// One of the extracted components in array imf2[]. ?} //------------------------------------------------------------------------------------
可以在本文末尾的 CEMDecomposition.zip 壓縮文件中找到通過 Web 界面顯示提取的 IMF 的完整分解例子。為了運(yùn)行這個(gè)例子,應(yīng)解壓縮指定的壓縮文件,并將整個(gè) \CEMDecomposition 目錄及其內(nèi)容放在客戶端的 \Indicators 或 \Scripts 目錄內(nèi)。之后,您可以編譯并運(yùn)行 EMDecomp_Test.mq5 腳本。請(qǐng)記住,應(yīng)允許在客戶端中使用外部庫。
圖 2 顯示另一個(gè)例子,使用 USDJPY 每日?qǐng)?bào)價(jià)的分解,序列長度為 100 個(gè)元素??梢钥吹?,此序列的分解生成四個(gè) IMF 提取和殘數(shù)。