股票量化交易軟件:組合趨勢和盤整策略

有多種多樣的交易策略,它們中的一些要尋找趨勢,而其它的一些會(huì)定義價(jià)格波動(dòng)的范圍而在其中進(jìn)行交易。市場是動(dòng)蕩的,趨勢之后永遠(yuǎn)是盤整,這對跟隨趨勢的交易者和在范圍內(nèi)低買高賣的人來說都有獲利的機(jī)會(huì)。當(dāng)兩組中的一組人獲利的時(shí)候,另一組或者在虧損或者在等待時(shí)機(jī)。
有沒有可能把這兩種方法組合到一起來增加獲利呢?這兩種策略能否相互補(bǔ)充呢?讓赫茲股票量化試試把這看起來不同的交易模型組合起來,看看這樣的組合有什么結(jié)果。
1. 組合策略的原則
從價(jià)格圖表上可以看到不斷變化的趨勢,大的變化后通常是盤整的階段,這時(shí)價(jià)格會(huì)開始在一個(gè)狹窄的范圍內(nèi)變化。交易者通常根據(jù)當(dāng)前市場的條件來選擇他們的交易策略,但是赫茲股票量化怎樣才能確定這個(gè)時(shí)候應(yīng)該選擇哪個(gè)策略呢?是趨勢策略還是盤整策略呢?

編輯切換為居中
有一些文章 [1] 和 [2] 是探討在不同的趨勢和盤整階段的交易策略的,很容易就會(huì)發(fā)現(xiàn),在評估市場條件后可以使用某種策略,這兩種策略類型都使用了不同的趨勢指標(biāo)來確定市場的狀態(tài),只是,當(dāng)在市場上有趨勢時(shí)使用趨勢策略入場,當(dāng)市場平靜時(shí)使用盤整策略建倉。因而,赫茲股票量化的第一種把兩種策略組合到一個(gè) EA 交易中的方法就是: 如果有趨勢,就使用跟隨趨勢的算法,如果沒有趨勢,就使用盤整算法。
在更加詳細(xì)地檢查了價(jià)格圖表之后,赫茲股票量化可以看到,不論趨勢還是盤整,價(jià)格的變化都是沒有方向性的,所有的變化都伴隨著價(jià)格的波動(dòng)。如果是盤整時(shí)期的變化,它們有一個(gè)很近的范圍,而在有趨勢時(shí),有些變化會(huì)超過其它。這種特性可以在組合趨勢和盤整策略的時(shí)候使用,思路是跟隨一個(gè)趨勢,盡管入場點(diǎn)應(yīng)當(dāng)是使用盤整交易的振蕩指標(biāo)來確認(rèn)。這種方法有助于捕捉修正的結(jié)束,而減少回撤并增加價(jià)格向期望方向變化的潛在可能。
2. 開發(fā) EA 交易
為了演示組合策略的原則,我已經(jīng)從文章[1]中的策略1和文章[2]中的策略6,這兩個(gè)選定的策略都是使用 ADX 指標(biāo)來判斷趨勢的。EA 的優(yōu)化是預(yù)先在從 01.01.2017 到 8.01.2018 的時(shí)間段進(jìn)行的。根據(jù)這些策略的優(yōu)化結(jié)果,選擇了下面的參數(shù)。
趨勢策略 1.

編輯切換為居中
盤整策略 6.

編輯切換為居中
在屏幕截圖中提供了單個(gè) EA 在優(yōu)化參數(shù)后的交易結(jié)果。
趨勢策略 1.

編輯切換為居中

編輯切換為居中
盤整策略 6.

編輯切換為居中

