錯誤訊息速查
所屬章節:入門 每一則訊息都是 2026-08-21 實際觸發後抄下來的原文
撞到錯誤先查這頁。最後一節「不報錯但結果是錯的」是最該看的—— 那些不會拋例外,只會給你錯的答案。
兩層驗證:con() 驗規格,screener() 驗 class
這是最常誤解的地方。 con_tw() / con_us() 只比對 block_spec.json 的合法值清單;
積木 class 自己的限制要到 screener() 建構物件時才浮現。
B.con_tw('漲跌幅介於P1%到P2%之間', percent1=5, percent2=9) # 沒報錯,回一個 dict
B.screener_tw([那個 dict])
# ValueError: percent1 (5) must be greater than percent2 (9)
B.con_tw('今日收盤價突(跌)破D日均線', operator='>', period=20, table='日') # 沒報錯
B.screener_tw([那個 dict])
# ValueError: 找不到名為 '日' 的表格。
所以 con() 過了不代表能跑。 組完積木要真的跑一次 screener() 才算驗證過。
積木(api.Block)
| 訊息 | 原因 | 怎麼修 |
|---|---|---|
ValueError: 找不到積木 '不存在的積木'(market=tw) |
名稱打錯,或那個積木在 list_conditions 有但 get_table 沒有(停用/漏登錄) |
只信 get_table_tw() 的 key。找積木用 [n for n in B.get_table_tw() if '關鍵字' in n] |
ValueError: 積木「…」沒有參數 ['pct'] |
參數名打錯,或那個積木根本不吃參數 | B.get_table_tw()['積木名'] 看有哪些參數 |
ValueError: 積木「…」的參數 percent 不支援 4 |
值不在合法值清單裡 | 同上,看合法值。別依賴預設值——台股 59 個、美股 18 個積木的預設值不在自己宣告的清單內 |
ValueError: 積木「…」的參數 ['value'] 已由規格固定,不可指定value = 0.4 |
這個參數被規格釘死,con() 會自動帶出來 |
不要傳它。台股 28 個、美股 12 個積木有固定值 |
ValueError: percent1 (5) must be greater than percent2 (9) |
o6 的 percent1 是上界、percent2 是下界,與名稱直覺相反 |
大的填 percent1 |
ValueError: 找不到名為 '日' 的表格。 |
8 個複合值積木的 table/direction,get_table 顯示 ['日','周','月'] 但 class 要 '日_K' |
不要傳這個參數,用預設值(等於只有日頻)。o29/o30/v5/v7/v8/m5/m7 的 table、r4 的 direction |
TypeError: Block.screener_us() got an unexpected keyword argument 'pool' |
美股沒有股池 | 自己切 columns,見 usmsmp.md |
IndexError: list index out of range |
screener_tw([]) 傳了空清單 |
至少給一個積木 |
AttributeError: module 'snowyowl.blocks.data_context' has no attribute 'api' |
想繞過 so.login() 直接拿 api |
走 api = so.login(person_id, person_pwd)。資料來源是 login 內部 bind_api() 注入的 |
表格查詢(api.Data / api.USData)
| 訊息 | 原因 | 怎麼修 |
|---|---|---|
ValueError: 找不到 table: 不存在的表 |
表名打錯 | 表名要完全一致含全形括號與斜線。常漏的是開頭的「取得」——取得個股內外盤… 有,個股營收資訊… 沒有 |
ValueError: 參數輸入錯誤,正確用法:Data.get('…', '2330') |
參數個數不對(少傳或多傳都是這則) | 照訊息裡印的用法改 |
ValueError: 參數輸入錯誤,正確用法:Data.get('取得即時分K(最後交易日)', '2330', 1) # minutes 可選: [1, 3, 5, 15, 30, 60] |
分K 表漏傳 minutes |
分K 的參數規則不一致,有的要 minutes 有的不要,見 intraday.md |
KeyError: 'symbol' |
看起來像少傳 symbol,其實是 產業個股清單 的 sector 值不合法 |
sector 要填 台股產業對照表 的 指數彙編分類(172 種),'半導體' 不在其中 |
KeyError: '內盤' |
內外盤的欄名是簡體 内盤 |
用 df['内盤'] |
IndexError: positional indexers are out-of-bounds |
代號不存在(例如 '999999') |
先用 上市櫃/ETF清單(含當沖限制) 或 MSMP.INFO 確認代號 |
矩陣資料(api.MSMP / api.USMSMP)
| 訊息 | 原因 | 怎麼修 |
|---|---|---|
AttributeError: '_融資券' object has no attribute '融資餘額' |
欄名打錯。融資券的欄名帶單位:融資餘額_張、融券餘額_張 |
查 msmp-tables.md 的完整欄位清單 |
AttributeError: '_MSMP' object has no attribute '日_不存在' |
表名打錯 | 台股 25 張、美股 10 張,見 msmp-tables.md |
ValueError: cannot reindex on an axis with duplicate labels |
MSMP.list['all'] 含一個重複代號('7834'),拿它當 DataFrame 的 columns |
list(dict.fromkeys(api.MSMP.list['all'])) 先去重。用 isin() 篩不受影響 |
回測(api.bt)
| 訊息 | 原因 | 怎麼修 |
|---|---|---|
RuntimeError: 還沒有任何 K 棒就下單了 (self.row 是空的)。Condition.Global 只能在 on_bar / on_intrabar / on_position 裡呼叫,on_init 只用來初始化參數。 |
在 on_init 裡下單 |
on_init 只放參數與狀態容器 |
RuntimeError: make_daily: 每日損益全為 0,無法產生報表。…常見原因是 pandas / numpy 版本不相容… |
訊息會誤導。 實務上最常見的原因是資金不夠買一個單位,部位全被 floor 夾成 0 張 |
提高 capital、減少檔數,或改用單價低的標的。台股一張 1000 股 |
AttributeError: 'generate_report' object has no attribute 'trade' |
沒有 rp.trade 這個屬性 |
逐筆交易在 rp.trade_detail |
不報錯,但結果是錯的
這一節最重要。 下面每一項都不會拋例外,只會給你錯的答案。
| 症狀 | 為什麼 | 怎麼發現/避免 |
|---|---|---|
| 選股 0 檔,想知道是條件嚴格還是積木壞了 | 兩者的 dataframe 都是 (0, 0),分不出來 |
看 r['sig'].shape 的欄數:正常是 (1000, 2866)(只是當日沒人通過);(1000, 0) 才是積木有問題。目前全部 659 個積木都沒有這個問題(v24 那個已修),這條是留給日後的診斷法 |
| 檔數跟預期差很多 | 積木名稱與實際邏輯不符。例如 漲跌幅介於P1%到P2%之間 算的是近 20 日漲跌幅,不是當日 |
print(r['code']) 看它實際算什麼。積木名稱不是規格,code 才是 |
其他_大盤 除個股矩陣得到空的 |
其他_大盤 的 columns 是 29 個法人分類,不是股票代號 |
算佔比要用個股自己加總:df.div(df.sum(axis=1), axis=0) |
改 capital 完全沒反應 |
固定口數(qty >= 1)下單時走向量化路徑,capital 不參與計算 |
要資金池生效,qty 填 0~1 的比例。見 backtest-report.md |
| 回測成本高得離譜 | 證交稅被收了兩次 | 台股只填 tax_short=0.003,tax_long 留 0(預設就是 0)。tax_long 乘的是進場價、tax_short 乘出場價,台股買進不課證交稅 |
| 名目金額差 1000 倍 | 明確把 unit 設成 1000(以張計)之後又用 qty = 金額/price,qty 被當成張數 |
unit 預設就是 1(以股計),用 qty = 金額/price 不用改它。只有刻意以張計時才要把 qty 換算成張數 |
from ...data_context import msmp 拿到 None |
沒注入時安靜回 None,之後才在別處炸成 AttributeError |
走 api = so.login(person_id, person_pwd) |
| 分K 最後一根的量偏小 | 最後一根還在形成中,量還會累加 | 做訊號丟掉最後一根。K 棒用結束時間標記 |
| 月營收數字差 100 倍 | 金額_千 的單位是千元 |
÷ 1e5 得億元(_百萬 結尾則 ÷ 1e4) |
head(5) 不是「最好的 5 檔」 |
r['dataframe'] 是按代號排序的 |
要挑標的自己排序(按成交額或積木的中間值欄) |
| 美股漲幅排行全是沒聽過的代號 | 13174 檔裡有大量權證、次分錢股與反分割假象 | 加成交值門檻。美股沒有成交額欄,要 Volume × Close 自己算 |
| 台股與美股的日期對不起來 | 美股資料日通常比台股晚一天 | 各自取 index[-1],不要假設一致 |
| 「近五年」的資料只有四年 | 日頻硬上限 1000 筆(約 4.1 年) | 台股降到週/月/季頻(11~16 年)。美股不行,週月 K 也只有 4 年——長歷史只在財報與股利。見 data-history.md |
相關頁
- Block 已知落差與注意事項:12 節,積木層的完整落差清單
- 資料頻率與歷史長度:各頻率能回溯多久
- 回測:商品規格與績效報告:成本與部位大小的設定
- 盤中、分K與逐筆明細:盤中資料的用途界線