編寫自動交易,可是用起來怪怪的

  •   882 
  • 最後發表   奇怪的人  2021 九月 07
奇怪的人 發文於   2021/08/17

var:plratio(0),InCondition(True),OutCondition(False);

if barfreq <> "MIN" and barinterval <> 1 then raiseruntimeerror("請使用1分鐘頻率");

//1分鐘價格上漲1%,且分鐘成交量大於100張

InCondition = (close / close[1]) > 1.01 and volume > 100 ;

 

//以買進價為基準,獲利3檔出場或虧損2檔出場

if position > 0 and filled > 0 and 

(high >= addspread(filledavgprice, 3) or low <= addspread(filledavgprice, 2))then setposition(0, market);

 

//如果價格大於進場價格+5檔或小於進場價格-5檔的話就出場

 

//中午1點20分強制平倉

 

if position <> 0 and filled <> 0 and currenttime >= 132000 then setposition(0, market);

 

 

 

我做的邏輯是

1分鐘價格上漲1%以上,且分鐘成交量大於100張買進入場

以建倉價為基準,獲利3檔出場或虧損2檔出場

且中午1點20分強制平倉

 

 

 

且買進賣出價的設定

希望是觸發出場的價位加上上圖框選出來的功能,觸發價格+-檔數限價出場

排序方式: 標準 | 最新
XQ小幫手 發文於   2021/08/19

Hello 奇怪的人,

 

您的腳本裡面有進場的條件,但卻沒有進場指令。

另外您可以參考 setposition 的說明,您的腳本使用market的話就會在市價成交。

如果不希望下市價單而是想使用自動交易的設定,請不要填寫market。

附上小幫手修改過後的腳本供您參考。

需注意雖然是以買進價為基準,獲利3檔出場或虧損2檔出場,但是實際成交價會在更有利的地方。

所以出場價不一定就是獲利3檔虧損2檔。

您可以參考print出來的資訊。

附加文件

奇怪的人 發文於   2021/08/19

感謝小幫手

我用上面附加文件導入執行回測

發現幾個問題

1.有時候會有買進後的下一秒立刻賣出,但卻也沒有碰到停利停損以及強制平倉時間

2.如下進場條件,但回測觀察會有部分沒篩出來

//1分鐘價格上漲1.5%,且分鐘成交量大於100張,當日漲幅小於8%
InCondition = (close / close[1]) > 1.015 and volume > 100 and currentTime < 132000 and price_change<8 ;

3.強制平倉沒有執行,同時停利停損也沒執行,回測後出現距離建倉價很遠的檔數才出場,或是隔了好幾天才出場

 

 

以上

我一個字一個字的對函數寫法

也找不出原因

 

我是運用小幫手的附件加上當日漲幅小於8%進場

var:plratio(0),InCondition(False),OutCondition(False);
var: price_change(0);
price_change = 100 * ((close - GetField("參考價", "D")) / GetField("參考價", "D"));

if barfreq <> "MIN" and barinterval <> 1 then raiseruntimeerror("請使用1分鐘頻率");

//1分鐘價格上漲1.5%,且分鐘成交量大於100張,當日漲幅小於8%
InCondition = (close / close[1]) > 1.015 and volume > 100 and currentTime < 132000 and price_change<8 ;
if position = 0 and filled = 0 and InCondition then setposition(1);

//以買進價為基準,獲利3檔出場或虧損2檔出場
if position > 0 and filled > 0 then begin
    if high >= addspread(filledavgprice, 3) then begin
        setposition(0, addspread(filledavgprice, 3), label:="獲利出場");
        print("獲利出場", date, time, filledavgprice,addspread(filledavgprice, 3));
        end 
    else if low <= addspread(filledavgprice, 2)then begin
        setposition(0, addspread(filledavgprice, -2), label:="虧損出場");
        print("虧損出場", date, time, filledavgprice, addspread(filledavgprice, -2));
        end;
    end;

//中午1點20分強制平倉
if position <> 0 and filled <> 0 and currenttime >= 132000 then setposition(0, market);

 

XQ小幫手 發文於   2021/08/20

Hello 奇怪的人,

 

1.

