自動交易中心:利用語法控管第一次洗價

自動交易中心:利用語法控管第一次洗價

2024-12-17 18:53:54
    自動交易中心:利用語法控管第一次洗價

1. 摘要

這篇文章我們要來介紹,XS函數 isfirstcall ,它是用來偵測特定事件發生時的第一次觸發,解決腳本撰寫中常見的重複觸發、變數重置問題,提升腳本設計效率。函數支援四種情境:
  1. isfirstcall(" "):此次執行的第一次觸發,用於變數初始化或資料引用。
  2. isfirstcall("Bar"):每根K棒的第一次觸發,適合處理K棒內的單次或多次條件判斷。
  3. isfirstcall("Date"):每個交易日的第一次觸發,應用於跨日清倉等操作。
  4. isfirstcall("Realtime"):進入即時洗價區間的第一次觸發,適合即時行情處理,如時間限制策略。
isfirstcall 是以事件定義為基礎,讀取當次洗價的狀態,不受流程函數限制,可以大幅減少腳本邏輯的撰寫負擔並提高執行效率。  

2. isfirstcall(" "):此次執行的第一次洗價

只會 true 一次,後續洗價維持 false。 會用到這個事件,通常是為了在腳本啟動後,處理需要引用的資料或變數,而且只需要在一開始執行一次,之後不再需要。 只在第一次洗價時判斷條件,之後都不需再次判斷。

2.1. 不用 isfirstcall 的寫法:

 
{先宣告變數_firstTime,來限制觸發一次}

var:_firstTime(0);

condition1 = ……;

if _firstTime = 0 then begin

if condition1 then …… ;

_firstTime = 1; //第一次洗價後_firstTime就會持續=1,此後不會再=0了

end;
   

2.2. isfirstcall(" ") 的寫法:

 
condition1 = ……;

if isfirstcall(" ") then condition1 then ……;
 

 3. isfirstcall("Bar"):此根 Bar 的第一次洗價

換 Bar 就會更新為 true 一次,其餘洗價維持 false。 這些應該是 XS 玩家最常用到的情境了:

3.1. 逐筆洗價時,Bar 內單次觸發

援引「上一根 Bar 最後一次的洗價結果」

3.1.1 不用 isfirstcall 的寫法:

 
{宣告一個intrabarpersist性質的變數_Bar,來限制Bar內觸發一次}

var: intrabarpersist _Bar(0);

condition1 = ......;

if _Bar <> currentbar then begin 

if  condition1[1] then  ......; 

_Bar = currentbar;   //更新 _Bar的數值

end;
 

3.1.2. isfirstcall("Bar") 的寫法:

 
condition1 = ......;

if isfirstcall("Bar") and condition1[1] then ......;
 

3.2. Bar 內 N 次觸發,使用最新洗價的結果來判斷

3.2.1 不用 isfirstcall 的寫法:

 
input:N(3,"限制觸發次數");

var: intrabarpersist _Bar(0), intraBarPersist counts(0);

{將累積觸發次數counts,在Bar內第一次洗價時歸0}

if _Bar <> currentbar then begin 

counts = 0;

_Bar = currentbar;

end;

{Bar內最多累積N次觸發}

condition1 = ......;

if condition1 and counts < N then begin

......;

counts += 1;

end;
   

3.2.2. isfirstcall ("Bar") 的寫法:

 
input:N(3,"限制觸發次數");

var:intraBarPersist counts(0);

{將累積觸發次數counts,在Bar內第一次洗價時歸0}

if isfirstcall("Bar") then counts = 0;

{Bar內最多累積N次觸發}

if condition1 and counts < N then begin

......;

counts += 1;

end;
   

4. isfirstcall("Date"):此交易日的第一次洗價

依照執行商品的交易日來決定何時換日,例如:
  • 股票會在 09:00 時換日
  • 期貨(一般)會在 08:45 時換日
  • 期貨(全日)會在 15:00 時換日
換交易日就會更新為 true 一次,其餘洗價維持 false。 所以會根據執行商品的交易日更新時間,來決定第一次洗價的時機,會與單純用 date<>date[1] 來判斷 00:00 時換日,有所不同。   隔日沖開盤出場
  • 若是股票、期貨(一般),不用 isfirstcall 的寫法:
 
if date<>date[1] and Position > 0 then

SetPosition(0, label:="換日開盤清倉");
 
  • 若是期貨(全日),不用 isfirstcall 的寫法(通用於全部商品):
 
{用isSessionFirstBar來鎖定交易日的第一根Bar,再加上單根Bar內限制觸發一次的邏輯}

var:intraBarPersist _Bar;

if isSessionFirstBar and _Bar <> currentBar and Position > 0 then begin

SetPosition(0, label:="換日開盤清倉");

_Bar = currentBar;

end;
 
  • isfirstcall("Date") 的寫法(通用於全部商品):
 
if IsFirstCall("Date") and Position > 0 then

SetPosition(0, label:="換日開盤清倉");
   

5. isfirstcall("Realtime"):進入即時洗價區間的第一次洗價

從資料歷史區間轉進即時區間後,就會更新為 true 一次,其餘洗價維持 false。 如題,只有在即時洗價區間才會成立,洗價區間分為歷史與即時,歷史洗價區間就是所謂「資料讀取筆數(totalbar)」或「自動交易的策略部位計算」的範圍;即時洗價區間則是在資料讀取完成後,進入盤中即時行情的範圍。 策略進入即時洗價後 N 分鐘,停止策略
  • 不用 isfirstcall 的寫法:
 
input:N(60,"幾分鐘後停止策略");

var:_firstTime(0), _startTime(0);

if _firstTime = 0 then begin

   _startTime = currentTime;

   _firstTime = 1;

end;

if currentTime >= TimeAdd(_startTime,"MM",N) then 

raiseRunTimeError("時間到停止策略");
   
  • isfirstcall("Date") 的寫法:
 
input:N(60,"幾分鐘後停止策略");

var: _startTime(0);

if isfirstcall("Realtime") then _startTime = currentTime;

if currentTime >= TimeAdd(_startTime,"MM",N) then 

raiseRunTimeError("時間到停止策略");
 

6.  總結

isfirstcall 不會受到 if…else… 等流程函數限制,它的作法是讀取當次洗價,是否為事件定義的第一次洗價:若是則為 true;若不是,那就會維持 false 直到事件再次更新。 舉 isfirstcall(" ") 為例,只有此次執行的第一次洗價為 true,若腳本設定的資料讀取筆數 (settotalbar)<>0,或是交易策略有設定歷史策略部位計算,那 isfirstcall(" ") 就會在歷史區間的第一根 Bar 為 true,之後都會維持 false 的狀態。 不會因為在盤中啟動腳本,才在即時區間的第一次洗價為 true,即時區間的第一次洗價要使用 isfirstcall("Realtime")。 另外,若是用 if… 等流程函數將 isfirstcall 包住,導致避開事件定義的第一次洗價,那之後即使通過流程函數並第一次呼叫 isfirstcall,那也會是 false。 第一段所謂「事件再次更新」的意思是,例如 isfirstcall("Bar") 在進到新的 Bar 時、isfirstcall("Date") 在跨到新的交易日時、isfirstcall("Realtime") 每次從歷史區間跨到即時區間時,會重新為 true 一次。 以上就是 利用語法控管第一次洗價教學,我是 XQ 小編,我們下次見。