2019年3月3日

分批進場與分批出場

先建立一個觀念:把加減碼訊號分出來開發成獨立策略,再統整成一個投資組合(各訊號是獨立運行下單),往往比把多個交易訊號通通塞在單一策略裡要好,理由是分開寫可以獨立評估績效與調整,此外,合在一起寫也易發生因為語法控制不當導致訊號互相壓抑或是其他訊號不符預期的狀況。不過,還是會有需求要針對單一策略寫一些簡單的加減碼機制,介紹如下。

更改「部位限制」設定值

在MultiCharts的預設值裡,交易訊號都是1口進1口出,所以如要達到分批進出,首先要去更改「部位限制」設定值,策略>屬性設定>部位限制,如下圖所示:

範例程式碼1:分批進場,一次出場(面進點出)

我們以一個簡單的長短均線交叉策略為例,獲利50點加碼1口,獲利100點加碼第2口,回檔破近5根K的最高或最低點,部位全部平倉。在這裡出場指令(Sell及BuytoCover)都沒有指定口數,會執行全部平倉。


========================================
input:len1(5),len2(20);
vars:ma1(0),ma2(0);
ma1=average(close,len1);
ma2=average(close,len2);

if marketposition<>1 and ma1 cross over ma2 then buy("LE") 1 contracts next bar at market;  
if marketposition=1 and  currentcontracts=1 then buy("LE+1") 1 contracts next bar at entryprice+50 stop;
if marketposition=1 and  currentcontracts=2 then buy("LE+2") 1 contracts next bar at entryprice+100 stop;
if marketposition=1 and currentcontracts>1 then Sell("L_Plus_out")  next bar at lowest(Low,5) stop;

if marketposition<>-1 and ma1 cross below ma2 then sellshort("SE") 1 contracts next bar at market;
if marketposition=-1 and  currentcontracts=1 then Sellshort("SE+1") 1 contracts next bar at entryprice-50 stop;
if marketposition=-1 and  currentcontracts=2 then Sellshort("SE+2") 1 contracts next bar at entryprice-100 stop;
if marketposition=-1 and currentcontracts>1 then buytocover("S_Plus_out") next bar at highest(High,5) stop;
========================================

其中「marketposition=1 and currentcontracts=1」 表示目前部位是1口多單在倉,「marketposition=1 and currentcontracts=2」則表示目前是2口多單在倉,這樣寫法可以協助較精確控制部位,如果加碼邏輯較複雜時可派上用場,但有個缺點,就是當遇到同一根K棒同時達到獲利50及100點(同時滿足兩個加碼單的條件),但第二個加碼單會在下一根K棒才進場。

範例程式碼2:分批進場,分批出場(面進面出)

承上例,不同的是出場當從高點或低點回檔30點,只把加碼部位出場,這邊要就要在平倉指令(Sell及BuytoCover)後面指定平倉口數,語法為:

Sell N Contracts Total

留意要加Total這個保留字,才能達到指定口數平倉(有沒有加「Total」差別請看附註)。此外,也有可能部分平倉後又立刻符合加碼條件,導致馬上加碼單又進場,這個就要另外靠程式碼去細部控制了


========================================
input:len1(5),len2(20);
vars:ma1(0),ma2(0);
ma1=average(close,len1);
ma2=average(close,len2);

if marketposition<>1 and ma1 cross over ma2 then buy("LE") 1 contracts next bar at market;  
if marketposition=1 and  currentcontracts=1 then buy("LE+1") 1 contracts next bar at entryprice+50 stop;
if marketposition=1 and  currentcontracts=2 then buy("LE+2") 1 contracts next bar at entryprice+100 stop;
if marketposition=1 and currentcontracts>1 then Sell("L_Plus_out") currentcontracts-1 contracts total next bar at lowest(Low,5) stop;

if marketposition<>-1 and ma1 cross below ma2 then sellshort("SE") 1 contracts next bar at market;
if marketposition=-1 and  currentcontracts=1 then Sellshort("SE+1") 1 contracts next bar at entryprice-50 stop;
if marketposition=-1 and  currentcontracts=2 then Sellshort("SE+2") 1 contracts next bar at entryprice-100 stop;
if marketposition=-1 and currentcontracts>1 then buytocover("S_Plus_out") currentcontracts-1 contracts  total next bar at highest(High,5) stop;
========================================

範例程式碼3:指定平倉

在MultiCharts中平倉順序是採先進先出,指定平倉可以無視進場訊平掉特定進場訊號的部位,例如我們指定平掉第2個加碼單,語法為:

Sell from Entry("LE+2")

其中” LE+2”就是對應第二次加碼進場訊號的名稱(也可以從MC的圖上面看進出訊號連接線來比對)。一樣,也有可能部分平倉後又立刻符合加碼條件,導致馬上加碼單又進場,這個就要另外靠程式碼去細部控制了


========================================
input:len1(5),len2(20);
vars:ma1(0),ma2(0);
ma1=average(close,len1);
ma2=average(close,len2);

if marketposition<>1 and ma1 cross over ma2 then buy("LE") 1 contracts next bar at market;  
if marketposition=1 and  currentcontracts=1 then buy("LE+1") 1 contracts next bar at entryprice+50 stop;
if marketposition=1 and  currentcontracts=2 then buy("LE+2") 1 contracts next bar at entryprice+100 stop;
if marketposition=1  then Sell("L_Plus_out") from entry("LE+2") next bar at lowest(Low,5) stop;

if marketposition<>-1 and ma1 cross below ma2 then sellshort("SE") 1 contracts next bar at market;
if marketposition=-1 and  currentcontracts=1 then Sellshort("SE+1") 1 contracts next bar at entryprice-50 stop;
if marketposition=-1 and  currentcontracts=2 then Sellshort("SE+2") 1 contracts next bar at entryprice-100 stop;
if marketposition=-1 then buytocover("S_Plus_out") from entry("SE+2") next bar at highest(High,5) stop;
========================================

結論

還是建議交易人把加減碼訊號分出來開發成獨立策略,再統整成一個投資組合(各訊號是獨立運行下單),如要把加減碼進出寫在同一訊號,務必檢查進出訊號是否符合預期,有沒有發生重複進出場的問題。




備註:

一般我們使用出場指令(Sell及BuytoCover)都不會特意去指定平倉口數,想當然爾會以為像下面這樣寫,就是平倉2口多單的意思:

Sell 2 Contracts  

其實是大誤,細讀官方sell語法解釋

Sell[("ExitLabel")] [From Entry("EntryLabel")] [TradeSize[Total]] Exit
其中對於TradeSize 的定義:By default, the number of contracts or shares specified by the TradeSize parameter will be sold from each one of the open long entries.

也就是寫Sell 2 Contracts是告訴程式每個進場訊號出2口。如果目前的持倉部位是來自同一個進場訊號那就沒有問題,但如果倉位是來自不同訊號,例如2個訊號,我們就會發現出場的口數會變成4口(如果倉位小於4就會全出),就跟我們想的不一樣。因此,正確寫法應該是:

Sell 2 Contracts Total


歡迎加入LINE@
加入好友
(點擊上方圖示)

1 則留言:

  1. 感謝版主這篇教學文,讓我縮短許多摸索時間

    回覆刪除

歡迎留言討論!