区间型财务数据与企业风险识别 — 交互报告

项目: interval-financial-risk | 随机种子: 202608

合成数据演示 · 结果用于检验研究流程,不代表真实企业风险识别能力。

比较点特征与过去四个季度的分布特征;同一公司的未来季度进入测试集。报告期是合成季度标记,尚未证明真实财报发布日期可得性。

实验来源与评价口径

{"source": "synthetic", "rows": 4800, "companies": 300, "quarters": 16, "positive_rate": 0.12, "date_start": "2019-03-31", "date_end": "2022-12-31", "data_sha256": "75acf0ca44c06957ae6d62e2225280d2626b1304bb00d67bd36d92fd63dbd336"}

表格为各测试折指标的等权均值 ± 折间标准差;ROC/PR 图将测试预测合并,口径不同。标准差不是置信区间。分类阈值固定 0.5;PR-AUC 使用 average precision。

诊断模型由验证集平均 AUC 选择:Logistic Baseline。消融与置换重要性在最后测试折评估,属于探索性诊断。

时间验证边界

按 report_date 扩展训练窗口;预处理仅拟合训练集。验证窗口用于模型选择,测试窗口不参与该选择。

fold train_start train_end train_n train_positives validation_start validation_end validation_n validation_positives test_start test_end test_n test_positives
1 2019-03-31 2020-12-31 2400 193 2021-03-31 2021-06-30 600 94 2021-09-30 2021-12-31 600 84
2 2019-03-31 2021-06-30 3000 287 2021-09-30 2021-12-31 600 84 2022-03-31 2022-06-30 600 103
3 2019-03-31 2021-12-31 3600 371 2022-03-31 2022-06-30 600 103 2022-09-30 2022-12-31 600 102

模型对比 (滚动验证均值)

model auc pr_auc brier f1 precision recall calibration_error auc_std pr_auc_std brier_std f1_std precision_std recall_std calibration_error_std
Logistic Baseline 0.724 0.344 0.203 0.402 0.309 0.591 0.281 0.024 0.055 0.010 0.037 0.048 0.030 0.026
Logistic + Interval Features 0.686 0.310 0.218 0.363 0.268 0.580 0.282 0.034 0.057 0.020 0.045 0.048 0.029 0.037
Elastic Net + Interval Features 0.686 0.308 0.218 0.362 0.268 0.576 0.281 0.035 0.061 0.020 0.047 0.050 0.026 0.036
XGBoost 0.678 0.302 0.147 0.340 0.382 0.306 0.106 0.036 0.061 0.002 0.065 0.079 0.058 0.013
LightGBM 0.669 0.325 0.154 0.343 0.333 0.354 0.125 0.035 0.055 0.003 0.045 0.057 0.032 0.016

ROC 曲线

概率校准:预测风险与实际标签频率

Precision–Recall:与测试正例率对照

滚动验证稳定性

特征重要性

置换重要性检验

消融模型

预先固定为 Logistic + Interval Features,各消融变体重新拟合,使用同一最后测试折;这样即使点模型获胜,移除区间特征也不会变成空操作。

消融检验

标签预测区间的覆盖与宽度

名义覆盖 90% · 经验覆盖 92.2% · 平均宽度 0.965

覆盖对象是二元标签 y,不是未知真实风险概率。时间漂移与公司内相关性违反经典可交换性假设;只报告本次经验覆盖。区间很宽也可能得到高覆盖,应同时阅读宽度。

预先固定模型:Logistic + Interval Features;不按测试或校准得分挑选模型。

{"train": {"start": "2019-03-31", "end": "2021-03-31", "rows": 2700}, "calibration": {"start": "2021-06-30", "end": "2021-12-31", "rows": 900}, "test": {"start": "2022-03-31", "end": "2022-12-31", "rows": 1200}}

保形预测校准 (覆盖率有效性)

正交化关联诊断

仅控制行业;随机交叉拟合未按公司分组,OLS 标准误未做公司聚类修正。系数不构成因果效应或稳健统计显著性证据。

复现配置

