請問小幫手,為何庫存賣出後又買入? 如何修正

  •   348 
  • 最後發表   XQYi  2025 二月 20
XQYi 發文於   2025/02/19

加了(not (Filled < Filled[1]))//不允許有庫存時賣出後又立即訊號買進 

為何庫存賣出後又觸發買入?

 

if  position >=0

and condition1

and (not (Filled < Filled[1]))//不允許有庫存時賣出後又立即訊號買進

then SetPosition(1,close);

 

Filled < Filled[1] 是否改為Position < Position[1] 就可避免?

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

not (Filled < Filled[1]) 其實就是Filled >= Filled[1]。賣掉庫存,filled不應該變大。當庫存賣出之後,若沒有成交,則Position < Position[1],而Filled < Filled[1]則不一定成立。沒成交時,兩者可能相等。

賣出庫存馬上買進,與Tick有關。你的position[1]是前根K棒的position,而非前一個Tick的Position。

你欠缺很多基本概念。若不投資進修,只靠論壇片片斷斷學習,還會有很多坎等著你。

  • 按讚來自於
  • YEAH301000
XQYi 發文於   2025/02/20

我是用日K頻率逐筆洗價,,Position 不是應該隨逐筆而變化?

GPT:

var LastSellTick = 0;

 

if position < position[1] then LastSellTick = CurrentTick; // 記錄賣出時刻

 

if position >= 0 

and condition1 

and CurrentTick > LastSellTick + 2  // 至少等 2 個 Tick 才允許買回

 

then SetPosition(1, close);

 

🎯 結論

如果 position[1] 是逐筆更新,那 position < position[1] 應該可以即時反映減碼,但仍可能因 Tick 內快速變化而導致「剛賣就買」。
如果 position[1] 來自 K 棒級別,就需要用 LastPosDelay 機制來防止誤判
可以增加 FilledDelay 條件,確保減碼後不會立即買回,防止洗價影響策略執行。

你可以先測試方法 1,如果還是出現問題,再試方法 2 或 3 🚀

 

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

日頻率之下,position[1]代表前一個交易日的position。若你相信ChatGPT,就請便。

  • 按讚來自於
  • YEAH301000
XQYi 發文於   2025/02/20

建議期待XQ, 整理出XS編寫問題的處理對策資料, 方便用戶查詢除錯的參考。

以下程式碼該如何修正? 是否有其他錯誤或疏忽之處?

程式交易的設計需求是

1. 設定實際庫存量允許的最大值

2. 商品最大部位不超過所設定的實際庫存量下交易

3. 依觸發訊號一張一張買進(最好能指定加碼次數),但不允許賣出後的商品又立即買進 (設計由第6個需求來執行)

4. 若庫存股有獲利如3%,則一張一張賣出(最好能指定減碼次數)

5.若是今日才買入的而有獲利,但該商品已有庫存時,只沖銷今日買的這張價位

6.若庫存股獲利後賣出,有回跌如2%則當沖買回

 

//訊號觸發買進
var: IntraBarPersist B1Pod(False); //尚未委買

if position <= position[1] then B1Pod=False;

if FilledAtBroker <=2  //控制各策略合計庫存總數量

    and B1Pod=False //尚未委買

    and position >=0 //目前部位 >=0

         and Condition1 //觸發條件

    and (not (Position < Position[1]))//不允許賣出後又立即訊號買進

then

begin

    SetPosition(minlist(position+1,2),MinList2(value2,value3,GEtField("收盤價", "Tick")),label:="訊號觸發買進"); 

    B1p=MinList2(value2,value3,GEtField("收盤價", "Tick")); //觸發取次低價格

    B1Pod=true; //已經委買

    BIT=Getfield("時間","Tick"); //觸發的時間
alert("B1P觸發",NumToStr(B1P,1),"Position",NumToStr(Position,1),"Position[1]",NumToStr(Position[1],1),"Filled",NumToStr(Filled,1),
    "Filled[1]",NumToStr(Filled[1],1));

end;

