MQL4課程-移動止損和保平止損

在趨勢交易中,移動止損和保平止損是一個特別有用的功能,它能幫我們及時地鎖住利潤,避免價格突然反方向運行造成的巨大虧損,同時能夠幫我們克制一下人性的弱點

第七節移動止損和保平止損

在趨勢交易中,移動止損和保平止損是一個特別有用的功能,它能幫我們及時地鎖住利潤,避免價格突然反方向運行造成的巨大虧損,同時能夠幫我們克制一下人性的弱點。那如何用MQL4來實現這些功能呢,下面我們來寫一下。

1移動止損

移動止損用到的函數還是OrderModify()函數,為了方便我們看到移動止損的效果,這次採用EA來編寫,同時介紹一下EA的回測功能。我們新建一個EA,把其他函數都刪掉,只留下頭函數和OnTick()函數,接下來在OnTick函數里面編寫。

我們規定在25EMA上穿60EMA時,我們做多0.1手,初始止損設置在入場對應的K線以及前兩根K線的最低價,移動止損設置在布林帶的下軌,如果移動止損超過了當前的止損價那麼就把止損設置為移動止損。

我們一步一步來,首先我們寫出當25EMA上穿60EMA時開倉做多,初始止損設置在入場K線以及前兩根K線的最低價。這裡我們要介紹一下用於提取均線數值的函數,這個函數是iMA()函數,打開幫助文件查一下,我們可以看到要查找MA的數值需要輸入7個參數:

第一個參數是品種名稱;

第二個參數是時間框架,比如要提取1h圖的MA數值那就輸入60;

第三個參數是指標的周期;

第四個參數是偏移量,如果輸入1,則MA線往前偏移1根K線,什麼意思呢,比如說在沒有偏移的情況下前1根K線對應的數值是2,那麼偏移為1時,2就變成了當前K線對應的數值了。

第五個參數是MA的計算方法,有EMA、SMA、SMMA、LWMA四種,關於均線以及其他指標的計算在此不細講,感興趣的同學可以去看一下考夫曼寫的《交易系統與方法》,本課只專注於實際的應用。

第六個參數是計算所使用的價格,可以用收盤價計算均線數值,也可以用開盤價、最高價、最低價等,總共有七種價格,可以查幫助文件,一般來說我們都用收盤價計算。

第七個參數是查詢的K線的編號,如果查詢當前K線對應的均線數值那就是0。

好,有了查詢MA數值用的iMA函數,我們就可以寫出一些均線的策略邏輯了,實現以上功能的代碼如下:

 void OnTick() { int i; string sym= Symbol(); double lot=0.1; int ticket; int huadian=10; int peri= PERIOD_CURRENT; int mag=1333; for(i=OrdersTotal()-1;i>=0;i--) { if(OrderSelect(i,SELECT_BY_POS)) { if(OrderSymbol()==sym && OrderType()==OP_BUY && OrderMagicNumber ()==mag) { return; } } } double sl= iLow(sym,peri,0); sl= MathMin(sl, iLow(sym,peri,1)); sl= MathMin(sl, iLow(sym,peri,2)); if(iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,1)> iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,1) && iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,2)< iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,2)) { ticket= OrderSend(sym,OP_BUY,lot, MarketInfo(sym, MODE_ASK), huadian,sl,0,”Lesson 7”,mag,0,clrRed); } } 


整個程序我把它分成了三部分,第一部分是控制一次只能開一個單子,如果當前持有倉位,那麼就不做任何事情,第二部分是初始止損的計算,用到了MathMin函數來,這個函數返回的是兩個值的最小值。

最後一部分是最關鍵的策略邏輯部分,如果25EMA上穿了60EMA,那麼也就是說前一根K線25EMA>60EMA,再前一根K線25EMA<60EMA,這個時候我們開一個多單。

接下來我們用MT4的回測工具驗證以下程序是否正確,我們打開MT4後在上方的“顯示”這一欄中可以找到EA交易測試的選項,如下兩個截圖:



關於EA參數的優化我們現在暫時用不到,把優化的勾去掉,測試品種、週期、時間範圍、測試的EA都調整好後我們就可以開始測試了。以上EA的測試結果如下圖:



可以看到在畫紅框的位置25EMA上穿了60EMA,在後一根K線的開盤時我們入場了一個多單,止損設置在當前K線以及前兩根K線的最低點處。雖然後面被打掉了止損,但是可以看到我們的程序是有效的。

接下來我們需要深化一下,把移動止損給加上去,我們只需要將第一部分的程序修改一下即可,將布林帶下軌的價格和訂單的止損比較一下,如果布林帶下軌的價格大於訂單的止損,那麼修改訂單的止損到布林帶的下軌。現在最關鍵的是我們要查詢布林帶的數值。和均線的查詢類似,布林帶也有內置的函數,它就是iBand()函數。使用這個函數我們需要輸入8個參數,參數意義分別為:

第一個參數是品種名稱;

第二個參數是時間框架;

第三個參數是指標的周期;

第四個參數是偏離的標準差,如果是2那偏離2倍的標準差。

第五個參數是偏移量,參考MA。

第六個參數是計算所使用的價格,同MA。

第七個參數是需要查詢的內容,如果想要查詢上軌的數值,那麼就是MODE_UPPER或者輸入1,如果要查詢中軌就輸入MODE_MAIN或者輸入0,如果要查詢下軌那麼輸入MODE_LOWER或者輸入2。

