Skip to main content

HonestDiD (Python)

Python 3.8+ License: MIT

Robust inference for Difference-in-Differences and event study designs.

This is a Python implementation of the methods proposed in Rambachan and Roth (2023), "A More Credible Approach to Parallel Trends."

Overview

The honestdid package implements methods for constructing robust confidence intervals in difference-in-differences and event study designs. These methods allow researchers to relax the parallel trends assumption and perform sensitivity analysis to evaluate how violations of parallel trends affect their conclusions.

The key idea is that pre-trends are informative about violations of parallel trends. The package formalizes this intuition through two main approaches:

Smoothness Restrictions (Delta^{SD})

Restrictions that bound how the slope of the underlying trend can change between consecutive periods. Setting $M = 0$ implies the counterfactual trend is exactly linear, while larger values of $M$ allow for more non-linearity.

Relative Magnitudes Restrictions (Delta^{RM})

Restrictions that bound the post-treatment violation of parallel trends relative to the maximum pre-treatment violation. Setting $\bar{M} = 1$ means post-treatment violations can be no larger than the maximum pre-treatment violation.

Installation

Install from GitHub (recommended)

pip install git+https://github.com/anzonyquispe/honestdid.git

Install from source

git clone https://github.com/anzonyquispe/honestdid.git
cd honestdid
pip install -e .

Dependencies

  • Python >= 3.8
  • PyTorch >= 1.9.0
  • NumPy >= 1.19.0
  • SciPy >= 1.6.0
  • CVXPY >= 1.1.0
  • Pandas >= 1.2.0

Basic Usage

import torch
import honestdid as hd

# Load your event study estimates (betahat) and variance-covariance matrix (sigma)
# betahat: coefficient estimates for pre and post periods (excluding reference period)
# sigma: variance-covariance matrix

# Example: 4 pre-treatment periods + 4 post-treatment periods
numPrePeriods = 4
numPostPeriods = 4

# Target parameter: effect in first post-treatment period
l_vec = hd.basis_vector(index=1, size=numPostPeriods)

# Original confidence set (assuming parallel trends holds exactly)
original_cs = hd.constructOriginalCS(
    betahat=betahat,
    sigma=sigma,
    numPrePeriods=numPrePeriods,
    numPostPeriods=numPostPeriods,
    l_vec=l_vec,
    alpha=0.05
)

# Sensitivity analysis using smoothness restrictions (DeltaSD)
sensitivity_results = hd.createSensitivityResults(
    betahat=betahat,
    sigma=sigma,
    numPrePeriods=numPrePeriods,
    numPostPeriods=numPostPeriods,
    l_vec=l_vec,
    Mvec=[0, 0.01, 0.02, 0.03],  # different values of M
    alpha=0.05
)
print(sensitivity_results)

# Sensitivity analysis using relative magnitudes (DeltaRM)
sensitivity_rm = hd.createSensitivityResults_relativeMagnitudes(
    betahat=betahat,
    sigma=sigma,
    numPrePeriods=numPrePeriods,
    numPostPeriods=numPostPeriods,
    l_vec=l_vec,
    Mbarvec=[0.5, 1.0, 1.5, 2.0],  # different values of Mbar
    alpha=0.05
)
print(sensitivity_rm)

Main Functions

Function Description
constructOriginalCS Constructs the original confidence set assuming parallel trends holds
find_optimal_flci Finds the optimal fixed-length confidence interval
createSensitivityResults Sensitivity analysis under smoothness restrictions (DeltaSD)
createSensitivityResults_relativeMagnitudes Sensitivity analysis under relative magnitudes (DeltaRM)
computeConditionalCS_DeltaSD Conditional confidence set for DeltaSD
computeConditionalCS_DeltaRM Conditional confidence set for DeltaRM
DeltaSD_upperBound_Mpre Upper bound for M from pre-treatment periods
DeltaSD_lowerBound_Mpre Lower bound for M from pre-treatment periods

Advanced Usage

Fixed-Length Confidence Intervals (FLCI)

flci = hd.find_optimal_flci(
    betahat=betahat,
    sigma=sigma,
    numPrePeriods=numPrePeriods,
    numPostPeriods=numPostPeriods,
    l_vec=l_vec,
    M=0,  # smoothness parameter
    alpha=0.05
)
print(f"FLCI: [{flci['FLCI'][0]:.4f}, {flci['FLCI'][1]:.4f}]")

Breakdown Values

Calculate the value of M at which the confidence set includes zero:

# Get upper bound for M from pre-treatment data
M_upper = hd.DeltaSD_upperBound_Mpre(
    betahat=betahat,
    sigma=sigma,
    numPrePeriods=numPrePeriods,
    alpha=0.05
)
print(f"Upper bound for M: {M_upper:.4f}")

Combined Restrictions

The package also supports combining multiple restrictions:

  • computeConditionalCS_DeltaSDB: Smoothness + sign restrictions
  • computeConditionalCS_DeltaSDM: Smoothness + monotonicity
  • computeConditionalCS_DeltaRMB: Relative magnitudes + sign restrictions
  • computeConditionalCS_DeltaRMM: Relative magnitudes + monotonicity
  • computeConditionalCS_DeltaSDRM: Smoothness + relative magnitudes

Related Implementations

Citation

If you use this package, please cite:

@article{rambachan2023more,
  title={A More Credible Approach to Parallel Trends},
  author={Rambachan, Ashesh and Roth, Jonathan},
  journal={Review of Economic Studies},
  volume={90},
  number={5},
  pages={2555--2591},
  year={2023},
  publisher={Oxford University Press}
}

References

License

MIT License

Metadata

Release files for honestdid 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for honestdid 0.1.1
File Size Uploaded
honestdid-0.1.1.tar.gz 26.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for honestdid 0.1.1
File Interpreter ABI Platform
honestdid-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 50.6 kB

Release files / honestdid-0.1.1.tar.gz

Download URL honestdid-0.1.1.tar.gz
Size 26.2 kB
Tags Source
SHA-256 checksum
How to use checksums
029db67477a375d490fc59ca9ef08ec763a6d291b9ec603c0f5d81cf2928969a
BLAKE2b-256 checksum
How to use checksums
5ac035ecbc1a1a0be91c5f6719919a9d4ba7ae2bec52ad3b0e5140cee5a69c33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Mar 3, 2026.

Transparency log

Release files / honestdid-0.1.1-py3-none-any.whl

Download URL honestdid-0.1.1-py3-none-any.whl
Size 24.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
66828bc8b4856033fbc1c6aea575ed64f0382425f5f3ee2f8e5c93a5f62063d9
BLAKE2b-256 checksum
How to use checksums
e6aef3e759c398d7efdc7ac1f13ce997102fb16fc47ec07ad72b2d5eb3abc0b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Mar 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page