DriftSurvival: Survival Analysis on Credit Risk with Data Drift Handling
driftsurvival is a specialized Python package designed for credit risk survival analysis under non-stationary environments. It implements the LMISO (Landmark One-Hot + Isotonic Calibration) framework for mortgage default prediction, addressing data drift caused by macroeconomic shifts, changing borrower behaviors, and dynamic loan lifecycles.
🌟 Key Features
- Longitudinal Behavioral Markers (
driftsurvival.markers): Computes balance deviation ($BD_{pct}$) trajectories based on standard loan amortization formulas, tracking borrower payment behavior over time. - Landmark Dataset Construction (
driftsurvival.landmark): Transforms dynamic panel loan data into landmark-based observation points with customizable prediction horizons (e.g., default within 12 months). - Discrete-Time Hazard Modeling (
driftsurvival.models): Logistic regression-based survival models incorporating static, dynamic, and landmark one-hot ($LM$) baseline hazard adjustments. - Isotonic Probability Calibration (
driftsurvival.calibration): Non-parametric post-hoc calibration ensuring accurate default risk probabilities without altering rank ordering. - Drift Adaptation & Weighting (
driftsurvival.models.weighting): Supports Time-Decay Weighting ($TD$) and Importance Weighting ($IW$) for adaptive learning during distribution shifts. - Drift Simulation & Diagnostics (
driftsurvival.drift): Tools for injecting sudden, incremental, or recurring synthetic drift into panel data, along with drift quantification metrics. - Benchmark Suite (
driftsurvival.benchmarks): Standardized wrappers for baseline survival models, including Cox Proportional Hazards (lifelines), XGBoost, and River streaming estimators. - Visualization Suite (
driftsurvival.visualization): Integrated diagnostic plots for survival curves, reliability diagrams, drift distributions, and model coefficients.
🏗️ Package Architecture
driftsurvival/
├── markers/ # Longitudinal marker calculation (BD_pct & trajectory fitting)
├── landmark/ # Dynamic landmark dataset construction & one-hot encoding
├── models/ # Discrete-time hazard models, LMISO estimator, and decay/importance weighting
├── calibration/ # Post-hoc isotonic calibration mapping
├── drift/ # Synthetic drift simulation (sudden, incremental, recurring) & quantification
├── evaluation/ # Survival metrics (AUC, Brier score, ECE) & grouped loan-level CV
├── preprocessing/ # Domain-specific mortgage data preprocessors & amortization calculators
├── visualization/ # Diagnostic plotting utilities
└── benchmarks/ # Interfaces for baseline comparisons (Cox, XGBoost, River)
💻 Installation
Standard Installation
pip install driftsurvival
Installation with Optional Benchmarks & Development Dependencies
# Install with benchmark comparison dependencies (lifelines, xgboost, river)
pip install driftsurvival[benchmarks]
# Install in editable mode for development
pip install -e .[dev,benchmarks]
🚀 Quickstart & Usage
1. Compute Longitudinal Behavioral Markers
import pandas as pd
from driftsurvival.markers import BalanceDeviationMarker
# Sample loan panel data
panel_df = pd.DataFrame({
"loan_id": ["L001"] * 6,
"LoanAge": [1, 2, 3, 4, 5, 6],
"CurAct_UPB": [99500, 99000, 98400, 97800, 97000, 96000],
"OrigUPB": [100000] * 6,
"OrigInterestRate": [6.0] * 6,
"OrigLoanTerm": [360] * 6
})
marker = BalanceDeviationMarker()
df_with_markers = marker.fit_transform(panel_df)
print(df_with_markers[["loan_id", "LoanAge", "BD_pct", "BD_slope"]])
2. Build Landmark Datasets
from driftsurvival.landmark import LandmarkDatasetConstructor
constructor = LandmarkDatasetConstructor(
landmark_months=[6, 12, 18, 24],
prediction_horizon=12
)
# Convert dynamic loan history into landmark observations
landmark_data = constructor.transform(
df=panel_df,
id_col="loan_id",
time_col="LoanAge",
target_col="DefaultFlag"
)
3. Fit the Complete LMISO Estimator
from driftsurvival.models import LMISOEstimator
estimator = LMISOEstimator(
landmark_months=[6, 12, 18, 24],
prediction_horizon=12,
use_calibration=True,
l2_regularization=1.0
)
# Fit pipeline on historical loan panel
estimator.fit(panel_df, target_col="DefaultFlag", id_col="loan_id", time_col="LoanAge")
# Predict probability of default within horizon at landmark 12
probs = estimator.predict_proba(panel_df, landmark_month=12)
4. Inject Synthetic Data Drift for Testing
from driftsurvival.drift import DriftSimulator
simulator = DriftSimulator(seed=42)
# Inject incremental interest rate & default prevalence drift starting at month 24
drifted_panel = simulator.inject_incremental_drift(
panel_df,
feature="OrigInterestRate",
start_time=24,
end_time=48,
magnitude=2.5
)
📊 Evaluation & Metrics
driftsurvival provides group-aware evaluation tools ensuring loan-level isolation during validation:
from driftsurvival.evaluation import GroupedSurvivalCV, evaluate_survival_predictions
metrics = evaluate_survival_predictions(
y_true=y_test,
y_prob=probs,
landmarks=landmark_test_ids
)
print(f"AUC-ROC: {metrics['auc']:.4f}")
print(f"Brier Score: {metrics['brier_score']:.4f}")
print(f"Expected Calibration Error (ECE): {metrics['ece']:.4f}")
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
📖 Citation
This package is based on the following paper:
Incorporating data drift to perform survival analysis on credit risk Jianwei Peng (1), Stefan Lessmann (1 and 2) ((1) Humboldt-Universität zu Berlin, (2) Bucharest University of Economic Studies)
Survival analysis has become a standard approach for modelling time to default by time-varying covariates in credit risk. Unlike most existing methods that implicitly assume a stationary data-generating process, in practise, mortgage portfolios are exposed to various forms of data drift caused by changing borrower behaviour, macroeconomic conditions, policy regimes and so on. This study investigates the impact of data drift on survival-based credit risk models and proposes a dynamic joint modelling framework to improve robustness under non-stationary environments. The proposed model integrates a longitudinal behavioural marker derived from balance dynamics with a discrete-time hazard formulation, combined with landmark one-hot encoding and isotonic calibration. Three types of data drift (sudden, incremental and recurring) are simulated and analysed on mortgage loan datasets from Freddie Mac. Experiments and corresponding evidence show that the proposed landmark-based joint model consistently outperforms classical survival models, tree-based drift-adaptive learners and gradient boosting methods in terms of discrimination and calibration across all drift scenarios, which confirms the superiority of our model design.
Metadata
Release files for driftsurvival 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| driftsurvival-0.1.0.tar.gz | 47.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| driftsurvival-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.0 kB
Release files / driftsurvival-0.1.0.tar.gz
| Download URL | driftsurvival-0.1.0.tar.gz |
|---|---|
| Size | 47.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
943e97e603e289ee2d0fb622354ee60c0680865ad223390e319dac979d8b4d9e
|
|
BLAKE2b-256 checksum How to use checksums |
7360878a2d6845830b98067bd72c28ec508fb6580aecb33f11b8d7d3404d00f9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.
Transparency logRelease files / driftsurvival-0.1.0-py3-none-any.whl
| Download URL | driftsurvival-0.1.0-py3-none-any.whl |
|---|---|
| Size | 55.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
18ecc1be42979922113a4fadb72aeacee050c171674af0fe9b2db79486f0b6cc
|
|
BLAKE2b-256 checksum How to use checksums |
328c63be6bfefd0cedab9124142e2ed870c0648b78b82f5e96bd10f4caaf5607
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.
Transparency logSecurity for driftsurvival 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for driftsurvival-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.