自動交易程式寫出抓前一日漲停的條件

  •   65 
  • 最後發表   投資CC  4 週前
投資CC 發文於   2026/02/05

我寫了一個交易程式,有編譯成功,也能回測,也能正式交易。

但是關於前一日漲停條件,回測後,有發現有些交易實際前一日沒有漲停,但是卻被交易了。不明白為何會如此。

實際交易的清單如下(從2026/01/01到2026/02/04):

回測勾選如下:

 

回測交易在交易清單,但有問題的案例

旺宏2337在0123沒有漲停,但0126有交易。

世界5347在0129沒有漲停,但0130有交易。

新唐4919在0129沒有漲停,但0130有交易。

昇貿3305在0130沒有漲停,但0202有交易。

系統電5309在0202有漲停,0203有交易,此交易ok。

股票清單檔案。

https://limewire.com/d/6lo89#kzRRBxZvcx

 

程式

inputs:
  // ----- 出場參數 -----
  _TakeProfit(6),          // 停利目標 (單位: %)
  _StopLoss(5),            // 停損幅度 (單位: %)
  _ExitTime(131000),       // 強制出場時間 (HHMMSS格式)
  // ----- 進場條件參數 -----
  _MaxPrice(200),             // 最高股價限制
  _MinPrice(50);              // 最低股價限制

vars:
  _v_EntryCondMet(false);     // 盤前進場條件是否滿足 (每日重設)

// ------------------------------
// 0. 腳本環境檢查與設定
// ------------------------------
setbarBack(100, "D"); // 設定回溯張數

// 僅支援1分鐘線頻率執行
if barfreq <> "Min" or barinterval <> 1 then raiseRunTimeError("本腳本只適用於1分鐘線");

// ------------------------------
// 1. 計算日線級別數據與進場條件
// ------------------------------

// --- 宣告所需日線級別變數 ---
variable: _d_prev_close(0);            // 前一日收盤價
variable: _d_prev_limit_up(0);         // 前一日漲停價
variable: _d_prev_high(0);             // 前一日最高價
variable: _d_foreign_buy(0);           // 前一日外資買賣超
variable: _d_sitc_buy(0);              // 前一日投信買賣超
variable: _d_dealer_buy(0);            // 前一日自營商買賣超

variable: _cond1_is_limit_up(false);      // 條件1: 前一日是否漲停
variable: _cond2_institutional_ok(false);  // 條件2: 法人買賣超

// --- 取得日線欄位數據 (統一使用 GetField 以確保跨頻率正確性) ---
_d_prev_close = GetField("Close", "D")[1];
_d_prev_limit_up = GetField("漲停價", "D")[1];
_d_prev_high = GetField("High", "D")[1];
_d_foreign_buy = GetField("外資買賣超", "D")[1];
_d_sitc_buy = GetField("投信買賣超", "D")[1];
_d_dealer_buy = GetField("自營商買賣超", "D")[1];

// --- 條件1:  ---
if _d_prev_close >= _d_prev_high and _d_prev_high = _d_prev_limit_up and _d_prev_limit_up > 0 then
  _cond1_is_limit_up = true; 

// --- 條件2:  ---
if _d_foreign_buy <= 0 and _d_sitc_buy <= 1000 and _d_dealer_buy <= -300 then
  _cond2_institutional_ok = true;

// 彙整盤前核心條件 (condition98)
// 包含:漲停、法人未同步買超 (註解部分可依需求開啟)
condition98 = _cond1_is_limit_up and _cond2_institutional_ok; 

// --- 基本過濾條件 (condition97) ---
condition1 = GetSymbolInfo("IsDayTrading") = True; // 必須可當沖
condition2 = _d_prev_close > _MinPrice and _d_prev_close < _MaxPrice; // 符合價格區間
condition97 = condition1 and condition2;

// ------------------------------
// 2. 盤中進場邏輯判斷
// ------------------------------
// 判斷時間為 090300 進場,且尚未進場過並符合盤前條件
if condition97 and condition98 and not _v_EntryCondMet and position = 0 and currentTime = 090300 then begin
  // 進場做空 1 單位,以當前價減 1 tick 進場
  SetPosition(-1, addSpread(Close, -1)); 
  _v_EntryCondMet = true; // 標記今日已觸發進場
end;

// ------------------------------
// 3. 出場邏輯判斷
// ------------------------------
// 定義出場條件
condition51 = currentTime >= _ExitTime; // 達到指定強制出場時間
condition52 = Close <= FilledAvgPrice * (1 - 0.01 * _TakeProfit); // 空單停利:價格下跌達到目標
condition53 = Close >= FilledAvgPrice * (1 + 0.01 * _StopLoss);   // 空單停損:價格上漲超過幅度

// 若符合任一出場條件且目前持有空單,則平倉
if filled < 0 then begin
  if condition51 or condition52 or condition53 then begin
    SetPosition(0); // 回補空單平倉
  end;
end;

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

在回測期間,若之前曾經漲停,則條件_cond1_is_limit_up會一直保留True(因為你的程式沒有讓它再次變成False的機會)。這會造成你看到的邏輯錯誤,明明前一天沒漲停,但卻觸發訊號。你可以在程式裡面條件1的前面加上讓它為False的指令:

_cond1_is_limit_up=false;

 

  • 按讚來自於
  • hiex88
投資CC 發文於   2026/02/05

請教教授,我用了date <> date [1]的方式,將其_cond1_is_limit_up=false;

而關於_cond2_institutional_ok是否也是會有一樣的情況,要_cond2_institutional_ok = false,如果沒有這樣寫會一直保留對嗎?


另外請教教授,關於程式的那些變數variable宣告的預設值,是只有程式第一次執行的時候會如此,所以教授才說要將
_cond1_is_limit_up=false寫上。

但關於其他變數由函數運算取得的,是否也要放在date <> date[1]裡面。(如以下這些變數)

目前我date <> date[1]這是放在前面和與variable宣告的後面,接著才是這些變數用函數運算賦值。

variable: _d_prev_close(0);            // 前一日收盤價
variable: _d_prev_limit_up(0);         // 前一日漲停價
variable: _d_prev_high(0);             // 前一日最高價
variable: _d_foreign_buy(0);           // 前一日外資買賣超
variable: _d_sitc_buy(0);              // 前一日投信買賣超
variable: _d_dealer_buy(0);            // 前一日自營商買賣超

虎科大許教授 發文於   2026/02/05

(1)宣告區的變數及參數只會在第一根K棒執行。

(2)用每天第一根分K時重新設定變數是OK的。只要可能在過去K棒會被改變的變數,為了避免數值被保留,應該在第一根分K恢復預設值。

(3)記錄前一天數值的變數,沒有必要在當天任何一個Tick都計算,那樣很沒效率。你一樣可以在第一根K棒計算即可,但我更建議用isFirstCall("Date"),亦即在第一個Tick處理。這樣更有效率。

 

 

  • 按讚來自於
  • hiex88
發表回覆
Close