回測跟自動交易程式進場有bug

  •   212 
  • 最後發表   bigjohnsonlai  2023 三月 30
bigjohnsonlai 發文於   2023/03/28

 

if GetSymbolInfo("買賣現沖")=false or GetSymbolInfo("處置股")=true then raiseruntimeerror("不可當沖");

 

 

///變數定義

variable:flag(0),_low(0),_low2(0),barcount(0),flag1bar(0),flag2bar(0),flag3bar(0),flag4bar(0),flag1count(0),flag4count(0),flag5count(0)

,flag6count(0),_sellcount(0),_low11(0),_lowperiod2(0),_periodhigh2(0),_period2(0),flag7count(0),_highperiodtime(0),_highperiodtime2(0),

recordhigh(0),arecord(0),alow(0),condition3_(0),AAA(0),barcount1(0),M(0),_sellprice(0),_switch(0),positioncount(0),

volumeflag1(0),flag1highvolumebar(0),i(0),tv(0),tp(0),close2(0),_high2(0),_true(0),highcount(0),volhigh(0),vollowprice(0),volhigh2(0),_period(0),_periodhigh(0),_lowperiod(0);

VARiable:INTRaBarPersist flagnum(0),_high(0);

 

//////////////////////////////////////////////////////////////////////////選股邏輯//////////////////////////////////////////////////////////////////////

 

 

///barcount 定義///

 

if date <> date[1] then ///參數定義

begin

barcount=1;

end

else

barcount+=1;

 

////////////////////////////////////////////////////////判斷價位區間

if c>10 and c<20  then _switch=10;

if c>20 and c<30  then _switch=20;

if c>30 and c<40  then _switch=30;

if c>40 and c<50  then _switch=40;

if c>50 and c<60  then _switch=50;

if c>60 and c<70  then _switch=60;

if c>70 and c<80  then _switch=70;

if c>80 and c<90  then _switch=80;

if c>90 and c<100 then _switch=90;

if c>100          then _switch=100;

 

///下單張數

positioncount=Round(300/c,0);

 

 

//////////////////////////////////////////////////////////////////////////////////進場條件////////////////////////////////////////////////////////////

//////////////////////////////

if c>_avgprice and GetField("成交量", "D")[1]>500 and _estvolume99>4

then begin

setposition(1);

end;

 

 

