期貨量化交易軟件:按記錄過濾
簡(jiǎn)介
有不同的過濾器:指標(biāo)值、市場(chǎng)波動(dòng)性、時(shí)間和工作日。 它們?nèi)靠梢杂脕?lái)過濾虧損交易。 將過濾器添加至 Expert Advisor 非常容易——只要在開始程序塊之前另加一個(gè)條件即可。 但是,如果要使用 EA 記錄作為過濾器,應(yīng)如何做呢? 如果在數(shù)次不成功的交易后關(guān)閉交易系統(tǒng),則隨后不會(huì)生成記錄,因此沒有可以分析的內(nèi)容。 要解決這個(gè)問題,我們需要教會(huì) Expert Advisor 虛擬交易,即模擬開倉(cāng)、修改和平倉(cāng)而無(wú)需真實(shí)交易活動(dòng)。 這是本文要講述的內(nèi)容。

編輯切換為居中
試驗(yàn)策略
為了系統(tǒng)的實(shí)施,我們將在 Expert Advisor CrossMACD_DeLuxe.mq4 進(jìn)行一些改動(dòng):
在每個(gè)頭寸的開倉(cāng)/修改/平倉(cāng)點(diǎn),改動(dòng)將寫在虛擬頭寸的數(shù)組內(nèi);
添加虛擬頭寸的 StopLoss 和 TakeProfit 的啟動(dòng)跟蹤;
添加過濾標(biāo)準(zhǔn)——現(xiàn)實(shí)交易不會(huì)進(jìn)行的條件。
我將力圖詳盡的描述 EA 修改的每個(gè)步驟。 如果你不感興趣,可以下載現(xiàn)成的 Expert Advisor 并前往“游戲是否得不償失?”部分。
解釋虛擬頭寸
出現(xiàn)開倉(cāng)的信號(hào)。 計(jì)算 StopLoss 和 TakeProfit 參數(shù),完全做好調(diào)用 OrderSend() 函數(shù)的準(zhǔn)備。 我們正是在此刻開始虛擬交易——只要將所有必要參數(shù)保存在合適的變量: void OpenBuy() ? { ? ? int _GetLastError = 0; ? ? double _OpenPriceLevel, _StopLossLevel, _TakeProfitLevel; ? ? _OpenPriceLevel = NormalizeDouble(Ask, Digits); ? ? ? if(StopLoss > 0) ? ? ? ? _StopLossLevel = NormalizeDouble(_OpenPriceLevel - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? StopLoss*Point, Digits); ? ? ?else ? ? ? ? _StopLossLevel = 0.0; ? ? ?if(TakeProfit > 0) ? ? ? ? _TakeProfitLevel = NormalizeDouble(_OpenPriceLevel + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TakeProfit*Point, Digits); ? ? ?else ? ? ? ? _TakeProfitLevel = 0.0; ? ? ? ?//---- open the virtual position ? ? virtOrderSend(OP_BUY, _OpenPriceLevel, _StopLossLevel, ? ? ? ? ? ? ? ? ? ?_TakeProfitLevel); ? ? ? if(OrderSend(Symbol(), OP_BUY, 0.1, _OpenPriceLevel, 3, ? ? ? ? _StopLossLevel, _TakeProfitLevel, "CrossMACD", ? ? ? ? _MagicNumber, 0, Green) < 0) ? ? ? { ? ? ? ? _GetLastError = GetLastError(); ? ? ? ? Alert("Error OrderSend № ", _GetLastError); ? ? ? ? return(-1); ? ? ? } ? } ? //---- Save parameters of the opened position in main variables void virtualOrderSend(int type, double openprice, double stoploss, ? ? ? ? ? ? ? ? ? ? ? double takeprofit) ? { ? ? virtTicket = 1; ? ? virtType = type; ? ? virtOpenPrice = openprice; ? ? virtStopLoss = stoploss; ? ? virtTakeProfit = takeprofit; ? } 可以看到,我們只用了五個(gè)變量: int ? ? ? virtTicket ? ? = 0; ? ?// determines, if there is an open virtual position int ? ? ? virtType ? ? ? = 0; ? // position type double ? ?virtOpenPrice ?= 0.0; // position opening price double ? ?virtStopLoss ? = 0.0; // position StopLoss double ? ?virtTakeProfit = 0.0; // position TakeProfit
我們?nèi)蝿?wù)的完成并不需要其他特征。 如果要拓展該示例的功能性,僅需添加必要的變量。
為了追蹤平倉(cāng)和頭寸修改,我們需要更多操作。 復(fù)制 Expert Advisor 內(nèi)未平倉(cāng)頭寸控制的程序塊,并更改訂單特征為虛擬: int start() ? { ? ? // skipped... //+------------------------------------------------------------------+ //| Control block of "virtual" positions ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ if(virtTicket > 0) ? ? ? { ? ? ? ? //---- if BUY-position is open, if(virtType == OP_BUY) ? ? ? ? ? { ? ? ? ? ? ? //---- if MACD crossed 0-line downwards, if(NormalizeDouble(MACD_1 + CloseLuft*Point*0.1, ? ? ? ? ? ? ? ? Digits + 1) <= 0.0) ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? //---- close position ? ? ? ? ? ? ? ? virtOrderClose(Bid); ? ? ? ? ? ? ? } ? ? ? ? ? ? //---- if the signal did not change, accompany the position by ?// ? ? TrailingStop else ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? if(TrailingStop > 0) ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? if(NormalizeDouble(Bid - virtOpenPrice, ? ? ? ? ? ? ? ? ? ? ? ? Digits ) > 0.0) ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? if(NormalizeDouble( Bid - TrailingStop*Point - ? ? ? ? ? ? ? ? ? ? ? ? ? ? virtStopLoss, Digits) > 0.0 || virtStopLoss < Point) ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? virtStopLoss = Bid - TrailingStop*Point; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? ? //---- if SELL position is open if(virtType == OP_SELL) ? ? ? ? ? { ? ? ? ? ? ? //---- if MACD crossed 0-line upwards, if(NormalizeDouble(MACD_1 - CloseLuft*Point*0.1, ? ? ? ? ? ? ? ? Digits + 1 ) >= 0.0) ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? //---- close the position ? ? ? ? ? ? ? ? virtOrderClose(Ask); ? ? ? ? ? ? ? } ? ? ? ? ? ? //---- if the signal did not change, accompany the position by ?// ? ? TrailingStop else ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? if ( TrailingStop > 0 ) ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? if(NormalizeDouble( virtOpenPrice - Ask, ? ? ? ? ? ? ? ? ? ? ? ? Digits ) > 0.0 ) ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? if(NormalizeDouble( virtStopLoss - ( Ask + ? ? ? ? ? ? ? ? ? ? ? ? ? ? TrailingStop*Point ), Digits ) > 0.0 || ? ? ? ? ? ? ? ? ? ? ? ? ? ?virtStopLoss <= Point ) ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? virtStopLoss = Ask + TrailingStop*Point; ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? } ? ? // skipped... return(0); ? } ? ? ?//---- virtual position closing function void virtOrderClose(double closeprice) ? { ? ? //---- Save the parameters of the closed position in the array ArrayResize(virtClosedOrders, virtClosedOrdersCount + 1); ? ? ? virtClosedOrders[virtClosedOrdersCount][0] = virtType; ? ? virtClosedOrders[virtClosedOrdersCount][1] = virtOpenPrice; ? ? virtClosedOrders[virtClosedOrdersCount][2] = virtStopLoss; ? ? virtClosedOrders[virtClosedOrdersCount][3] = virtTakeProfit; ? ? virtClosedOrders[virtClosedOrdersCount][4] = closeprice; ? ? ? virtClosedOrdersCount ++; ? ? ? //---- clear variables ? ? virtTicket = 0; ? ? virtType = 0; ? ? virtOpenPrice = 0.0; ? ? virtStopLoss = 0.0; ? ? virtTakeProfit = 0.0; ? } 可以看到,修改變?yōu)楹?jiǎn)單的將新值分配給 virtStopLoss 變量。 平倉(cāng)非常困難——所有平倉(cāng)訂單的特征都保存在一個(gè)數(shù)組內(nèi)。 隨后整個(gè)虛擬記錄將保存在內(nèi)。 我們將從中提取平倉(cāng)頭寸的信息,用于進(jìn)行新開倉(cāng)的決策。