生成命令:python scripts/run_experiment.py --config config/config.yaml。随附 run_manifest.json 记录依赖、数据摘要与源码哈希,predictions.csv 支持独立复算。

展开完整配置
{
  "project": {
    "name": "interval-financial-risk",
    "seed": 202608,
    "n_jobs": 1
  },
  "data": {
    "use_synthetic": true,
    "synthetic": {
      "n_companies": 300,
      "n_quarters": 16,
      "start_date": "2019-01-01",
      "freq": "QE",
      "risk_rate": 0.12
    },
    "raw_path": "data/raw",
    "processed_path": "data/processed"
  },
  "features": {
    "point_features": [
      "revenue_growth",
      "profit_margin",
      "operating_cash_flow",
      "volatility"
    ],
    "interval_features": [
      "revenue_growth",
      "profit_margin",
      "operating_cash_flow",
      "volatility"
    ],
    "interval_window": 4,
    "interval_stats": [
      "mean",
      "std",
      "min",
      "max",
      "q25",
      "q50",
      "q75",
      "skew",
      "kurt"
    ],
    "use_interval_width": true,
    "impute_strategy": "median"
  },
  "models": {
    "logistic_baseline": {
      "name": "Logistic Baseline",
      "model_type": "logistic_regression",
      "params": {
        "max_iter": 1000,
        "class_weight": "balanced"
      },
      "feature_set": "point_only",
      "optimize": false,
      "optuna_trials": 50
    },
    "logistic_interval": {
      "name": "Logistic + Interval Features",
      "model_type": "logistic_regression",
      "params": {
        "max_iter": 1000,
        "class_weight": "balanced"
      },
      "feature_set": "point_and_interval",
      "optimize": false,
      "optuna_trials": 50
    },
    "elastic_net": {
      "name": "Elastic Net + Interval Features",
      "model_type": "elastic_net",
      "params": {
        "max_iter": 5000,
        "class_weight": "balanced",
        "l1_ratio": 0.5,
        "C": 1.0
      },
      "feature_set": "point_and_interval",
      "optimize": false,
      "optuna_trials": 50
    },
    "xgboost": {
      "name": "XGBoost",
      "model_type": "xgboost",
      "params": {
        "n_estimators": 200,
        "max_depth": 4,
        "learning_rate": 0.05,
        "subsample": 0.8,
        "colsample_bytree": 0.8,
        "eval_metric": "logloss"
      },
      "feature_set": "point_and_interval",
      "optimize": false,
      "optuna_trials": 50
    },
    "lightgbm": {
      "name": "LightGBM",
      "model_type": "lightgbm",
      "params": {
        "n_estimators": 200,
        "max_depth": 4,
        "learning_rate": 0.05,
        "subsample": 0.8,
        "colsample_bytree": 0.8,
        "verbose": -1
      },
      "feature_set": "point_and_interval",
      "optimize": false,
      "optuna_trials": 50
    }
  },
  "validation": {
    "method": "rolling_window",
    "initial_train_quarters": 8,
    "test_quarters": 2,
    "step_quarters": 2,
    "min_train_samples": 200
  },
  "evaluation": {
    "metrics": [
      "auc",
      "pr_auc",
      "brier",
      "f1",
      "precision",
      "recall"
    ],
    "permutation_n_repeats": 20,
    "ablation_groups": [
      {
        "name": "interval_stats",
        "description": "移除所有区间统计特征",
        "remove_patterns": [
          "_mean",
          "_cv",
          "_std",
          "_min",
          "_max",
          "_q25",
          "_q50",
          "_q75",
          "_skew",
          "_kurt",
          "_width"
        ]
      },
      {
        "name": "quantiles",
        "description": "移除分位数特征",
        "remove_patterns": [
          "_q25",
          "_q50",
          "_q75"
        ]
      },
      {
        "name": "width",
        "description": "移除区间宽度特征",
        "remove_patterns": [
          "_width"
        ]
      }
    ],
    "calibration_bins": 10
  },
  "groups": {
    "by_industry": true,
    "by_time": true
  },
  "output": {
    "figures_dir": "outputs/figures",
    "reports_dir": "outputs/reports",
    "models_dir": "outputs/models"
  }
}