akg-factor-bridge/sql/astock_kg_slot_views.sql

109 lines
6.0 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ============================================================================
-- astock-kg 因子插槽接口:只读视图 v2供 akg-factor-bridge 消费)
-- ----------------------------------------------------------------------------
-- 相对 v1 的变更2026-07-26 评审):
-- ① v_factor_transmissionn_paths → n_sourcesdistinct 源数),修「变长边每种
-- 长度各返回一条 + 三桶间不去重」导致的路径重复计数n_paths_raw 保留作观察。
-- ② v_factor_transmission暴露 target / target_type / members_total / moved /
-- mkt_trade_date让桥能自检上游截断与快照新鲜度。
-- ③ v_factor_events补 doc_id / source_type / tier供年报污染防护
-- ④ v_factor_universe / v_factor_consensus 逻辑未变,只补注释。
--
-- 应用docker exec -i akg-postgres psql -U akg -d akg < sql/astock_kg_slot_views.sql
-- 幂等:全部 CREATE OR REPLACE。
--
-- ★ 数据安全性:本文件**只创建视图 + 加列 + 加索引**,不写、不改、不删任何一行数据。
-- claims / documents 一个字节都不动,之前抽取的成果全部保留,无需 replay、无需重抽。
-- 唯一的 DDL 变更是 transmission_candidates 加一个可空列(见文件末尾 ALTER 段),
-- 已存行取值 NULL桥侧按 NULL 容忍(见 factors.build_transmission
-- ============================================================================
-- 0) 覆盖池 universe = 全部 industry_pools 成员 ts_code 并集
-- ⚠️ 注意(评审 §4industry_pools 只存最新态、每周一 refresh_pools 自动长大。
-- 本视图是「当前态」,用它过滤历史子因子会引入成员性前视。
-- 子因子表建议不过此过滤(桥侧 SUBFACTOR_UNIVERSE=market只在 akg_score 侧用。
CREATE OR REPLACE VIEW v_factor_universe AS
SELECT DISTINCT m->>'ts_code' AS ts_code
FROM industry_pools p
CROSS JOIN LATERAL jsonb_array_elements(COALESCE(p.members, '[]'::jsonb)) AS m
WHERE m->>'ts_code' IS NOT NULL AND m->>'ts_code' <> '';
-- 1) 一致预期(供 upsideconsensus_daily 全 asof 行投影,桥按 trade_date 做 as-of。
-- n_orgs / n_reports_90d 一并给出——可作 upside 的可信度权重(当前桥未用)。
CREATE OR REPLACE VIEW v_factor_consensus AS
SELECT ts_code,
asof_date,
target_mid_avg,
eps_med,
np_med,
n_orgs,
n_reports_90d
FROM consensus_daily
WHERE target_mid_avg IS NOT NULL;
-- 2) 利好利空事件(供 eventEVENT 断言投影。
-- 评审 §6.5:补 doc_id + source_type。年报也带 company_ts_code 锚,而一份年报能抽
-- 十几条 EVENT且含**历史**诉讼/处罚),桥侧必须按来源过滤或封顶,
-- 否则 S2 的负面否决闸会因一份年报否决掉一只好股。
-- ✅ 列名已核实db/postgres/init.sql:12documents.source_type取值
-- annual_report / research_report / announcement / news / interactive_qa
-- 另补 tierfact/opinion/market—— 桥侧若想只信事实层事件,这里就够用。
CREATE OR REPLACE VIEW v_factor_events AS
SELECT d.meta->>'company_ts_code' AS ts_code,
c.disclosure_date,
c.qualifiers->>'event_type' AS event_type,
c.qualifiers->>'direction' AS direction,
c.qualifiers->>'scope' AS scope,
c.confidence,
c.tier,
c.dedup_key,
c.doc_id, -- 供「单文档封顶」用
d.source_type -- 供「只取公告」用
FROM claims c
JOIN documents d ON d.doc_id = c.doc_id
WHERE c.predicate = 'EVENT'
AND d.meta->>'company_ts_code' IS NOT NULL;
-- 3) 板块传导(供 transmissiontransmission_candidates 的未动成员(quiet)摊平。
-- ★ 核心修复n_sources = 指向该环节的 distinct 源数。
-- 原 n_paths = jsonb_array_length(paths) 是「被提及次数」——
-- cascade() 的变长边 *1..N 会把 A→B 与 A→X→B 各返回一条,
-- transmission_targets() 的 updown/supply/drives 三桶之间也不去重,
-- 于是同一 source 对同一 target 重复计入,而 n_paths 是 factor_value 的主量级。
-- 改成 distinct source 数,同时也更贴合传导模块自述的语义「多源汇聚=逻辑更硬」。
CREATE OR REPLACE VIEW v_factor_transmission AS
SELECT t.scan_date,
t.rank,
t.target,
t.target_type,
q->>'ts_code' AS ts_code,
(SELECT count(DISTINCT p->>'source')
FROM jsonb_array_elements(COALESCE(t.paths, '[]'::jsonb)) p) AS n_sources,
jsonb_array_length(COALESCE(t.paths, '[]'::jsonb)) AS n_paths_raw,
t.moved_ratio,
t.members_total, -- 桥用:== 上游 topic_context cap 时 moved_ratio 不可信
t.moved,
jsonb_array_length(COALESCE(t.quiet, '[]'::jsonb)) AS n_quiet_stored,
t.mkt_trade_date -- 桥用:≠ scan_date 说明用了陈旧 movers可能为 NULL
FROM transmission_candidates t
CROSS JOIN LATERAL jsonb_array_elements(COALESCE(t.quiet, '[]'::jsonb)) AS q
WHERE q->>'ts_code' IS NOT NULL AND q->>'ts_code' <> '';
-- ============================================================================
-- 前置 ALTER幂等可反复跑
-- ----------------------------------------------------------------------------
-- mkt_trade_date记录本次扫描实际用到的 mkt_daily stock 快照日。
-- 动因(评审 §6.2hotspot._latest_mkt 用 `max(trade_date) FROM mkt_daily`
-- 不是 scan_date 的快照。17:30 sync_market 晚点时18:15 的传导扫描会用 T1 的
-- movers 写成 scan_date=T桥完全无从察觉。落这一列后桥可以自检并拒收。
-- ============================================================================
ALTER TABLE transmission_candidates
ADD COLUMN IF NOT EXISTS mkt_trade_date DATE;
-- 便于按环节回查与审计
CREATE INDEX IF NOT EXISTS idx_tc_target ON transmission_candidates (target, scan_date);