Files
sanguo_vnpy_v2/sanguo_factor/fundamental_adapter.py
T
2026-09-10 07:18:28 +08:00

113 lines
4.2 KiB
Python
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.
# sanguo_factor/fundamental_adapter.py
"""财务因子适配层: NAS 静态域三表+forecast parquet → PIT 日频特征列.
口径红线(docs/fundamental_factor_survey_20260907.md §7):
- R1 单季差分: Q1 直接取累计,其余 = 本期累计 − 年内上期累计;缺上期置 NaN 不填 0
- R2 TTM: 连续 4 个单季之和,不足 4 期 NaN
- R3 PIT: NOTICE_DATE ≤ 决策日才可见(有效披露日 = 三表 NOTICE_DATE 最大值,保守);
NOTICE_DATE 缺失的报告期整期跳过(宁缺毋假)
- 金融股(OPERATE_COST 缺失/为 0 的银行模板): 盈利质量/成长族特征置 NaN(估值族保留)
数据形态(NAS 实测 2026-09-07):
- 三表按股: static/{income,balance,cashflow}/{code}.{SH|SZ}_{table}.parquet
(北交 920xxx 残留零行文件、沪深退市 355 只文件不存在 → 读取容错跳过)
- forecast 按报告期全市场: static/forecast/{YYYYMMDD}_forecast.parquet(中文列,
一股多行=按「预测指标」,归母净利润行优先)
- 日期列为 "YYYY-MM-DD 00:00:00" 字符串;东财金额单位=元
- valuation(中文列)不读: 估值类因子市值 = close × SHARE_CAPITAL 自算(表达式层)
P1-B 四新域(NAS 实测 2026-09-08):
- dividend 按股: static/dividend/{code}.{SH|SZ}_dividend.parquet;code 列为
baostock 小写格式(sh.600519)与文件名不同 → 以文件名路由;日期/数值列为
字符串('' 为空);一行=一次分红事件,同年可多行
- gdhs 按期: static/gdhs/{YYYYMMDD}_gdhs.parquet(53 期 2013Q1→2026Q1);
用 代码/股东户数-本次/股东户数统计截止日-本次/公告日期 四列(实测列名
无第二连字符;噪声行情快照列不读)
- top_holders: 只读聚合产物 factor_cache/top_holders_agg.parquet(static
兄弟目录;由 scripts/factor_research/preaggregate_top_holders.py 一次性
预聚合 108,610 个按股×期小文件)
- valuation_baostock 按年: data/valuation_baostock/{year}.parquet(static
兄弟目录);date 为字符串,exchange 实测为 SH/SZ(映射回 SSE/SZSE);
2026 文件仅 08-13 起(bs 日喂起点)→ 01-01~08-12
缺口用 static/valuation(ak em 中文列 PE(TTM)/市净率)倒数补
- 四域缺任一 → 相关特征列全 NaN + 一次性 warning(优雅降级,本地可跑通)
输出: vt_symbol × datetime(日频) × FEATURE_COLUMNS,join 到 alpha_df 后
供 cs_rank(列) 表达式直接消费。
模块拆分(2026-09-10,纯结构重构零行为变化): 本文件保留为门面,re-export
全部原模块级名字(引用方与测试零改动),实现按数据域拆为:
- fundamental_schema.py 常量/列契约(FEATURE_COLUMNS 等)
- fundamental_statements.py 三表读取层(报告期宽表)
- fundamental_report_features.py 报告期级指标预计算(单季化/TTM/比率族)
- fundamental_forecast.py 业绩预告事件层
- fundamental_domains.py P1-B 四新域事件层
- fundamental_pit.py PIT 对齐 + 分块 join 主入口
"""
from __future__ import annotations
from .fundamental_schema import ( # noqa: F401
FEATURE_COLUMNS,
FORECAST_TYPE_SCORE,
DEFAULT_STATIC_DIR,
_BALANCE_COLS,
_BEAT_COLS,
_CUM_MAP,
_DA_PARTS,
_DATE_COLS,
_DOMAIN_COLS,
_FIN_NULL_COLS,
_FORECAST_COLS,
_IBD_PARTS,
_SYM,
_VT_TO_FILE_SUFFIX,
)
from .fundamental_statements import ( # noqa: F401
_TABLE_RAW,
_dedupe_reports,
_load_statements,
_norm_dates,
_read_static,
_vt_to_file_code,
)
from .fundamental_report_features import ( # noqa: F401
_cagr5,
_compute_report_features,
_delta4,
_mean4,
_qidx,
_safe_ratio,
_single_quarter,
_std16,
_ttm_of,
_yoy4,
)
from .fundamental_forecast import ( # noqa: F401
_ANNUALIZE_FACTOR,
_load_forecast_events,
)
from .fundamental_domains import ( # noqa: F401
_DIVIDEND_CHAIN,
_EMPTY_EVENTS,
_GDHS_CUTOFF_CANDIDATES,
_VB_GAP,
_code6_to_vt,
_inv_guard,
_load_dividend_cum,
_load_extra_domains,
_load_gdhs_events,
_load_topholder_events,
_load_vb_daily,
_missing_warned,
_warn_domain_missing,
)
from .fundamental_pit import ( # noqa: F401
BATCH_CODES,
_build_beat_events,
_build_grid,
_load_feature_events,
_prepare_days,
build_fundamental_features,
iter_fundamental_feature_chunks,
)