呼叫小幫手,有庫存下intraBarPersist B1P(FilledAvgPrice),為何抓到的資料為0?

  •   443 
  • 最後發表   XQYi  2025 一月 17
XQYi 發文於   2025/01/08

有庫存下intraBarPersist B1P(FilledAvgPrice),為何抓到的資料為0,而導致虧損賣

input: T1(60,"09:30秒"), T2(300,"秒"), 
       C1(1,"均1"), C2(2,"均2"), C3(5,"均5"), 
       C4(12,"E12"), C5(26,"E26");
// 設定時間參數 T1 和 T2,代表未成交單的取消時間
// 設定均線參數 C1-C5,分別為不同週期的移動平均線與指數移動平均線

input: B1A(1.03); 
// 設定獲利出場百分比 (1.03 = 3% 獲利目標)

var: intraBarPersist B1P(FilledAvgPrice), intraBarPersist BIT(0);
// B1P: 紀錄買進時的價格
// BIT: 紀錄買進訊號的時間

var: intraBarPersist ord1(False), intraBarPersist Sod1(FilledAvgPrice);
// ord1: 賣出訂單狀態標記,防止重複賣出
// Sod1: 紀錄賣出時的價格

var: intraBarPersist Brd1(False); 
// Brd1: 當沖買回狀態標記,防止重複買回

value1 = average(close, C1);
// 計算 C1 週期的簡單移動平均 (SMA)
value2 = average(close, C2);
// 計算 C2 週期的簡單移動平均 (SMA)
value3 = average(close, C3);
// 計算 C3 週期的簡單移動平均 (SMA)
value4 = ema(close, C4);
// 計算 C4 週期的指數移動平均 (EMA)
value5 = ema(GetField("Close"), C5);
// 計算 C5 週期的指數移動平均 (EMA)

value11 = BarsLast(xf_EMA("D", Close, 12) cross over xf_EMA("D", Close, 26));
// 計算 12 週期 EMA 上穿 26 週期 EMA 到現在的天數
value12 = BarsLast(xf_EMA("D", Close, 12) cross under xf_EMA("D", Close, 26));
// 計算 12 週期 EMA 下穿 26 週期 EMA 到現在的天數
value13 = minlist(value11, value12);
// 取上述兩者較小的數值,代表最近一次金叉或死叉發生的時間
Value14 = highest(high, value13);
// 取得最近金叉/死叉期間的最高價
Value15 = lowest(low, value13);
// 取得最近金叉/死叉期間的最低價

Condition1 = trueAll(Value15 >= Value15[1], 3) AND trueAll(Value14 >= Value14[1], 3) 
             AND (Value14 - Value15) / Value15 >= 0.05;
// 條件1: 最近的低點和高點連續 3 個週期上升,且高低差距超過 5%

// 買進訊號
if FilledAtBroker <= 2  // 檢查庫存數量,最多允許兩筆庫存
    and value2 cross Over value3  // 當短期均線 (C2) 上穿中期均線 (C3)
    and Value11 < Value12 // 當前屬於 EMA 金叉階段
    and Condition1 // 符合支撐與上漲條件
    and position >= 0 then  // 當前倉位為非負數
begin
    SetPosition(position + 1, MinList(value3, GetField("收盤價", "Tick")), label:="訊號觸發買進");
    // 下單買進,價格取均線或即時收盤價中較低者
    B1P =  GetField("收盤價", "Tick");
    // 記錄買進價格
    BIT = GetField("時間", "Tick");
    // 記錄買進時間
end;

// 未成交單取消邏輯
if Position > filled then 
begin
    if currentTime <= 093000 and GetField("時間", "Tick") >= TimeAdd(BIT, "S", T1) then 
        CancelAllOrders(label:="未成交逾時T1取消買進委託");
    // 早於 09:30,檢查時間是否超過 T1 秒,若超過則取消未成交單
    if currentTime > 093000 and GetField("時間", "Tick") >= TimeAdd(BIT, "S", T2) then 
        CancelAllOrders(label:="未成交逾時T2取消買進委託");
    // 晚於 09:30,檢查時間是否超過 T2 秒,若超過則取消未成交單
    BIT = 0;
    // 重置買進時間標記
end;

// 獲利賣出條件
if Filled > 0 and ord1 = False and (
    GetField("收盤價", "Tick") > FilledAvgPrice * B1A or 
    (Filled > Filled[1] and GetField("收盤價", "Tick") > B1P * B1A)) then 
begin
    SetPosition(Position - 1, GetField("收盤價", "Tick"), label:="獲利後賣出");
    // 下單賣出,價格為即時收盤價
    Sod1 = GetField("收盤價", "Tick");
    // 記錄賣出價格
    ord1 = True;
    // 設定賣出狀態標記
end;

// 當沖買回條件
if ord1 = True and Brd1 = False and GetField("收盤價", "Tick") < Sod1 * 0.98 then 
begin
    SetPosition(Position + 1, GetField("收盤價", "Tick"), label:="賣出後當沖買回");
    // 下單買回,價格為即時收盤價
    Brd1 = True;
    // 設定買回狀態標記
end;

// 狀態重置
if Position = position[1] then 
begin
    ord1 = False;
    Brd1 = False;
    // 重置賣出與買回標記
end;

// 數據除錯輸出
if position <> position[1] or filled <> Filled[1] 
then 
print( "Position",Position,"Position[1]",Position[1],"Filled",Filled,"Filled[1]",Filled[1],
"------","B1p ",B1p,"V3 ",value3,"CTick ",GEtField("收盤價", "Tick"),"BIt ",BIT,"Sod1 ",Sod1
,"ord1 ", ord1,"Brd1 ",Brd1); //,"TBIT ",TBIT); 
// 輸出各變數數值以供除錯

