跳轉到

Block.screener 執行選股

所屬章節:積木 Block 以 2026-08-20 實際執行結果為準(資料日 2026-08-19)

Overview

把一組積木跑成選股結果。多個積木之間是 AND。

api.Block.screener_tw(block_list, pool=None, date='now')
api.Block.screener_us(block_list, date='now')
參數 型態 說明
block_list list[dict] con_tw() / con_us() 產生的積木清單,彼此 AND
pool list[str], optional 股池,僅台股。預設 ['all']。見 股池
date str 'now'(預設)、'last',或 'YYYY-MM-DD'

回傳 dict,四個 key:

key 型態 說明
dataframe DataFrame 符合條件的股票,一列一檔,含各積木的中間計算值
date Timestamp 這批結果對應的資料日期
sig DataFrame 完整訊號矩陣,日期(index)× 股票代號(columns),值為 bool
code str 等價的可執行 python 程式碼,見 產生的程式碼

api.Block 沒有開放 include_values=False,dataframe 一律含中間值。

Manual Sample Input/Output

Example 1:單一積木

input

b1 = api.Block.con_tw('今日收盤價<>開高低P%',
                      operator='>', ohlc_field='adj_High', percent=3)
r = api.Block.screener_tw([b1])
print(list(r))
print(r['date'], r['dataframe'].shape, r['sig'].shape)
r['dataframe'].head(3)

output

['code', 'dataframe', 'date', 'sig']
2026-08-19 00:00:00 (2343, 8) (1000, 2865)

  stock_id   sig  cond1_sig  cond1_close  cond1_ohlcData  cond1_ohlc_processed  cond1_olhc_metrics  cond1_comparison_ratio
0   00400A  True       True      14.7200         14.3600               11.0725             10.7500                 1.3294
1   00401A  True       True      13.3800         13.1500               10.8150             10.5000                 1.2372
2   00402A  True       True       9.7200          9.6300                9.1670              8.9000                 1.0603

欄位規則:

  • stock_id:股票代號
  • sig:最終訊號(全部為 True,因為只列出通過的)
  • cond<N>_*:第 N 個積木的中間值。cond1_sig 是該積木自己的訊號,其餘欄名由該積木類別決定

sig 是完整矩陣(1000 個交易日 × 2865 檔),不只當日。


Example 2:多積木 AND

input

b1 = api.Block.con_tw('今日收盤價<>開高低P%',
                      operator='>', ohlc_field='adj_High', percent=3)
b2 = api.Block.con_tw('今日收盤價(開低高)與近D日內最高價<P%',
                      period=20, percent=5)

print(api.Block.screener_tw([b1])['dataframe'].shape[0], '檔(僅積木1)')
print(api.Block.screener_tw([b2])['dataframe'].shape[0], '檔(僅積木2)')
r = api.Block.screener_tw([b1, b2])
print(r['dataframe'].shape[0], '檔(AND)')
list(r['dataframe'].columns)

output

2343 檔(僅積木1)
1040 檔(僅積木2)
816 檔(AND)

['stock_id', 'sig',
 'cond1_sig', 'cond1_close', 'cond1_ohlcData', 'cond1_ohlc_processed',
 'cond1_olhc_metrics', 'cond1_comparison_ratio',
 'cond2_sig', 'cond2_close', 'cond2_high', 'cond2_rolling_high',
 'cond2_distance_pct']

積木數量增加時,cond<N>_* 欄位會累加。


Example 3:date 參數

input

for d in ('now', 'last'):
    r = api.Block.screener_tw([b1], date=d)
    print(f"date={d!r} -> {r['date']}, {r['dataframe'].shape[0]} 檔")

output

date='now' -> 2026-08-19 00:00:00, 2343 檔
date='last' -> 2026-08-19 00:00:00, 2343 檔
  • 'now':取 ≤ 今天 的最後一個可用日期
  • 'last':取矩陣的最後一列,不管是否已過今天
  • 指定日期字串:取 ≤ 該日期 的最後一個可用日期

盤中執行時 MSMP 只到前一交易日,所以 'now' 與 'last' 通常相同。 兩者會分歧的情況是季頻/月頻積木——那些資料的 index 可能排到未來 (例如 api.MSMP.INDEX['Q'] 最後一筆是 2026-11-16),此時 'last' 會取到未來日期。


Example 4:美股

美股不開放 pool(api.USMSMP 沒有 list)。

input

b = api.Block.con_us('今日收盤價<>開高低P%',
                     operator='>', field1='Open', percent=1)
r = api.Block.screener_us([b])
print(r['date'], r['dataframe'].shape, r['sig'].shape)
r['dataframe'].head(3)

output

2026-08-18 00:00:00 (1569, 6) (1000, 13169)

  stock_id   sig  cond1_sig  cond1_close  cond1_rhs  cond1_threshold
0     AACG  True       True       0.9959     0.9605           0.9701
1     AAOZ  True       True       9.8800     8.4500           8.5345
2     AAPB  True       True      38.2200    37.6000          37.9760

Example 5:零命中時 dataframe 是 (0, 0)

沒有任何股票通過時,dataframe 是完全空的——連欄位都沒有:

input

b = api.Block.con_us('今日收盤價<>開高低P%',
                     operator='>', field1='High', percent=3)
r = api.Block.screener_us([b])
print(r['dataframe'].shape, list(r['dataframe'].columns), r['sig'].shape)

output

(0, 0) [] (1000, 13169)

(收盤價要高於當日最高價的 1.03 倍,本質上不可能成立。)

所以不能無條件存取 r['dataframe']['stock_id'],會 KeyError。安全寫法:

df = r['dataframe']
symbols = df['stock_id'].tolist() if len(df) else []

Example 6:選不出股票時,先看 sig 的欄數

「選出 0 檔」有兩種完全不同的意思,看 sig 的欄數就能分辨:

sig 形狀 意思
(1000, 2865) 但 dataframe 是 (0, 0) 條件正常,只是當日沒有股票通過
(1000, 0) 訊號矩陣裡根本沒有股票,這個積木壞了

input

r = api.Block.screener_tw([b])
print(r['sig'].shape, r['dataframe'].shape)

output

(1000, 2865) (0, 0)      # 正常,只是沒人通過

sig 欄數為 0 通常是積木內部把兩個欄位對不起來的矩陣相除或相比 (例如個股矩陣的 columns 是股票代號,另一邊卻是法人類別), pandas 對齊後交集為空。這是 bug,不是篩選結果。

台股有 20 個積木在 2026-08-19 這天合理地選出 0 檔(孤島晨星、一紅吃三黑、 十字線這類很嚴格的 K 線型態,以及年度股利的緊門檻),它們的 sig 欄數都正常。


Example 7:首次呼叫會下載資料

積木用到的 MSMP 欄位是延遲載入的,第一次碰到某個欄位會即時下載:

正在下載 最高價: 100%|##########| 10.6M/10.6M [00:01<00:00, 5.71MB/s]
下載成功
正在下載 最低價: 100%|##########| 6.63M/6.63M [00:01<00:00, 5.11MB/s]
下載成功

所以同一組積木第一次跑約 6 秒,第二次約 0.8 秒。要量測效能請跑第二次以後。