編輯切換為居中
這兩個(gè) EA 都是根據(jù)指標(biāo)信號(hào),在信號(hào)出現(xiàn)時(shí)沒有開啟的倉位,就會(huì)開啟訂單。根據(jù)預(yù)先定義的獲利和止損值關(guān)閉倉位。
這種方法可以把倉位跟蹤模塊排除在外,而大幅度地簡化了 EA 的邏輯。當(dāng)組合 EA 時(shí),我將會(huì)保持 EA 的運(yùn)行邏輯不變,來演示組合方法(而不是改變 EA 的邏輯)是如何影響結(jié)果的。
2.1. 方法一
第一種方法是按順序檢查兩種策略的信號(hào),而當(dāng)它們中的任意一個(gè)出現(xiàn)時(shí)就開啟倉位。每個(gè)策略都有它自己的指標(biāo)參數(shù),以及止損和獲利水平。使用這種方法,如果有一種策略開啟的倉位會(huì)阻止另一個(gè)策略開啟倉位,所以,在市場上永遠(yuǎn)最多只有一個(gè)開啟的倉位,這樣可以減少風(fēng)險(xiǎn)。
這種方法的缺點(diǎn)是可能會(huì)喪失獲利交易的機(jī)會(huì),這在一個(gè)策略有信號(hào)而存在另一個(gè)策略所開啟的倉位時(shí)可能會(huì)出現(xiàn)。但是,根據(jù)這種方法,所應(yīng)用的策略應(yīng)當(dāng)在不同的市場階段來交易,也就意味著這個(gè)缺點(diǎn)造成的影響應(yīng)當(dāng)比較小。
為了實(shí)現(xiàn)這個(gè)方法,把兩個(gè) EA 的代碼復(fù)制到一個(gè)文件中,根據(jù)相同的函數(shù)來把它們組合在一起,為了防止名稱的重復(fù),在跟隨趨勢策略的函數(shù)中加上"Trend"變量,而在盤整策略的函數(shù)中加入"Flat"類的變量。
//--- 公用參數(shù) input double ? ? ? ? ? ? ? Inp_Lot=0.01; ? ? ? ? ? ? ? ? ? ? ? ? ?//手?jǐn)?shù) input MarginMode ? ? ? ? ? Inp_MMode=LOT; ? ? ? ? ? ? ? ? ? ? ? ? //資金管理 input int ? ? ? ? ? ? ? ? ?Inp_MagicNum=1111; ? ? ? ? ? ? ? ? ? ? //幻數(shù) input int ? ? ? ? ? ? ? ? ?Inp_Deviation = 2; ? ? ? ? ? ? ? ? ? ? //偏差(點(diǎn)數(shù)) //--- input string ? ? ? ? ? ? ? Trend_EaComment="Trend Strategy"; ? ? ?//策略的注釋 input int ? ? ? ? ? ? ? ? ?Trend_StopLoss=25; ? ? ? ? ? ? ? ? ? ? //止損(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Trend_TakeProfit=90; ? ? ? ? ? ? ? ? ? //獲利(點(diǎn)數(shù)) //--- RSI_Color 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Trend_RSIPeriod=28; ? ? ? ? ? ? ? ? ? ?//RSI 周期數(shù) input double ? ? ? ? ? ? ? Trend_Overbuying=70; ? ? ? ? ? ? ? ? ? //超買區(qū)域 input double ? ? ? ? ? ? ? Trend_Overselling=30; ? ? ? ? ? ? ? ? ?//超賣區(qū)域 //--- ADX_Cloud 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Trend_ADXPeriod=11; ? ? ? ? ? ? ? ? ? ?//ADX 周期數(shù) input double ? ? ? ? ? ? ? Trend_alpha1 = 0.25; ? ? ? ? ? ? ? ? ? //alpha1 input double ? ? ? ? ? ? ? Trend_alpha2 = 0.25; ? ? ? ? ? ? ? ? ? //alpha2 //--- input string ? ? ? ? ? ? ? Flat_EaComment="Flat Strategy"; ? ? ? ?//策略注釋 input int ? ? ? ? ? ? ? ? ?Flat_StopLoss=50; ? ? ? ? ? ? ? ? ? ? ?//止損(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Flat_TakeProfit=50; ? ? ? ? ? ? ? ? ? ?//獲利(點(diǎn)數(shù)) //--- WPR 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Flat_WPRPeriod=7; ? ? ? ? ? ? ? ? ? ? ?//WPR 周期數(shù) //--- ADX 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Flat_ADXPeriod=11; ? ? ? ? ? ? ? ? ? ? //ADX 周期數(shù) input int ? ? ? ? ? ? ? ? ?Flat_FlatLevel=40; ? ? ? ? ? ? ? ? ? ? //ADX 平盤水平
在 OnTick 函數(shù)的開始, 檢查是否有開啟的倉位。如果沒有開啟的倉位,就更新指標(biāo)數(shù)據(jù)并按順序檢查趨勢和盤整策略的入場信號(hào)。如果有任何信號(hào)出現(xiàn),就根據(jù)對應(yīng)的策略開啟一個(gè)倉位。
void OnTick() ?{ //--- 檢查由 EA 在早前開啟的倉位 ? if(!Trade.IsOpenedBySymbol(_Symbol,Inp_MagicNum)) ? ? { ? ? ?//--- 取得用于計(jì)算的數(shù)據(jù) ? ? ?if(!GetIndValue()) ? ? ? ? return; ? ? ?//--- 根據(jù)趨勢算法開啟訂單 ? ? ?//--- 如果有買入信號(hào),開啟訂單 ? ? ?if(TrendBuySignal()) ? ? ? ? Trade.BuyPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Inp_MagicNum,Trend_EaComment); ? ? ?else ? ? ?//--- 如果有賣出信號(hào),開啟訂單 ? ? ?if(TrendSellSignal()) ? ? ? ? Trade.SellPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Inp_MagicNum,Trend_EaComment); ? ? ?else ? ? ?//--- 根據(jù)盤整算法開啟訂單 ? ? ?//--- 如果有買入信號(hào),開啟訂單 ? ? ?if(FlatBuySignal()) ? ? ? ? Trade.BuyPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Inp_MagicNum,Flat_EaComment); ? ? ?else ? ? ?//--- 如果有賣出信號(hào),開啟訂單 ? ? ?if(FlatSellSignal()) ? ? ? ? Trade.SellPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Inp_MagicNum,Flat_EaComment); ? ? } ?}
完整的 EA 代碼在附件中 (Combination1 項(xiàng)目)。
2.2. 方法二
第二種方法的組合過程稍微復(fù)雜一些,除了第一種方法之外,還創(chuàng)建了兩種策略相結(jié)合的信號(hào)。
在提供的趨勢策略實(shí)例中,使用 ADX 云指標(biāo)來定義趨勢,這個(gè)指標(biāo)顯示了在 DI+ 和 DI- 線之間的差距,而沒有檢驗(yàn)趨勢的強(qiáng)弱。同時(shí),盤整策略在開啟倉位之前會(huì)使用 ADX 閾值來檢驗(yàn)趨勢的強(qiáng)弱,這樣,赫茲股票量化就能在交易中引入另一個(gè)過濾器,在趨勢策略之后根據(jù)趨勢的強(qiáng)弱來進(jìn)行交易。
bool TrendBuySignal() ?{ ? return(trend_adx[0]>trend_adx[1] && trend_rsi1[0]==1 && trend_rsi1[1]==1 && ?flat_adx[0]>=Flat_FlatLevel)?true:false; ?}
在趨勢策略中,交易是根據(jù) RSI 指標(biāo)排序的,這樣赫茲股票量化就能夠通過排除與 RSI 信號(hào)相反的方向開啟倉位來減少在盤整策略之后虧損交易的數(shù)量。
bool FlatBuySignal() ?{ ? return(flat_wpr[0]<-80 && flat_adx[0]<Flat_FlatLevel && trend_rsi2[0]!=1)?true:false; ?}
完整的 EA 代碼可以在附件中找到 (Combination2 項(xiàng)目)。
2.3. 方法三 第三個(gè)方法是用于鎖倉賬戶的,在單個(gè)EA中獨(dú)立使用兩種策略。每種策略的訂單都賦予了特定的幻數(shù),根據(jù)到來信號(hào)開啟倉位,不管是否有其他策略所開啟的倉位。 這種方法精確地模擬了在一個(gè)相同賬戶中使用兩個(gè) EA 的情況,同時(shí)保留了這種方法的所有優(yōu)點(diǎn)和缺點(diǎn),特別是因?yàn)闀?huì)根據(jù)不同的策略同時(shí)開啟兩個(gè)倉位,可能會(huì)增加風(fēng)險(xiǎn)。 //--- 公用參數(shù) input double ? ? ? ? ? ? ? Inp_Lot=0.01; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //手?jǐn)?shù) input MarginMode ? ? ? ? ? Inp_MMode=LOT; ? ? ? ? ? ? ? ? ? ? ? ? ? ?//資金管理 input int ? ? ? ? ? ? ? ? ?Inp_Deviation = 2; ? ? ? ? ? ? ? ? ? ? ? ?//偏差(點(diǎn)數(shù)) //--- input string ? ? ? ? ? ? ? Trend_EaComment="Trend Strategy"; ? ? ? ? //策略的注釋 input int ? ? ? ? ? ? ? ? ?Trend_StopLoss=25; ? ? ? ? ? ? ? ? ? ? ? ?//止損(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Trend_TakeProfit=90; ? ? ? ? ? ? ? ? ? ? ?//獲利(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Trend_MagicNum=1111; ? ? ? ? ? ? ? ? ? ? ?//幻數(shù) //--- RSI_Color 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Trend_RSIPeriod=28; ? ? ? ? ? ? ? ? ? ? ? //RSI 周期數(shù) input double ? ? ? ? ? ? ? Trend_Overbuying=70; ? ? ? ? ? ? ? ? ? ? ?//超買區(qū)域 input double ? ? ? ? ? ? ? Trend_Overselling=30; ? ? ? ? ? ? ? ? ? ? //超賣區(qū)域 //--- ADX_Cloud 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Trend_ADXPeriod=11; ? ? ? ? ? ? ? ? ? ? ? //ADX 周期數(shù) input double ? ? ? ? ? ? ? Trend_alpha1 = 0.25; ? ? ? ? ? ? ? ? ? ? ?//alpha1 input double ? ? ? ? ? ? ? Trend_alpha2 = 0.25; ? ? ? ? ? ? ? ? ? ? ?//alpha2 //--- input string ? ? ? ? ? ? ? Flat_EaComment="Flat Strategy"; ? ? ? ? ? //策略注釋 input int ? ? ? ? ? ? ? ? ?Flat_StopLoss=50; ? ? ? ? ? ? ? ? ? ? ? ? //止損(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Flat_TakeProfit=50; ? ? ? ? ? ? ? ? ? ? ? //獲利(點(diǎn)數(shù)) input int ? ? ? ? ? ? ? ? ?Flat_MagicNum=1112; ? ? ? ? ? ? ? ? ? ? ? //幻數(shù) //--- WPR 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Flat_WPRPeriod=7; ? ? ? ? ? ? ? ? ? ? ? ? //WPR 周期數(shù) //--- ADX 指標(biāo)參數(shù) input int ? ? ? ? ? ? ? ? ?Flat_ADXPeriod=11; ? ? ? ? ? ? ? ? ? ? ? ?//ADX 周期數(shù) input int ? ? ? ? ? ? ? ? ?Flat_FlatLevel=40; ? ? ? ? ? ? ? ? ? ? ? ?//ADX 平盤水平 在 OnTick 函數(shù)中, 獨(dú)立檢查由趨勢策略開啟的倉位的幻數(shù)和使用盤整策略開啟倉位的幻數(shù)。 void OnTick() ? { //--- 檢查之前由 EA 開啟的趨勢策略的訂單 if(!Trade.IsOpenedBySymbol(_Symbol,Trend_MagicNum)) ? ? ?{ ? ? ? //--- 取得用于計(jì)算的數(shù)據(jù) if(!GetIndValue()) ? ? ? ? ?return; ? ? ? //--- 如果有買入信號(hào),開啟訂單 if(TrendBuySignal()) ? ? ? ? ?Trade.BuyPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Trend_MagicNum,Trend_EaComment); ? ? ? else //--- 如果有賣出信號(hào),開啟訂單 if(TrendSellSignal()) ? ? ? ? ?Trade.SellPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Trend_MagicNum,Trend_EaComment); ? ? ?} //--- 檢查之前由EA 開啟的盤整策略的訂單 if(!Trade.IsOpenedBySymbol(_Symbol,Flat_MagicNum)) ? ? ?{ ? ? ? //--- 取得用于計(jì)算的數(shù)據(jù) if(!GetIndValue()) ? ? ? ? ?return; ? ? ? //--- 如果有買入信號(hào),開啟訂單 if(FlatBuySignal()) ? ? ? ? ?Trade.BuyPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Flat_MagicNum,Flat_EaComment); ? ? ? else //--- 如果有賣出信號(hào),開啟訂單 if(FlatSellSignal()) ? ? ? ? ?Trade.SellPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Flat_MagicNum,Flat_EaComment); ? ? ?} ? } 完整的 EA 代碼可以在附件中找到 (Combination3 項(xiàng)目).
3. 測試 EA 交易
在準(zhǔn)備了三個(gè)由不同的策略組合方法開發(fā)的 EA 之后,是時(shí)候來測試這些 EA 并比較結(jié)果了,為了保證結(jié)果的兼容性,測試要在不修改 EA 參數(shù)的情況下進(jìn)行。
3.1. 測試方法一
第一種測試顯示有利潤??偟睦麧櫤突謴?fù)系數(shù)比任何一個(gè)原來的 EA 都更高。與盤整策略相比,余額曲線看起來更平坦,而交易數(shù)量上升了,而相對余額和資金的回撤都減少了。同時(shí),獲利因子略有下降,而總的利潤比最初策略的總利潤也少一些。