print(file("C:\print\"),date,barcount,position,c,_avgprice,GetField("成交量", "D")[1],_estvolume99);

 

 


以上為程式碼,以下為print出來的結果

可以看到其中一項進場條件為_estvolume99>4才進場,可是print出來看只有0.6多 

卻觸發進場,今天盤中開起來自動交易模擬有進場 回測結果也是如此

請問小幫手這個情況該怎麼解決?

date,                   barcount,       position,  c,              _avgprice  ,   GetField("成交量", "D")[1],        _estvolume99

20230328.000000 143.000000    0.000000   40.250000  39.772378    48104.000000                            0.642940 

20230328.000000 143.000000    1.000000   40.200000  39.773384    48104.000000                            0.648012 

20230328.000000 144.000000    1.000000   40.150000  39.774456    48104.000000                            0.648552 

 

排序方式: 標準 | 最新
XQ小幫手 發文於   2023/03/29

 Hello bigjohnsonlai,

 

要麻煩您提供 完整的交易腳本、回測的設定 (回測報告或截圖皆可)、交易的商品和日期時間來測試看問題為何。

您可以直接將檔案上傳,也可以Mail至客服信箱 XQservice@XQ.com.tw 且務必附上 討論文章連結網址(小幫手才能盡早處理)。

感謝。

bigjohnsonlai 發文於   2023/03/29

小幫手你好 附上交易程式碼,其中_avgprice _estvolume99都是函數 我附在後面

回測設定我附上截圖

再麻煩了

 

//////////////////////////////////////////////////////////////////////////////////回測設定

//////////////////////////////////////////////////////////////////////////////////交易腳本

 

if c>_avgprice and _estvolume99>4

then begin

setposition(1);

end;

 

 ///////////////////////////////////////////_avgprice函數腳本////////////////////////////////

 

var:i(0),tv(0),tp(0);

///均價程式///

i=0;

if date<>date[1]

   then begin

   value1=0;

   value2=0;

end;

 

if volume>0

   then begin

   while getfield("時間","1")[i]>=time and getfielddate("成交量","1")[i]=date

   i+=1;

while i>0

begin

i-=1;

tv=getfield("成交量","1")[i];

tp=(getfield("收盤價","1")[i]+getfield("開盤價","1")[i])/2;

value1+=tv;//成交量累加

value2+=(tv*tp);//成交值累加

end;

   end;

   if value1<>0 then 

value3=value2/value1;//均價

 

_avgprice=value3;//均價

 

 

 

bigjohnsonlai 發文於   2023/03/29

 

 

///////////////////////////////////////////_estvolume99函數腳本////////////////////////////////

 

 

//

// 參數: 統計天期(N)

// 繪製: 當日估計成交量

//

// 支援任何頻率(分鐘/日)

//

// 計算方式: 依照過去N日, 每日1分鐘累計成交均量(統計天期平均), 算出每分鐘累計成交量的分佈比例, 

// 然後依照目前的累計日成交量以及分佈比例, 推算當日收盤估計成交量

//

variable: barcount(0);

if date <> date[1] then 

begin

barcount=1;

end

else

barcount+=1;

 

 

variable: BARPERDAY(270); // 1分鐘bar每一天270筆

 

array: arr_minvolume[](0); // (過去N日)每日每分鐘累計: 共length * 270筆

array: arr_minvolume_percent[270](0); // (平均)每分鐘累計成交量比例: 共270筆

array: arr_avg_minvolume[270](0); // (平均)每分鐘累計成交量: 共270筆

 

variable: _i(0), _j(0), _k(0);

variable: _totaldays(0);

variable: _lastdate(0);

 

Array_SetMaxIndex(arr_minvolume, 5* 270);

 

 

 

if _lastdate = 0 then begin

// 跳過第一個不滿一天的資料

if barfreq = "Min" then

_lastdate = date

else begin

// 日線的話則從20190101才開始算

if date >= 20190101 then

_lastdate = date;

end; 

end;

 

if _lastdate <> 0 and date <> _lastdate then begin

_lastdate = date;

_totaldays = _totaldays + 1;

if _totaldays >= 5 then begin

// 計算過去N天的成交量分佈

//

// 因為我可能跑在不同頻率上, 所以要先算出過去N日'1分鐘'資料的起點跟終點

//

variable: _start(0), _end(0), _startdate(0), _accvolume(0);

 

_end = 1;

while getfield("time", "1")[_end] <> 132900 begin

_end = _end + 1;

end;

 

_start = _end + BARPERDAY * 5 - 1;

 

// _start = 統計日期第一日第一筆1分鐘資料的位置

// _end = 統計日期最後一日最後一筆1分鐘資料的位置

//

 

// arr_minvolume[]: 儲存過去N天, 每一分鐘的日累積成交量

// arr_minvolume[1] = 09:00, 

// arr_minvolume[2] = 09:01

// arr_minvolume[271] = 第二天09:00

// ..

_startdate = getfield("date", "1")[_start];

_accvolume = 0;

for _i = _start downto _end begin

if _startdate <> getfield("date", "1")[_i] then begin

// 換日

_accvolume = 0;

_startdate = getfield("date", "1")[_i];

end;

_accvolume += getfield("volume", "1")[_i];

arr_minvolume[_start - _i + 1] = _accvolume; // 當日累積volume

end;

 

// arr_avg_minvolume[]: 每一分鐘的日平均累積成交量

//

for _j = 1 to BARPERDAY begin

arr_avg_minvolume[_j] = 0;

for _i = 1 to 5 begin

arr_avg_minvolume[_j] += arr_minvolume[_j + (_i - 1) * BARPERDAY];

end; 

end;

for _j = 1 to BARPERDAY begin

arr_avg_minvolume[_j] = arr_avg_minvolume[_j] / 5;

end;

 

// arr_minvolume_percent[]: 每一分鐘的日平均累積成交量%

//

for _j = 1 to BARPERDAY begin

arr_minvolume_percent[_j] = arr_avg_minvolume[_j] / arr_avg_minvolume[BARPERDAY];

end;

 

{

print(text(

"main-date=", numtostr(date, 0), ",",

"main-time=", numtostr(time, 0), ",",

"start=", numtostr(_start, 0), ",",

"end=", numtostr(_end, 0), ",",

"startdate=", numtostr(getfield("date", "1")[_start], 0), ",", numtostr(getfield("time", "1")[_start], 0), ",",

"enddate=", numtostr(getfield("date", "1")[_end], 0), ",", numtostr(getfield("time", "1")[_end], 0), ","

));

 

for _i = 1 to 270 begin

print(text(

numtostr(_i, 0), "=", 

numtostr(arr_minvolume_percent[_i] * 100, 2))); 

end; 

}

end;

end;

 

if _totaldays >= 5 then begin

// 如果已經有分佈資料了, 則計算估計成交量

//

variable: _estvolume(0);

variable: _timeindex(0);

variable: _time(0), _v(0),_estvolume77(0);

 

// 算出目前時間應該是1~270的哪一筆

// 分鐘線的話就用bar的時間

// 日線的話, 如果是歷史日線, 就用收盤時間估算, 如果是最後一天(盤中日線), 用目前時間估算

 

 

////////

 

{

if barfreq = "Min" then

_time = time

else begin

if date < currentdate then

_time = 132900

else 

_time = currenttime;

end;}

{

_timeindex = floor(timediff(_time, 090000, "M")) + 1;

_timeindex = minlist(_timeindex, 270);

_timeindex = maxlist(1, _timeindex);}

 

// 預估量 = 累計到目前的日成交量 / 這個時間點之前所佔的日成交量%

//

 

if arr_minvolume_percent[barcount] > 0 then

_estvolume = GetField("volume", "D") / arr_minvolume_percent[barcount]

else

_estvolume = 0;

end;

 

_estvolume99=_estvolume/GetField("成交量", "D")[1];

bigjohnsonlai 發文於   2023/03/29

回測結果

 

XQ小幫手 發文於   2023/03/30

 Hello bigjohnsonlai,

 

if c>_avgprice and _estvolume99>4 這種寫法,會讓當c>_avgprice不符合時就不繼續執行 _estvolume99>4 的判斷。

但 _estvolume99 是個需要連續執行的函數,所以這種寫法會讓條件中 _estvolume99 計算出來的值出錯。

而您print的 _estvolume99 會是每次都執行的,故數值會和條件中的 _estvolume99 不同。

 

小幫手建議您可以將腳本修改為:

value1 = _estvolume99;

value2 = _avgprice;

 

if c>value2 and value1 > 4 then begin

setposition(1, market);

end;

 

確保_estvolume99每次都會執行,就不會出問題。

 

或是您也可以在 _estvolume99 函數腳本中最前面加上 SetBarMode(2);,強制該函數在執行到時會去補算之前沒有運算到的部分。

發表回覆
Close