AETF report_data:持股、每日異動、逐股合計
適用 aetf-v8~aetf-v14。v12 將官方交易日 anchor、最後有效持股日與績效窗口完全分離,並增加持股新鮮度及績效日期;v13 排除台北今天尚未到共用資料時間的 session,不變更資料結構;v14 調整機械正文的日數去重、零/未知與自然時間文案並更新快取版本,report_data payload 不變。這是 core/mas/aetf_report_data.py 的 build_aetf_llm_payload(facts) 產生的報告專用資料,不是公開 API 的完整 facts。公開 request/response 外層 shape 保留;後端提供股數可判定性及日期證據,供 serializer 區分零與未知。user prompt 僅包含此 JSON,沒有預先寫好的報告或結論。
三組主要資料:
current_holdings:目前持股明細,每檔一筆。daily_changes:依官方交易日列出有變動個股及股數/估值,保留無異動日、缺日與必要例外,供理解調整順序。stock_summary:每檔股票分別累計各日的增持、減持與淨變化,包含 5 日及 20 日各一組合計,供比較累計規模。完整且無異動的個股也提供零值合計;已退出個股仍保留歷史變動與合計。
另外附 ETF 身分、日期、分析範圍、共通語意及 ETF 績效。所有股票保留,不裁切成固定前幾名。最新一日異動在 daily_changes 最後一天,不再另複製一份 today summary。舊送模欄位 daily_trades/summary 改名僅限報告 serializer,不重新命名公開 facts 的 daily_intervals/stock_changes。
結構與欄位語意
? 表示條件出現,number | null 表示不能算時保持未知;省略不是零。
report_data
etf: { ticker: string, name: string, market: "taiwan" }
requested_date, anchor_date: ISO date
holdings_as_of: ISO date | null
holdings_freshness: {
status: "current" | "stale" | "unknown",
anchor_date: ISO date,
holdings_as_of: ISO date | null,
lag_session_count: nonnegative integer | null
}
scope: { included: "identified_TW_TWO_stocks", covers_entire_fund: boolean | null }
semantics: {
shares_unit: "股", amount_currency: "TWD",
performance: { basis: "raw_close_price_return", is_nav: false, is_total_return: false },
buys_sells, estimated_amount, period_boundary, overlap, zero_null,
data_status, empty_day, stock_period, days_streak: string
}
periods: { today, five_day, twenty_day: Period }
performance: { today, five_day, twenty_day: Performance }
current_holdings: [Holding]
daily_changes: [Day]
stock_summary: [StockSummary]
Holding
ticker, name: string
shares, weight_pct: number | null
status?: "partial" # 只在股數/身份品質不完整時出現
Day
date: ISO date # 該次相鄰快照比較的期末交易日
data_status: "complete" | "partial" | "unavailable"
buys, sells: [Change]
reasons?: [string]
all_stocks_unknown?: true # 該日全體股數變動無法確認
unknown_tickers?: [string] # 僅指定個股股數變動無法確認
exceptions?: [{ ticker, name, reason: string, weight_change_pct?: number }]
Change
ticker, name: string
shares: positive number
estimated_amount: nonnegative number | null
position_change?: "added" | "removed"
StockSummary
ticker, name: string
five_day: StockPeriod
twenty_day: StockPeriod
Totals # 已確認範圍的合計;無操作時為零
buy_shares, sell_shares: nonnegative number
net_shares: number
estimated_buy_amount, estimated_sell_amount: nonnegative number | null
estimated_net_amount: number | null
buy_days, sell_days: nonnegative integer
StockPeriod
Totals 的全部欄位 # 不完整期間時全部為 null
status?: "partial" | "unavailable" # 省略表示 complete
unknown_days?: nonnegative integer
confirmed_subintervals?: Totals # 僅已確認區間的合計,不代表完整期間
ending_streak: EndingStreak | null
position_change?: "added" | "removed"
latest_reversal?: "to_increase" | "to_decrease"
weight_change_pct?: number
EndingStreak
{ direction: "increase" | "decrease", days: positive integer }
或 { direction: "none", days: 0 }
Period
start_date, end_date: ISO date
interval_count: 1 | 5 | 20
data_status: "complete" | "partial" | "unavailable"
missing_dates?: [ISO date]
Performance
baseline_date, end_date: ISO date
return_pct: number | null
status: "complete" | "partial" | "unavailable"
has_ex_dividend, has_other_corporate_action: boolean | null
範圍、期間與品質
scope.included指可識別的台灣上市/上櫃股票。covers_entire_fund=false表示有範圍外資產;true僅在快照完整且未發現範圍外資產時成立;不足以判定為null。這不是個股資料完整度。periods.*.data_status指指定範圍內股數變動是否足以判定。排除現金、非股票或海外部位本身不使範圍內股票降級;缺快照、股數/識別/公司行動證據不足才限制判讀。缺個股價格不否定已確認股數,改以金額null及missing_price例外揭露。start_date是基準快照日,累計嚴格使用start_date < daily_changes.date <= end_date。interval_count是官方交易區間數,不是日曆天數,也不表示實際資料已齊全;完整度另看data_status。anchor_date是 requested date 當日或以前最近的合格官方交易日;僅 requested date 等於台北今天且現在早於共用DAILY_STOCK_UPDATE_TIME(15:30)時排除今天,15:30 起納入。歷史請求不受今天時間影響;週末/休市不額外退一個 session。holdings_as_of是最後一個success、非空且列數相符的持股快照日。periods的 2/6/21 個快照日結束於holdings_as_of,不會被較新的績效日期拉動。holdings_freshness.lag_session_count是(holdings_as_of, anchor_date]之間的官方交易日數,不是日曆天數。同日為 0;週末/休市的 requested date 不額外增加 lag。無法驗證時為unknown/lag 為null,不猜測或當成 0。- 例如近 5 日基準日為
2026-10-05時,不包含2026-10-05當日的異動。缺日仍保留在完整官方交易日序列,不能跳過後續接成連續。 - 每日
all_stocks_unknown=true表示該日所有個股都不能用空清單推論零;局部不足則以unknown_tickers指出受影響個股。exceptions補充已知具體原因或僅權重變化;正常資料不逐筆重複警語。
零、未知與連續日數
buys/sells是快照股數增減,不是成交紀錄,可能包含申贖。股數一律正值,方向由清單決定;net_shares = buy_shares - sell_shares。daily_changes與stock_summary來自同一份已標準化變動;彙總直接累加明細中的股數、估值與操作日數,不重新定價。逐日估值是股數差乘同日未還原收盤價;兩側各自為正值,淨額為增持減減持。缺個股價格時保留股數,沿用該股期間估值全有或未知的口徑:任一變動缺價,該期間三個估值合計都為null。0是可確認的零;null是未知或不可計算。淨零但正負兩邊不為零,表示有操作而相抵。- 每日
buys=[]、sells=[]只有在data_status=complete且無例外時,才表示範圍內確認無異動。 - 已確認整段無異動的個股提供零值 Totals;沒出現 action 並非足夠證據。某個期間未提供,預設不能解讀成無異動。
- 整體「確認未見持股股數變化」還要求
stock_summary至少有一檔可分析股票。最新一日須同時是完整daily_changes、無 unknown/exception,且buys/sells皆空;近 5/20 日則要求每檔對應期間的buy_shares/sell_shares都是明確的0。空stock_summary表示缺少可分析的台股持股,不能用空集合宣稱無異動。 buy_days/sell_days是期間內有增減持的交易日數;ending_streak才是該期間截至最新一日的連續區間數。最後一天確認無異動為none/0,可確認連續增減持為方向/正整數,無法確認為null。無異動日中斷連續;缺漏不能跨越,若缺漏讓連續長度不確定則保留未知。- 無
status的 StockPeriod 表示該股票完整期間合計。partial/unavailable時,八個完整期間合計欄位全部為null;有已確認區間才提供confirmed_subintervals,不得稱完整期間結果。即使全窗口有其他個股例外,完整個股仍可保有完整合計。 - 只有權重變化不推論股數,留在例外或
weight_change_pct。新增/退出只由後端已驗證事件提供,不能由淨股數正負或權重推論;weight_pct=0不代表shares=0。 - 每日明細與期間合計是同一批變動的不同呈現,不能重複相加;5 日又包含於 20 日內,兩期間也不能相加。
績效與 prompt 使用
performance.*.return_pct 使用未還原收盤價漲跌;共通 semantics.performance.basis=raw_close_price_return,非 NAV、非含息總報酬。績效獨立使用結束於 official anchor_date 的 2/6/21 個官方交易日,不回退到舊持股日;每期的 baseline_date、end_date 直接保留在 performance 物件。指定日價格缺失時回 partial|unavailable 與 null,不改用其他日價格。公司行動旗標為三態:true 有已知事件,false 僅在相應覆蓋完整且無事件時成立,缺覆蓋為 null。
prompt 保留三段、約 250~400 字與精簡寫作要求;current_holdings 用於理解目前部位,daily_changes 用於理解調整順序而非逐日流水帳,stock_summary 用於引用期間累計與比較規模。連續操作以 ending_streak 為準,正文寫「截至最新一日」;只有近 20 日完整方向證據支持的位置比較才寫「20 個交易日前」。完整度與缺值限制判讀,只有實質影響主要結論時才用白話寫入正文。
實際樣本與驗證
實際樣本使用已保存的唯讀來源 source-00981A-2026-10-13.json.gz:主動統一台股增長(00981A.TW),21 個官方交易日,2026-09-10 至 2026-10-13。資料不代表目前即時持股。
task worktree 的 .codex/aetf-actual-llm-input-00981A-2026-10-13.txt 是可整份貼給 LLM 的 prompt+JSON;同名 aetf-actual-llm-data-…json 為展開格式資料;request manifest 記錄實際生成呼叫邊界、來源 hash 與筆數。擷取不呼叫 provider、不存取 DB。
驗證入口為 test_aetf_agent.py 與 test_aetf_agent_real_fixture.py:從原始快照及同日價格核對每日與逐股合計,並檢查基準日排除、零與未知、正負相抵、無異動/缺日中斷、範圍排除及零權重持股。實際執行結果與完整生成樣本以本次 task evidence 為準;本文件不宣稱尚未執行的測試通過。