編輯切換為居中

編輯切換為居中
3.2. 測試方法二
使用第二種方法與第一種方法相比可以增加更多的利潤,而交易的數(shù)量還保持同樣,盡管總的利潤還是比最初 EA 的利潤略少一些。相應(yīng)地,利潤的增長也增加恢復(fù)和利潤因子 (后者變得與盤整策略相等了), 以及獲利交易的比例。同時(shí),最大余額回撤也減少了。

編輯切換為居中

編輯切換為居中
3.3. 測試方法三
使用第三種方法可以增加總利潤,與初始 EA 的總利潤水平相同。利潤的增長是可能通過增加交易數(shù)量達(dá)到的,同時(shí),存款負(fù)載和最大余額回撤增加了。

編輯切換為居中

編輯切換為居中
4. 優(yōu)化策略
在前一部分測試的 EA 展示了在 EA 中組合策略的優(yōu)點(diǎn),所有這三種方法都顯示了和最初的策略相比利潤有所增加。但是我們不應(yīng)忘記,最初的策略是為測試的時(shí)間短做了優(yōu)化的,而在測試組合 EA 時(shí)我們使用了相同的初始參數(shù)。
但是,我們都意識(shí)到 EA 邏輯中的任何影響都需要另外修改它的參數(shù),讓我們嘗試使用最初的兩種組合策略的方法優(yōu)化 EA 來看看結(jié)果。
請記住,開發(fā) EA 的最終目的是在市場上賺錢,而不是在歷史數(shù)據(jù)中演示它們的功能。所以,我建議把測試的時(shí)間段分成兩個(gè)部分,之前,我們是在從 1.01.2017 到 8.01.2018 進(jìn)行測試的,現(xiàn)在,我建議在相同的時(shí)間段,即從 1.01.2017 到 6.01.2018 進(jìn)行優(yōu)化,而在剩余的時(shí)間段進(jìn)行一次前瞻測試。

編輯切換為居中
4.1. 優(yōu)化方法一
在選擇優(yōu)化參數(shù)的時(shí)候,請記住赫茲股票量化的每個(gè) EA 都包含兩個(gè)部分的策略,在這種情況下,每個(gè)策略都使用了兩個(gè)指標(biāo)來入場交易,但是我們不要忘記,兩個(gè)策略都使用 ADX 來判斷趨勢的強(qiáng)弱和方向,所以,EA 的邏輯使用了三個(gè)指標(biāo)來定義入場點(diǎn)。我建議優(yōu)化這三個(gè)指標(biāo)的周期數(shù),
ADX 指標(biāo)周期數(shù)的優(yōu)化顯示出,在指標(biāo)周期數(shù)從12到14的范圍有最大化的利潤和穩(wěn)定性。下面的圖片顯示了 EA 利潤與 ADX 和 RSI 在優(yōu)化時(shí)間段的周期數(shù)變化的相互關(guān)聯(lián)。