由於您腳本內使用 high >= addspread(filledavgprice, 3) 跟 low <= addspread(filledavgprice, 2),很有可能當跟Bar的高低點就觸發。

如果您是使用逐筆洗價的話,那麼當根Bar進出場的可能性挺大的。

您可以觀察print出來的資訊即可得知。

若您不希望發生這種狀況,建議您將停損停利設遠一點。

 

2, 3.

小幫手這邊測試幾檔商品沒有發生您敘述的情形。

麻煩您提供回測設定或回測報表,交易腳本並告知是什麼商品,什麼時候發生您說的狀況來讓小幫手檢查。

建議您可以先將運算的數字print出來看是否有問題。

奇怪的人 發文於   2021/08/21

進出場感覺有問題

進場(close / close[1]) > 1.015的條件回推來看

幾乎都沒有觸發就進場了

策略:4個TICK停利,-2個TICK停損

以下是我抓8/19周轉率前25名來8/20做的回測結果

正德 : 1個TICK就出場了

鑫科 : 完全沒有出場,不管是停利停損以及132000強制市價平倉都沒作動

晶宏 : 1個TICK就出場了
點序 : 正常出場

聚積 : 1個TICK就出場了

旺矽 : 1個TICK就出場了

大甲 : 正常出場

九豪 : 1個TICK就出場了

德微 : 1個TICK就出場了

聚和 : 1個TICK就出場了

美琪瑪 : 1個TICK就出場了

世禾 : 同價價出,進場點也未達到分鐘成交量>100

泰藝 : 1個TICK就出場了

 

 

var:plratio(0),InCondition(False),OutCondition(False);
var: price_change(0);
price_change = 100 * ((close - GetField("參考價", "D")) / GetField("參考價", "D"));

if barfreq <> "MIN" and barinterval <> 1 then raiseruntimeerror("請使用1分鐘頻率");

//1分鐘價格上漲1.5%,且分鐘成交量大於100張,當日漲幅小於8%
InCondition = (close / close[1]) > 1.015 and volume > 100 and currentTime < 132000 and currentTime > 090200 and price_change<8 ;
if position = 0 and filled = 0 and InCondition then setposition(1);

//以買進價為基準,獲利4檔出場或虧損2檔出場
if position > 0 and filled > 0 then begin 
    if high >= addspread(filledavgprice, 4) then begin
        setposition(0, addspread(filledavgprice, 4), label:="獲利出場");
        print("獲利出場", date, time, filledavgprice,addspread(filledavgprice, 4));
        end 
    else if low <= addspread(filledavgprice, -2)then begin
        setposition(0, addspread(filledavgprice, -2), label:="虧損出場");
        print("虧損出場", date, time, filledavgprice, addspread(filledavgprice, -2));
        end;
    end;

//中午1點20分強制平倉
if position <> 0 and filled <> 0 and currenttime >= 132000 then setposition(0, market);

 

 

---------------------------補充---------------------------

目前策略是觸碰進場\邏輯固定買進X張

我們有辦法調整為每次進場X萬元嗎?

就如同策略雷達下單量的設定

附加文件

XQ小幫手 發文於   2021/08/24

Hello 奇怪的人,

 

小幫手以正德、鑫科和世禾為範例說明。

需注意您是用1分鐘逐筆,所以1分鐘Bar會被切分成4個Tick來模擬。

小幫手將print的資訊修改為如下讓您比較好理解:

print("進場觸發", date, time, volume, close, close[1], close / close[1], 100 * ((close - GetField("參考價", "D")) / GetField("參考價", "D")));

print("獲利觸發", date, time, high, filledavgprice, addspread(filledavgprice, 3));

print("虧損觸發", date, time, low, filledavgprice, addspread(filledavgprice, -2));

 

以下是正德print出來的結果:

進場觸發 20210820.000000 90000.000000 181.000000 28.200000 27.350000 1.031079 3.107861 

獲利觸發 20210820.000000 90000.000000 28.650000 28.200000 28.350000 

進場觸發 20210820.000000 90000.000000 726.000000 28.500000 27.350000 1.042048 4.204753 

虧損觸發 20210820.000000 90100.000000 28.450000 28.550000 28.450000 