於是我們可以輕易地完成移動止損的操作,代碼如下:

 void OnTick() { int i; string sym= Symbol(); double lot=0.1; int ticket; int huadian=10; int peri= PERIOD_CURRENT; int mag=1333; int check; double bandlow=iBands(sym,peri,20,2,0,PRICE_CLOSE,2,1); for(i=OrdersTotal()-1;i>=0;i--) { if(OrderSelect(i,SELECT_BY_POS)) { if(OrderSymbol()==sym && OrderType()==OP_BUY && OrderMagicNumber ()==mag) { if(bandlow>OrderStopLoss()) { check= OrderModify(OrderTicket(),OrderOpenPrice(), bandlow,OrderTakeProfit(),0,clrRed); } return; } } } ………. 


以上的省略號省略後面不變的部分。我們用這款EA再測試以下看移動止損是否有效,測試結果如下:



從第一張圖看,當前K線的布林帶下軌已經高於了止損位置了,那麼按照EA的邏輯,下一K線開盤的時候,止損會被移動到布林帶下軌的位置,於是我們等待下一根K線的開盤。

從第二張圖可以看到,K線開盤後,止損便移動到了上一根K線的布林帶下軌處,因此我們的移動止損發揮了作用。

但是我們往回看,發現有的時候一根K線裡面會開兩次倉,如下圖所示。



由於EA不止在K盤的時候可以進場,其他時間只要沒有訂單也可以進場,這樣的話在波動比較劇烈時會開很多次倉,造成嚴重虧損。所以我們要控製程序只在開盤的時候運行一次,其他時間不運行。要實現這個功能也是非常簡單,我們只要數K線的根數就行了,如果新增了一根K線那說明有K線開盤了,程序如下:

於是我們可以輕易地完成移動止損的操作,代碼如下:

 int bar=0; void OnTick() { int i; string sym= Symbol(); double lot=0.1; int ticket; int huadian=10; int peri= PERIOD_CURRENT; int mag=1333; if(bar==Bars) { return; } bar= Bars; ………. 



可以看到這回的結果是正確的,這一根K線只在開盤的時候開了一個訂單。

2保平止損

當盈利達到一定程度後,我們就要將止損設置到成本位置來確保不會由於行情的回調而造成虧損,這個在趨勢行情中是非常有用的。

為了實現這個功能,我們就要規定盈利達到多少我們便調整止損到保平,這裡暫時定為當K線的收盤價高於訂單的開盤價10個點時做保平止損。

代碼如下:


 ……….. for(i=OrdersTotal()-1;i>=0;i--) { if(OrderSelect(i,SELECT_BY_POS)) { if(OrderSymbol()==sym && OrderType()==OP_BUY && OrderMagicNumber ()==mag) { if(bandlow>OrderStopLoss()) { check= OrderModify(OrderTicket(),OrderOpenPrice(), bandlow,OrderTakeProfit(),0,clrRed); } if(iClose(sym,peri,1)> OrderOpenPrice()+ 10*(MarketInfo(sym,MODE_POINT)*10) && bandlow< OrderOpenPrice()) { check= OrderModify(OrderTicket(),OrderOpenPrice(), OrderOpenPrice(),OrderTakeProfit(),0,clrRed); } return; } } } ………. 


之所以要在判斷保平條件時加上bandlow< OrderOpenPrice()這一句是為了避免保平止損和移動止損的衝突導致止損一直是保平止損。再回測試一下效果:



可以看出我們的移動止損發揮了作用,當價格收盤在開盤價以上10個點時將止損拉到了保平的位置。

以上我們就實現了移動止損和保平的功能,完整的代碼如下:


 int bar=0; void OnTick() { int i; string sym= Symbol(); double lot=0.1; int ticket; int huadian=10; int peri= PERIOD_CURRENT; int mag=1333; int check; double bandlow=iBands(sym,peri,20,2,0,PRICE_CLOSE,2,1); if(bar==Bars) { return; } bar= Bars; for(i=OrdersTotal()-1;i>=0;i--) { if(OrderSelect(i,SELECT_BY_POS)) { if(OrderSymbol()==sym && OrderType()==OP_BUY && OrderMagicNumber ()==mag) { if(bandlow>OrderStopLoss()) { check= OrderModify(OrderTicket(),OrderOpenPrice(), bandlow,OrderTakeProfit(),0,clrRed); } if(iClose(sym,peri,1)> OrderOpenPrice()+ 10*(MarketInfo(sym,MODE_POINT)*10) && bandlow< OrderOpenPrice()) { check= OrderModify(OrderTicket(),OrderOpenPrice(), OrderOpenPrice(),OrderTakeProfit(),0,clrRed); } return; } } } double sl= iLow(sym,peri,0); sl= MathMin(sl, iLow(sym,peri,1)); sl= MathMin(sl, iLow(sym,peri,2)); if(iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,1)> iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,1) && iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,2)< iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,2)) { ticket= OrderSend(sym,OP_BUY,lot, MarketInfo(sym, MODE_ASK), huadian,sl,0,”Lesson 7”,mag,0,clrRed); } } 


以上就是本節課程的內容,這節課我們完成了移動止損和保平止損的功能,在以後的EA編寫中這兩個功能將會經常用到,同時這兩個功能對交易結果的提升是有著很大的幫助的,在後面的課我們就開始我們第一個簡單的雙均線EA的編寫。


更多內容請關注公眾號【火象】~

分享至:

作者:火象趣交易

本文為PANews入駐專欄作者的觀點,不代表PANews立場,不承擔法律責任。

文章及觀點也不構成投資意見

圖片來源:火象趣交易如有侵權,請聯絡作者刪除。

關注PANews官方賬號,一起穿越牛熊
推薦閱讀
2021-11-01 06:59
2021-11-01 06:57
2021-11-01 06:53
2021-11-01 06:31
2021-11-01 06:27
2021-11-01 06:21

熱門文章

行業要聞
市場熱點
精選讀物

精選專題

App内阅读