0f8a97a219
R 研报共识族(PIT=publishDate,180 天窗两端 cum 口径同 E11 手法):
- res_rating_pos 窗内买入+增持占比(emRatingName 正面集={买入,增持,推荐,强推,强买}),
覆盖门窗内研报<3 条→NaN 稀样本失真宁缺毋假
- res_coverage 窗内研报条数(首研报前 NaN=未覆盖,曾覆盖后窗空=0 值两语义区分)
- res_fwd_ep 窗内 mean 预测 EPS/predictThisYearEps(空值不算分母;当年口径,
跨年跳变由截面同年份对齐吸收)
- res_target_upside 最新带目标价条目+180 天新鲜度门——indvAimPriceT null 条目
不进 target 流→不遮蔽上一份带价研报(join_asof 保留 eff 算 datetime−eff≤180)
- res_rating_chg 窗内净上调次数(ratingChange='上调'−'下调';EM 空值已统一转 None)
Q 质押族(无质押=0 真实零,fill 语义与缺域 NaN 严格区分):
- pledge_ratio 周五快照 asof backward(akshare 中文列,质押比例=总股本口径%)
- pledge_ctrl 实控人在押 max 占所持——pledge_detail 月桶区间重建:生效开始=
max(PF_START_DATE,NOTICE_DATE) 公告日才可见宁晚毋早;结束=UNFREEZE_DATE
(EM 无解押公告日列,假设解押日≈公告日);IS_CONTROL_SHAREHOLDER=='1' 白捡
直标免 F10 actual_controller join;断点稀疏流=每股在押集合变化时刻聚合
max(PF_HOLD_RATIO),断点间值恒定 join_asof 填格子
- pledge_margin_dist=−pledge_warn_line/close(在押最高预估平仓线占现价,
低=安全垫厚;无在押 fill 0→0 值=最优档天然参与截面)
- pledge_net_180 窗内解押−新增笔数(生效开始=−1/解押=+1 两事件 cum 两端差);
MXID 跨月桶去重取最新桶状态(文件名升序 unique keep last)
- 区间重建 1997 全史留存→全窗可回测,非前向积累(与 S 族对照)
工程: conftest 扩三新域合成树(周窗文件+周五快照+月桶断点/解押/PIT notice
晚 start 用例);计数列聚合即 cast Int64(u32 环回坑 P2 实锤先例延续);
FEATURE_COLUMNS+9 列/_DOMAIN_COLS 扩;既有计数断言 80→89;新增 16 用例,
全套 1458 绿;设计档 §3 表同步 P1-C 行 [nas]
Co-Authored-By: Claude Code <noreply@anthropic.com>
154 lines
9.2 KiB
Python
154 lines
9.2 KiB
Python
# sanguo_factor/fundamental_schema.py
|
||
"""财务因子适配层常量/列契约(自 fundamental_adapter.py 拆出,纯结构重构).
|
||
|
||
口径红线与数据形态的完整说明见 fundamental_adapter.py 模块 docstring;
|
||
本模块只承载各数据域共享的列映射/清单常量,被读取层/特征层/PIT 层共同引用.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
DEFAULT_STATIC_DIR = "/volume1/stock/sanguo_vnpy_v2/data/static"
|
||
_SYM = "vt_symbol" # 时序分组键
|
||
|
||
# vt_symbol 后缀 → NAS 文件名后缀(600000.SSE → 600000.SH)
|
||
_VT_TO_FILE_SUFFIX = {"SSE": "SH", "SZSE": "SZ"}
|
||
|
||
# forecast 预告类型 → 有序分(§3.6 F04)
|
||
FORECAST_TYPE_SCORE: dict[str, int] = {
|
||
"预增": 3, "略增": 2, "扭亏": 2, "续盈": 1, "减亏": 1, "不确定": 0,
|
||
"略减": -1, "增亏": -2, "续亏": -2, "预减": -3, "首亏": -3,
|
||
}
|
||
|
||
# 累计口径列映射: 源列 → 短名(需单季化+TTM)
|
||
_CUM_MAP = {
|
||
"TOTAL_OPERATE_INCOME": "rev",
|
||
"OPERATE_COST": "cogs",
|
||
"PARENT_NETPROFIT": "np",
|
||
"DEDUCT_PARENT_NETPROFIT": "dnp",
|
||
"TOTAL_PROFIT": "tp",
|
||
"INVEST_INCOME": "invest_inc",
|
||
"FAIRVALUE_CHANGE_INCOME": "fv_inc",
|
||
"ASSET_IMPAIRMENT_LOSS": "asset_imp",
|
||
"CREDIT_IMPAIRMENT_LOSS": "credit_imp",
|
||
"NETCASH_OPERATE": "cfo",
|
||
"SALES_SERVICES": "sales_cash",
|
||
"ACCEPT_INVEST_CASH": "acc_inv_cash",
|
||
# ---- P1 批新增(income;NAS 实测 2026-09-08 列名核实)----
|
||
"RESEARCH_EXPENSE": "research", # 研发费用(2018Q3 起单列,早年 null 传播)
|
||
"SALE_EXPENSE": "sale_exp", # 销售费用
|
||
"FE_INTEREST_EXPENSE": "int_exp", # 财务费用-利息费用(披露稀疏,EBIT 组装层按 0)
|
||
"INCOME_TAX": "tax", # 所得税费用(τ 实际税率分子)
|
||
"BASIC_EPS": "eps", # 基本每股收益(累计口径,需单季化)
|
||
# ---- P1 批新增(cashflow 补充资料段 + 融资流)----
|
||
"FA_IR_DEPR": "fa_depr", # 固定资产折旧
|
||
"IA_AMORTIZE": "ia_amort", # 无形资产摊销
|
||
"LPE_AMORTIZE": "lpe_amort", # 长期待摊费用摊销
|
||
"USERIGHT_ASSET_AMORTIZE": "ua_amort", # 使用权资产折旧摊销(2019 起才有)
|
||
"CONSTRUCT_LONG_ASSET": "capex", # 购建长期资产现金(C17 投资率/D15 FCF)
|
||
"RECEIVE_LOAN_CASH": "recv_loan", # 取得借款现金(E03)
|
||
"ISSUE_BOND": "issue_bond", # 发行债券现金(E03)
|
||
"PAY_DEBT_CASH": "pay_debt", # 偿还债务现金(E03)
|
||
}
|
||
# 存量列(balance,时点值直接用;缺列 → null)
|
||
_BALANCE_COLS = ["TOTAL_ASSETS", "TOTAL_PARENT_EQUITY", "ACCOUNTS_RECE",
|
||
"OTHER_RECE", "GOODWILL", "SHARE_CAPITAL", "SHORT_LOAN",
|
||
"SHORT_FIN_PAYABLE", "NONCURRENT_LIAB_1YEAR", "LONG_LOAN",
|
||
"BOND_PAYABLE", "LEASE_LIAB",
|
||
# P1 新增存量列
|
||
"INVENTORY", "MONETARYFUNDS",
|
||
# P1-B 新增存量列(E08 CCC 分子: 应付账款,NAS 实测列名核实)
|
||
"ACCOUNTS_PAYABLE"]
|
||
# IBD 口径钉死含 LEASE_LIAB 版(survey §3.5 E 族注意点「定稿钉死」;2019 前该列
|
||
# 整体缺失按 0,与一年内到期非流动负债等组件同款处理)
|
||
_IBD_PARTS = ["SHORT_LOAN", "SHORT_FIN_PAYABLE", "NONCURRENT_LIAB_1YEAR",
|
||
"LONG_LOAN", "BOND_PAYABLE", "LEASE_LIAB"]
|
||
# DA 组装: cashflow 间接法补充资料四件,列/值缺失按 0(「列存在才加」;
|
||
# USERIGHT_ASSET_AMORTIZE 2019 前整列缺失不影响早年 DA)
|
||
_DA_PARTS = ["fa_depr", "ia_amort", "lpe_amort", "ua_amort"]
|
||
_DATE_COLS = ["REPORT_DATE", "NOTICE_DATE", "UPDATE_DATE"]
|
||
|
||
# 输出特征列(P0 32 + P1 35 因子及 2 变体的全部原料;契约由 test_fundamental_library
|
||
# 与 test_fundamental_p1_library 锁定)
|
||
FEATURE_COLUMNS: list[str] = [
|
||
# 报告期级比率(盈利能力 A / 盈利质量 B / 成长 C / 资本结构 E / 预期事件 F)
|
||
"roe_ttm", "roe_deduct_ttm", "roa_ttm", "gp_over_assets", "gross_margin",
|
||
"net_margin", "cfo_over_assets",
|
||
"tacc", "nonrec_ratio", "impairment_ratio", "invest_income_dep",
|
||
"receivables_anomaly", "sales_cash_ratio", "other_rece_ratio",
|
||
"rev_q_yoy", "np_q_yoy", "growth_scissors", "gm_delta", "roe_delta",
|
||
"asset_growth", "nsi", "ibd_ratio", "goodwill_ratio",
|
||
"sue_np", "sue_rev",
|
||
"forecast_type_score", "forecast_change_pct",
|
||
# 估值/资本行为因子的日频原料(表达式层 ÷ close×share_capital)
|
||
"np_ttm", "dnp_ttm", "cfo_ttm", "equity", "share_capital",
|
||
"acc_invest_cash_ttm",
|
||
# ---- P1 批新增(A 盈利 7)----
|
||
"roe_avg", "roa_pretax", "ebit_over_assets", "ebitda_margin", "roic",
|
||
"rd_intensity", "sale_expense_ratio",
|
||
# ---- P1 批新增(B 质量 8;B12 为哑变量的连续近似乘积)----
|
||
"inventory_anomaly", "cash_ibd_product", "vsig", "vsig_acc", "vsig_cfo",
|
||
"da_intensity", "gm_nm_scissors", "profit_streak",
|
||
# ---- P1 批新增(C 成长 8)----
|
||
"np_accel", "rev_accel", "nm_delta", "rev_cagr5", "np_cagr5",
|
||
"nwc_growth", "invest_growth", "equity_growth",
|
||
# ---- P1 批新增(D 估值 6 的原料;EV = close×share_capital + ev_ex_mv;
|
||
# forecast_np_annualized 走 forecast 事件流公告日 asof)----
|
||
"ebit_ttm", "ebitda_ttm", "fcf_ttm", "gp_ttm", "ev_ex_mv",
|
||
"forecast_np_annualized",
|
||
# ---- P1 批新增(E 资本 3)----
|
||
"debt_issue_ttm", "interest_cover", "goodwill_growth",
|
||
# ---- P1 批新增(F 预期 3 + SUE 严窗变体;forecast_beat 走独立兑现差事件流)----
|
||
"sue_eps", "disclosure_speed", "sue_np_strict", "forecast_beat",
|
||
# ---- P1-B 批新增(四新域 5 因子;契约由 test_fundamental_p1b_* 锁定)----
|
||
"ccc", # E08 三表自算现金转换周期
|
||
"send_total_12m", # E11 dividend 事件流(365 天滚动合计)
|
||
"gdhs_chg", # E12 股东户数相邻事件 Δln
|
||
"topholder_chg", # E13 十大流通占比相邻期 Δ(聚合产物)
|
||
"ep_vb", "bp_vb", # D14 长史 EP/BP(vb 日频域)
|
||
# ---- P2 批新增(七项目指标调研增量: D 估值 2 + E 股息 3;契约由
|
||
# test_fundamental_p2_* 锁定)----
|
||
"np_ttm_yoy", # D16 PEG 原料: TTM 净利同比(_yoy4 ttm 口径)
|
||
"rev_ttm", # D17 PS 原料: 营收 TTM
|
||
"peg_denom", # D16 PEG 分母 = np_ttm×g(守卫 np_ttm>0 且 g>1%)
|
||
"div_12m", # E14 股息率分子: 近365天现金分红/股(除息日锚)
|
||
"div_payout", # E15 派息率(np_ttm>0 守卫,pit 层后算)
|
||
"div_streak", # E16 连续现金分红年数(断年重计)
|
||
# ---- P1-C 批新增(spec §20.13 三新域: 研报共识 5 + 质押 4;契约由
|
||
# test_fundamental_p1c_* 锁定)----
|
||
"res_coverage", # R01 原料: 180 天窗研报条数(publishDate 锚两端 cum)
|
||
"res_rating_pos", # R02 原料: 窗内买入+增持占比(门 n≥3)
|
||
"res_fwd_eps", # R03 原料: 窗内 mean 预测 EPS(空值不算分母)
|
||
"res_target_price", # R04 原料: 最新可见目标价(180 天新鲜度门)
|
||
"res_rating_chg", # R05 原料: 窗内净上调次数(上调−下调)
|
||
"pledge_ratio", # Q01 原料: 总股本质押比例%(周五快照 asof,无=0)
|
||
"pledge_ctrl", # Q02 原料: 实控人在押 max 占所持%(区间重建)
|
||
"pledge_warn_line", # Q03 原料: 在押最高预估平仓线价(无在押=0)
|
||
"pledge_net_180", # Q04 原料: 180 天窗解押−新增笔数(无=0)
|
||
]
|
||
# 金融股置 NaN 的特征(盈利质量 B 族 + 成长 C 族 + 费用类,§7 红线 5;
|
||
# survey A 族注意点: A14/A16 金融无三费结构 → rd/sale_expense_ratio 同剔)
|
||
_FIN_NULL_COLS = ["tacc", "nonrec_ratio", "impairment_ratio",
|
||
"invest_income_dep", "receivables_anomaly",
|
||
"sales_cash_ratio", "other_rece_ratio",
|
||
"rev_q_yoy", "np_q_yoy", "growth_scissors", "gm_delta",
|
||
"roe_delta", "asset_growth",
|
||
"rd_intensity", "sale_expense_ratio",
|
||
"inventory_anomaly", "cash_ibd_product", "vsig", "vsig_acc",
|
||
"vsig_cfo", "da_intensity", "gm_nm_scissors", "profit_streak",
|
||
"np_accel", "rev_accel", "nm_delta", "rev_cagr5", "np_cagr5",
|
||
"nwc_growth", "invest_growth", "equity_growth",
|
||
# P1-B: E08 CCC 属营运效率,金融股无 CCC 概念(§7 红线扩展)
|
||
"ccc"]
|
||
# forecast 事件流日频列(公告日 asof): P0 两列 + P1 年化预告净利(D13)
|
||
_FORECAST_COLS = ("forecast_type_score", "forecast_change_pct",
|
||
"forecast_np_annualized")
|
||
# 预告兑现差独立事件流(F07 前视红线: 锚 = max(实际披露日, 预告公告日))
|
||
_BEAT_COLS = ("forecast_beat",)
|
||
# P1-B 四新域列(非报告期特征,由各域事件/日频流产出;报表加载须排除)
|
||
# P2 股息三列(dividend 域除息日锚事件流,pit 层产出)同属域列;
|
||
# P1-C 研报共识 5 + 质押 4(三新域事件/快照流)同属域列
|
||
_DOMAIN_COLS = ("send_total_12m", "gdhs_chg", "topholder_chg", "ep_vb", "bp_vb",
|
||
"div_12m", "div_payout", "div_streak",
|
||
"res_coverage", "res_rating_pos", "res_fwd_eps",
|
||
"res_target_price", "res_rating_chg",
|
||
"pledge_ratio", "pledge_ctrl", "pledge_warn_line", "pledge_net_180")
|