進場觸發 20210820.000000 90100.000000 261.000000 28.800000 28.500000 1.010526 5.301645 

獲利觸發 20210820.000000 90100.000000 28.800000 28.550000 28.700000 

進場觸發 20210820.000000 90200.000000 381.000000 29.000000 28.550000 1.015762 6.032907 

虧損觸發 20210820.000000 90200.000000 28.500000 28.900000 28.800000 

進場觸發 20210820.000000 91000.000000 186.000000 28.650000 28.350000 1.010582 4.753199 

虧損觸發 20210820.000000 91000.000000 28.300000 28.550000 28.450000 

進場觸發 20210820.000000 92700.000000 612.000000 29.100000 28.750000 1.012174 6.398537 

虧損觸發 20210820.000000 92700.000000 28.700000 29.100000 29.000000 

進場觸發 20210820.000000 93400.000000 291.000000 29.150000 28.850000 1.010399 6.581353 

虧損觸發 20210820.000000 93400.000000 28.850000 29.100000 29.000000 

可以看得出來,如果在當根1分鐘Bar的開盤價觸發進場的話,很多時候是在相同根Bar的最高價或最低價觸發限價賣出單。

如果您不希望當根就出場,請不要勾選逐筆洗價。

 

以下是鑫科print出來的結果:

進場觸發 20210820.000000 90000.000000 156.000000 38.950000 37.800000 1.030423 3.042328 

虧損觸發 20210820.000000 90000.000000 37.850000 38.950000 38.850000 

進場觸發 20210820.000000 90300.000000 132.000000 39.800000 39.150000 1.016603 5.291005 

虧損觸發 20210820.000000 90300.000000 39.000000 39.750000 39.650000  

鑫科在39.65掛了一張限價賣單,但當日價格沒有再上到39.65過所以未成交。

強制出場未觸發是因為當有兩個setposition符合的時候,只會優先執行上面的那一個。

小幫手想到的解決辦法是將 中午1點20分強制平倉 移到 以買進價為基準,獲利3檔出場或虧損2檔出場 上方,確保其會被優先執行。

並將其修改為:

if filled <> 0 and currenttime >= 132000 then setposition(0, market);

附上小幫手修改過的腳本。

 

以下是世禾print出來的結果:

進場觸發 20210820.000000 90000.000000 114.000000 63.800000 61.400000 1.039088 3.908795 

獲利觸發 20210820.000000 90000.000000 64.500000 63.900000 64.200000 

進場觸發 20210820.000000 115600.000000 114.000000 65.700000 64.700000 1.015456 7.003257 

虧損觸發 20210820.000000 115600.000000 64.900000 65.700000 65.500000 

該根觸發當下的成交量有超過100。

還有每個 close / close[1] 都有大於 1.01

 

至於您想用X萬元來換算成張數,可以在腳本內自行計算。

舉例來說10萬元好了:

value1 = floor(100000 / (close * 1000));

這樣就可以算出10萬元最多可以買幾張。

奇怪的人 發文於   2021/08/25

Q1

小幫手

我想要設定100塊以上以100萬內最大限度買進

100塊以下以50萬內最大限度買進

上面邏輯有弄出來回測也沒問題

if position = 0 and filled = 0 and InCondition and close > 100 then setposition(1000000/close/1000);
if position = 0 and filled = 0 and InCondition and close < 100 then setposition(500000/close/1000);

但是如果說我希望第二行小於100塊買進50萬想要連續下2次

也就是想要買到100萬,但是要分2單

這樣有辦法嗎?

 

 

-----------------------------補充-----------------------------

Q2

可以請小幫手幫我檢查看看嗎?

這是今天執行自動交易的圖片

 

重點在圖3

12:19:37.872  觸發執行正德(2641)進場

12:19:38.116  觸發執行正德(2641)退場

可是腳本退場設定是這麼寫的:

//中午1點20分強制平倉
if filled <> 0 and currenttime >= 132000 then setposition(0, market);


