(等待回應) 為什麼回測警示腳本帶自訂數列函數的時候,會出現 "不合法的欄位資料",而把該自訂數列函數直接寫到警示腳本內卻不會出現?答案:回測需要使用if currentbar

  •   289 
  • 最後發表   Sadless  2020 十月 13
Sadless 發文於   2020/09/24

寫了一個數列函數 f_accumulated_volume_per_minute,用以計算每分鐘的累積成交量。

數列函數:f_accumulated_volume_per_minute 

//函數功能:計算該日每分鐘的累積成交量,功能與getfield("成交量","D") 類似
//但getfield("成交量","D") 無法取得前一天的每分鐘累積成交量,而這個函數可以

//宣告
SetBarMode(2);

variable:v_minute_bar_local_number_in_a_day(0);

//如果09:00:00是當日編號1號的分K棒,計算現在這根分K棒的當日編號,也就現在距離09:00:00幾分鐘
v_minute_bar_local_number_in_a_day 
= 1 + timediff(time,90000,"M");

//計算該日每分鐘的累積成交量
if  v_minute_bar_local_number_in_a_day > 0 
then begin 
    f_accumulated_volume_per_minute 
        = Summation(volume, v_minute_bar_local_number_in_a_day);
end

else  
    f_accumulated_volume_per_minute =0;

 

我寫了一個警示,要測試這個數列函數。

警示腳本:Test.accumulated_volume_1

//Test.accumulated_volume_1

settotalbar(2*4.5*60);

if f_accumulated_volume_per_minute[2*4.5*60] > getfield("成交量","D")[1]
then ret=1;

 

回測這個警示腳本 Test.accumulated_volume_1,會出現 "不合法的欄位資料"。

回測結果如下圖一:

 

 

可是,如果把自訂數列函數直接寫到警示腳本內,卻不會出現 "不合法的欄位資料"。

警示腳本:Test.accumulated_volume_2

//Test.accumulated_volume_2

settotalbar(2*4.5*60);
{
if f_accumulated_volume_per_minute[2*4.5*60] > getfield("成交量","D")[1]
then ret=1;
}



variable:v_minute_bar_local_number_in_a_day(0);
variable:v_accumulated_volume_per_minute(0);

//如果09:00:00是當日編號1號的分K棒,計算現在這根分K棒的當日編號,也就現在距離09:00:00幾分鐘
v_minute_bar_local_number_in_a_day 
    = 1 + timediff(time,90000,"M");

//計算該日每分鐘的累積成交量
if  v_minute_bar_local_number_in_a_day > 0 
then begin 
    v_accumulated_volume_per_minute 
        = Summation(volume, v_minute_bar_local_number_in_a_day);
end

else  
    v_accumulated_volume_per_minute =0;

if v_accumulated_volume_per_minute[2*4.5*60] > getfield("成交量","D")[1]
then ret=1;

 

回測結果如下圖二:

 

請問小幫手,我的數列函數是不是有沒注意到的邏輯錯誤?

排序方式: 標準 | 最新
XQ小幫手 發文於   2020/09/24

Sadless 您好

是否能夠詢問您這段的意義是什麼嗎?

if f_accumulated_volume_per_minute[2*4.5*60] > getfield("成交量","D")[1]

因為在我看起來應該是誤打了這段 [2*4.5*60] 才導致計算有問題

我看您下方的程式版本似乎沒這段

拿掉應該就可以正常執行了

Sadless 發文於   2020/09/25

f_accumulated_volume_per_minute

是存放過去每分鐘的累積成交量

  

f_accumulated_volume_per_minute[2*4.5*60

是要去存取該數列中,往回看兩天前該分鐘的累積成交量

 

[2*4.5*60]

2: 代表2天。

4.5: 代表股票開盤時間4.5小時(從9:00~13:30),

60: 代表每小時60分鐘。

 

Sadless 發文於   2020/09/25

這一段程式碼本身的邏輯是為了測試警示腳本,是否能夠存取函示 f_accumulated_volume_per_minute 所提供的數列 。

 

關鍵的問題還是回到,為什麼這行程式碼有問題?

是我設計的函數數列f_accumulated_volume_per_minute不能夠這樣使用嗎?

 

警示腳本:Test.accumulated_volume

settotalbar(2*4.5*60);

if f_accumulated_volume_per_minute[2*4.5*60] > getfield("成交量","D")[1]
then ret=1;

 

警示腳本:Test.accumulated_volume_2 是把自訂函數搬移到警示腳本裡面,所以把f_accumulated_volume_per_minute改成了 區域變數 v_accumulated_volume_per_minute。

 

我不理解的是,為什麼同樣的邏輯,寫在警示腳本裡面可行,可是寫在自訂函數裡面卻不可行呢?

Sadless 發文於   2020/09/25

經由小幫手的提示,我寫了一個更簡化的測試用警示腳本,也許這個警示腳本更能夠讓我們找到問題。

測試用警示腳本:Test.accumulated_volume_3

//Test.accumulated_volume_3

settotalbar(200);

if f_accumulated_volume_per_minute[2] > getfield("成交量","D")[1]
then ret=1; 

 

測試結果如下圖三:

出現73個失敗,全部都是 "不合法的欄位資料"。

請問小幫手,這個原因是甚麼呢?

Sadless 發文於   2020/09/25

我又更簡化了這個問題,寫了一個測試自訂函數跟測試警示腳本。

也許我們從這個範例更容易討論出問題的來由。

 

測試自訂函數:f_series_function

//f_series_function

setbarmode(2);  //設定為數列

f_series_function=0;

測試警示腳本:Test.series_function

//Test.series_function

settotalbar(540);

if f_series_function[2] > 1  //因為f_series_function=0,所以永遠都不會成立
then ret=1;

依然會出現 "不合法的欄位資料"的錯誤。

我猜測是我對於自訂函數數列(series)的用法理解錯誤。

不知道小幫手有甚麼提示呢?

XQ小幫手 發文於   2020/09/25

Sadless 您好

關於這個問題

小幫手會幫您查清原因在回覆您

Sadless 發文於   2020/10/06

好的,小幫手再麻煩你。

XQ小幫手 發文於   2020/10/06

Sadless 您好

這個主要的原因在於

函數資料讀取的問題

---

首先如果您是寫在同一個腳本,那當然不會有問題 因為雷達按照資料讀取筆數執行

但是當自訂函數時我們要先讓"雷達"運行到有足夠資料,函數才能正常運作

所以這時候要使用這個語法currentbar  

以下為介紹連結 currentbar

所以我們把您的程式稍作修改

//Test.series_function
var:Testseries_function(0);
settotalbar(540);
Testseries_function=0;
if currentbar>2 and Testseries_function[2] > 1  //因為f_series_function=0,所以永遠都不會成立
then ret=1;

這樣就沒問題了

Sadless 發文於   2020/10/07

已經測試,的確是currentbar的問題,感謝小幫手指點。

  • 按讚來自於
  • b24524658
Sadless 發文於   2020/10/13

請問小幫手,currentbar 是否有呼叫 getfield或是其他函式去外部伺服器取得資料呢?

會問這個問題的原因是因為,如果有的話,我想要減少currentbar出現的次數,以降低回測所需時間。

發表回覆
Close