//獲利後賣出------------------------------------------------------------------------------------------
var: 
    intraBarPersist ord1(False), //下單狀態切換確認 未下賣單
    intraBarPersist Sod1(B1p*1.03); //預計賣出的價格 為避免抓錯資料改初始B1p測試
    if Position >= Filled then ord1=False; //目標部位 >= 實際部位
    if B1P <>0 then Sod1= B1P*1.03;

//庫平均  未新買入時舊庫存獲利會出場,未出場前若有新買入成本平均會異動
if Position > 0 and Filled > 0 //目前有庫存
    and ord1=False //尚未下單
    and GetField("收盤價", "Tick") > FilledAvgPrice*B1A //賣帳號內均價
then 
begin
    Setposition(maxList(Position-1,0),market,label:="庫獲利後賣出");
    {if Filled < Filled[1] then} Sod1=GetField("收盤價", "Tick");//紀錄賣出的價位
    {if Filled < Filled[1] then } ord1=True; //已下單賣出
    alert("庫獲利觸發",NumToStr(Sod1,1),"Position",NumToStr(Position,1),"Position[1]",NumToStr(Position[1],1),"Filled",NumToStr(Filled,1),
    "Filled[1]",NumToStr(Filled[1],1));
end;

//今日買沖(賣)  避免上未出場前若有新買入成本平均會異動,只針對新買入的價格做獲利出場
if Filled > 1 and Filled > Filled[1] //有庫存時有再買進
    and ord1=False //尚未下賣單
    and B1P > 10 
    and GetField("收盤價", "Tick") > B1P*B1A //賣今日買的
         //B1p似乎會抓錯資料暫不執行
then 
begin
    Setposition(maxList(Position-1,0),market,label:="再買獲利後賣出");
    Sod1=GetField("收盤價", "Tick");//紀錄賣出價位
    alert("再買獲利觸發",NumToStr(Sod1,1),"Position",NumToStr(Position,1),"Position[1]",NumToStr(Position[1],1),"Filled",NumToStr(Filled,1),
    "Filled[1]",NumToStr(Filled[1],1));
    if Filled < Filled[1] then ord1=True; //已下單賣出
end;

//"賣出後當沖買回" 因有兩種賣出情況 以下買回可能會有狀況-------------------------------------------------------------
var: intraBarPersist Brd1(False); //未下單買回 狀態切換
if Filled >=0 and Filled < Filled[1] then Brd1=False;
if  ord1=True //已獲利下單
    and Brd1=False //未下單買回
    and Sod1 > 10 and GetField("收盤價", "Tick") < Sod1*0.98 //價格回檔低於賣出價
    and condition1 //須仍有支撐及上漲空間才買回
then 
begin
    Print("賣沖F","日期",currentDate,"FIlled",NumToStr(FIlled,1),"B1P",NumToStr(B1P,1),
    "Sod1",NumToStr(Sod1,1),"Brd1",Brd1);
    setposition(Position+1,market,label:="賣出後當沖買回");
    alert("賣出後當沖獲利觸發",NumToStr(GetField("收盤價", "Tick"),1),"Position",NumToStr(Position,1),"Position[1]",NumToStr(Position[1],1),"Filled",NumToStr(Filled,1),
    "Filled[1]",NumToStr(Filled[1],1));
    if Position > Position[1] 
    then 
    begin 
        Brd1=True; //已下單買回
        Print("賣沖","日期",currentDate,"FIlled",NumToStr(FIlled,1),"B1P",NumToStr(B1P,1),
        "Sod1",NumToStr(Sod1,1),"Brd1",Brd1);
    end;
End;

//position恢復原來部位時的判斷
// 狀態重置
if currentTime >= 090000 and currentTime <=140000 and Position = position[1] 
then
begin
    ord1 = False;
    Brd1 = False;
    // 重置賣出與買回標記
end;

 

XQYi 發文於   2025/02/20

若 如先指定value55= -1

若觸發賣出後紀錄

value55= GetField("SeqNo", "Tick");

 

再將and (not (Filled < Filled[1]))//不允許有庫存時賣出後又立即訊號買進

這一段改為

and value55 = -1 //不允許有庫存時賣出後又立即訊號買進

發表回覆
Close