//以買進價為基準,獲利4檔出場或虧損2檔出場
if position > 0 and filled > 0 then begin 
    if high >= addspread(filledavgprice, 1) then begin
        setposition(0, addspread(filledavgprice, 1), label:="獲利出場");
        print("獲利出場", date, time, filledavgprice,addspread(filledavgprice, 1));
        end 
    else if low <= addspread(filledavgprice, -5)then begin
        setposition(0, addspread(filledavgprice, -5), label:="虧損出場");
        print("虧損出場", date, time, filledavgprice, addspread(filledavgprice, -5));
        end;
    end;

應該是以進場點為基準+1停利退場並-5停損退場

但是照執行下來看好像沒有照著執行

是哪邊有編寫錯誤嗎?

 

---------------------------------------------------------------------------------------------------------

 

Q3

還是以上面今天正德(2641)為例(2021/8/25)

它觸發進場後以33.5買進了14張

並在觸發33.55停利出場要掛單賣掉這14張

剛好觸碰到33.55為當時最高點指出掉部分8張

剩餘的6張繼續掛著委託33.55賣出但價格就往下掉下去了

要避免這種狀況

除了將觸發後市價賣出的發法外

有什麼方式可以解決嗎?

XQ小幫手 發文於   2021/08/27

Hello 奇怪的人,

 

1.

小幫手會建議您運用floor函數讓其化為整數。

至於您要2次進場的話,可以嘗試以下語法:

value1 = floor(500000/close/1000);  //一次進場口數

if position = 0 and filled = 0 and InCondition and close < 100 then setposition(value1)

else if position = value1 and filled = value1 and inCondition and close < 100 then setposition(value1 * 2);

這樣的話如果第一次進場成交後,進場條件還符合的話就會加碼。

 

2.

您只要去看當天 2021/08/25 12:19 那根1分鐘Bar就能理解了:

該根Bar開33.00、低也是33.00。

您觸發進場的價格是在 33.5 ,向下五檔的話就會是 33.5 - (0.05 * 5) = 33.25。

很明顯的當根最低價(開盤價)33.0就已經小於33.25了,自然就會觸發出場。

請注意您在腳本中用的是 low <= addspread(filledavgprice, -5) 跟 high >= addspread(filledavgprice, 1),不是用收盤價來判斷。

 

3.

若要確保成交,只能用市價出場。

限價單就是不能保證成交。

奇怪的人 發文於   2021/09/02

小幫手你好

目前邏輯為多單進場

如以下:

var:plratio(0),InCondition(False),OutCondition(False);
var: price_change(0);
price_change = 100 * ((close - GetField("參考價", "D")) / GetField("參考價", "D"));

value3 = GetBarOffset(date,090500);

if barfreq <> "Tick" and barinterval <> 1 then raiseruntimeerror("請使用1分鐘頻率");

//進場
InCondition =addspread(highD(0), -3)>=close[value3] and currentTime > 090500 and currentTime < 090530 and price_change < 8 ;
if position = 0 and filled = 0 and InCondition and close > 100 then setposition(1000000/close/1000);
if position = 0 and filled = 0 and InCondition and close < 100 then setposition(500000/close/1000);

//中午1點20分強制平倉
if filled <> 0 and currenttime >= 132000 then setposition(0, market);


//以買進價為基準,獲利3檔出場或虧損達到開盤價檔出場
if position > 0 and filled > 0 then begin 
    if high >= addspread(filledavgprice, 3) then begin
        setposition(0, addspread(filledavgprice, 3), label:="獲利出場");
        print("獲利出場", date, time, filledavgprice,addspread(filledavgprice, 3));
        end 
    else if low <= open then begin
        setposition(0, market, label:="虧損出場");
        print("虧損出場", date, time, filledavgprice, addspread(filledavgprice, -5));
        end;
    end;

 

那我要用相同邏輯反向做空

//進場
addspread(lowd(0), 3)<=close[value3] and currentTime > 090500 and currentTime < 090530 and price_change < 8 ;

我原本這份XS要怎麼改?

 

XQ小幫手 發文於   2021/09/07

Hello 奇怪的人,

 

您只需要將進場的部位數和獲利虧損調成相反即可。

需注意 CurrentTime 在回測時得到的數字和time相同,所以 CurrentTime > 090500 and CurrentTime < 090530 無法用在回測。

附上修改過的腳本供您參考。

附加文件

發表回覆
Close