每個月第一天看盤開始計算的問題

  •   51 
  • 最後發表   CL  2025 七月 23
CL 發文於   2025/07/19

你好

我想要寫一個每週和每月的第一天開始累計該週和該月的內外盤差額,我的寫法如下

vars: i(0),t_diff(0),t_diff1(0);
 value1 = GetField("內盤量","D");//單位:元
 value2 = GetField("外盤量","D");//單位:元
 if value1 <> 0 then
 value3 = value2 - value1;

t_diff = 0;
for i = 0 to DayOfWeek(Date)-1
 begin
 t_diff = t_diff + xf_getvalue("D",value3,i);
 end;

 t_diff1 = 0;
  for i = 0 to DayOfMonth(Date)-1
  begin
  t_diff1 = t_diff1 + xf_getvalue("D",value3,i);
  end;

執行後週的部分都沒有問題,但不知為何,月的部分都會加到前一個月最後一天的差額,更奇怪的是,2月第一天是加了一個不知道哪裡來的數字。麻煩指點一下。感謝。

排序方式: 標準 | 最新
虎科大許教授 發文於   2025/07/19

以下的程式未經驗證,請自行驗證數值是否正確。另外,第一個月的數值可能不準,因為資料開始的日期若非該月第一個交易日,數值就會被低估。

setTotalBar(212);
var: BidAskDiff(0);
if Month(date)<>Month(date[1]) then
    begin
        print(text(numtoStr(year(date),0),"年",numtoStr(month(date[1]),0),"月"),"內外盤量差",numtoStr(BidAskDiff,0)+"張");
        BidAskDiff=0;
        BidAskDiff=GetField("內盤量","D")-GetField("外盤量","D");     
    end
else 
    if isLastBar then   
        begin
            BidAskDiff+=GetField("內盤量","D")-GetField("外盤量","D");
            print(text(numtoStr(year(date),0),"年",numtoStr(month(date[1]),0),"月"),"內外盤量差",numtoStr(BidAskDiff,0)+"張");
        end
    else BidAskDiff+=GetField("內盤量","D")-GetField("外盤量","D");

CL 發文於   2025/07/20

我試了一下回應的程式碼,結果是每個月的第一根都是正確數字,但是之後的數字就都不正確... 我修改了一下原始PO問,加上用同樣方式累計每週累計內外盤差,結果都完全正確,但同樣的方式用在月的累計內外盤差,卻都在第一天會加到前一個月最後一天的數值(二月除外,不知道為什麼)。

虎科大許教授 發文於   2025/07/20

你的寫法是很沒效率的寫法且容易出現邏輯錯誤。跨頻率時,不應該用變數處理資料,問題出在使用變數value3。若要在分鐘頻率處理這個問題,則跑歷史K棒時,就稍微複雜一些,除了必須判斷分K的日與前一根K棒的日不同時,才記錄日內外盤差並累加,且月份與前一根分K的月份不同時,才將累加的數值呈現。處理方式與跑日頻率類似。

CL 發文於   2025/07/20

我前面回應其實有錯,應該是我有點不確定在分鐘級別每一根K棒呈現的GetField("外盤量","D")-GetField("內盤量","D")是累計差還是該K棒的差,如果是單一K棒的差,那你的寫法呈現出來的就都是正確的。不過因為我對程式的理解很粗淺,所以不是很了解您的解說,謝謝指點。

 

 

CL 發文於   2025/07/20

剛才又查了一下,GetField("外盤量","D")和GetField("內盤量","D")在分鐘頻率其實就是累計了當日的內外盤數量,所以GetField("外盤量","D")-GetField("內盤量","D")應該是累計的當日的內外盤差,所以您回應的程式,在分鐘頻率是把每一根K棒累計出來的數字再加起來,所以就不正確。結論就是我原本寫的程式,第一部分用在一周累計的的內外盤差是正確的,但用在一個月的累計出現問題的點是在每個月的第一天...不過我把您提供的程式後半段改成(把"D"拿掉),似乎就都正確了。目前問題應該是解決了,感謝協助。

else 
    if isLastBar then   
        begin
            BidAskDiff+=GetField("外盤量")-GetField("內盤量");
            print(text(numtoStr(year(date),0),"年",numtoStr(month(date[1]),0),"月"),"內外盤量差",numtoStr(BidAskDiff,0)+"張");
        end
    else BidAskDiff+=GetField("外盤量")-GetField("內盤量");

CL 發文於   2025/07/20

最後,出於好奇,您提到跨頻率時,不應該用變數處理資料,所以我就參照您寫的方式修改我原本的程式,

vars: i(0),t_diff(0),t_diff1(0);
 
 value2 = GetField("外盤量","D")-GetField("內盤量","D");
 value3 = GetField("外盤量")-GetField("內盤量");


//累計周差
t_diff = 0;
for i = 0 to DayOfWeek(Date)-1
 begin
 t_diff += GetField("外盤量","D")[i]-GetField("內盤量","D")[i];
 end;



//累計月差(錯誤)
t_diff1 = 0;
for i = 0 to DayOfMonth(Date)-1
   begin
   t_diff1 += GetField("外盤量","D")[i]-GetField("內盤量","D")[i];
   end;


plot1(value2,"當日內外盤差");
plot2(value3,"K棒內外盤差");

plot3(t_diff,"累計本周內外盤差");
plot4(t_diff1,"累計本月內外盤差");

 

但是結果似乎一樣,就是累計一周的沒問題,但是累計一個月的數字跟原本一樣,所以還是不知道為什麼。我也不是很懂您提到的效率問題,但在執行上確實有差,改用您寫的方式,圖立刻就出來,但我寫的就要等幾秒。

虎科大許教授 發文於   2025/07/20

效率是投入與產出的概念。若投入相同,產出比較多的,效率較高。產出相同,投入比較少的,效率較高。你我的程式產出相同,但我投入(執行)的時間較少,所以效率較高。造成你程式效率低的原因在於一直在跑迴圈。XQ是序列語言,很多問題可以不必跑迴圈就解決的。跑迴圈很耗資源,這造成你的指標顯示較慢。你試著改成我建議的方式(我的範例)寫看看,若還有問題,再貼文上來詢問。

XS小編 發文於   2025/07/23

Hello CL,

 

小編補充,變數的頻率會和執行頻率相同,所以在跨頻率時要注意取前期值時會取到不同的資訊。

舉例來說,腳本運作在1分鐘頻率上:

value1 = getfield("Close", "D");

 

value1[1] 會是前一分鐘的當日收盤價。

getfield("Close", "D")[1] 則會是前一日的收盤價。

 

關於腳本運算效率的問題,若想知道腳本怎麼撰寫會比較有效率,您可以參考關於演算法的資訊。

發表回覆
Close