附加文件

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

問題出在跑歷史K棒時filled、filledAvgPrice都是0,直到歷史K棒跑完,才會設定初始部位。此時,還沒出現進場訊號,B1p還沒被賦予數值,所以仍然是0。儘管你宣告時預設它是filledAvgPrice,但這只在第一根K棒執行,那時候filledAvgPrice仍然是0。

  • 按讚來自於
  • YEAH301000
XQYi 發文於   2025/01/08

所以把(filledAvgPrice)更改為一個較大的數值(5000),就可以避免為0 ?

還是有其他更為正確的做法?

 

虎科大許教授 發文於   2025/01/08

就B1p而言,重點是沒有進場訊號,所以會顯示預設值,0或5000無關。

XQYi 發文於   2025/01/08

所以程式列78 應該如何修改?

之前有試過用進場時間BIT > 0 、及增加變數TBIT(False),確定委買後TBIT=true 做判斷也是不行,

B1P > 10 and GetField("收盤價", "Tick") > B1P * B1A)  ? 試過太多忘了這個判斷的結果

如何才能針對有庫存再加碼時,將今日加碼買進的價位有獲利時當沖賣出

 

XQYi 發文於   2025/01/09

B1P > 10 and GetField("收盤價", "Tick") > B1P * B1A)  ? 試過太多忘了這個判斷的結果

回測結果也是發生虧損賣出!!!

XQYi 發文於   2025/01/13

小幫手是否能解?

或以此略複雜的交易方式,提供範例大眾參考

XQ小幫手 發文於   2025/01/13

Hi XQYI,

建議使用類似 Ver_B1P = FilledAvgPrice; 的方式,去紀錄買進時的價格,

可以 Print 出來觀察,用上述紀錄買進時的價格,就會比較正確,程式碼範例與圖片供參考,

請注意,記得用模擬交易帳戶確認過小幫手的建議是否 OK,謝謝。

input: T1(60,"09:30秒"), T2(300,"秒"), 
       C1(1,"均1"), C2(2,"均2"), C3(5,"均5"), 
       C4(12,"E12"), C5(26,"E26");
// 設定時間參數 T1 和 T2,代表未成交單的取消時間
// 設定均線參數 C1-C5,分別為不同週期的移動平均線與指數移動平均線

input: B1A(1.03); 
// 設定獲利出場百分比 (1.03 = 3% 獲利目標)

var: intraBarPersist B1P(FilledAvgPrice), intraBarPersist BIT(0);
// B1P: 紀錄買進時的價格
// BIT: 紀錄買進訊號的時間

var: intraBarPersist Ver_B1P(FilledAvgPrice);
// Ver_B1P: 小幫手紀錄買進時的價格

if getinfo("IsRealTime") = 1 then setposition(1, market);
// 小幫手模擬用。

Ver_B1P = FilledAvgPrice;

print(datetime,currentTime,Ver_B1P,B1P);

附加文件

XQ小幫手 發文於   2025/01/13

Hi XQYI,

不好意思,小幫手眼殘沒看到是有庫存的設定下,

其實作法同上所述,都建議使用類似 Ver_B1P = FilledAvgPrice; 的方式,去紀錄買進時的價格,

若是有庫存則程式碼範例與圖片如下圖,供參考。

input: T1(60,"09:30秒"), T2(300,"秒"), 
       C1(1,"均1"), C2(2,"均2"), C3(5,"均5"), 
       C4(12,"E12"), C5(26,"E26");
// 設定時間參數 T1 和 T2,代表未成交單的取消時間
// 設定均線參數 C1-C5,分別為不同週期的移動平均線與指數移動平均線

input: B1A(1.03); 
// 設定獲利出場百分比 (1.03 = 3% 獲利目標)

var: intraBarPersist B1P(FilledAvgPrice), intraBarPersist BIT(0);
// B1P: 紀錄買進時的價格
// BIT: 紀錄買進訊號的時間

var: intraBarPersist Ver_B1P(FilledAvgPrice);
// Ver_B1P: 小幫手紀錄買進時的價格

Ver_B1P = FilledAvgPrice;

print(datetime,currentTime,Ver_B1P,B1P);

 

附加文件

XQYi 發文於   2025/01/14

 
var: intraBarPersist Ver_B1P(FilledAvgPrice);
// Ver_B1P: 小幫手紀錄買進時的價格

Ver_B1P = FilledAvgPrice;

以上所述之修正"
理解為: 變數的"預設數值"不等於"起始的數值",必須"再指定一次"? 

是每一個指定的變數起始值若不是為0,都要再指定一次起始數值?

XQ小幫手 發文於   2025/01/14

Hi xqyi,

Var 宣告的變數,是初始值,也就是第一次執行腳本取得的值,

而 FilledAvgPrice 在第一次(也就是跑在資料讀取第 1 筆)執行交易腳本的初始值是 0,

直到進入到「開始即時洗價的狀態」才會是未平倉成本的數值。

所以小幫手才建議用 Ver_B1P = FilledAvgPrice; 去紀錄,這樣子每次執行腳本的時候,都會去更新一次未平倉成本的數值。

 

若用您原本的 Var 宣告變數的方式「var: intraBarPersist B1P(FilledAvgPrice)」

則會因為第一次執行腳本取得的初始值 FilledAvgPrice 是 0 的關係,

且無用 B1P = FilledAvgPrice; 每次執行腳本去更新,導致後續跑的腳本取得的 B1P 都會是 0。

顯示更多回應 發表回覆
Close