Skip to content

Add CRSP monthly characteristics pipeline - #4

Merged
Yuning598 merged 1 commit into
mainfrom
yuning598/chars-ciz-monthly
Aug 8, 2026
Merged

Add CRSP monthly characteristics pipeline#4
Yuning598 merged 1 commit into
mainfrom
yuning598/chars-ciz-monthly

Conversation

@Yuning598

Copy link
Copy Markdown
Collaborator

Summary

  • add a separate chars_ciz_monthly pipeline
  • source monthly and daily CRSP data from the crspm schema
  • keep WRDS credentials interactive rather than hard-coded
  • preserve size_grp as metadata in ranked outputs

Validation

  • compiled all Python modules
  • verified queries reference crspm.msf_v2, crspm.dsf_v2, and crspm.inddlyseriesdata
  • verified ranking retains size_grp without creating rank_size_grp

Copilot AI lite review requested due to automatic review settings August 8, 2026 05:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new chars_ciz_monthly pipeline to compute, merge, and publish monthly CRSP/Compustat/IBES-based characteristics (including rolling-window market microstructure measures and quarterly-sourced “satellite” anomalies), with a companion WRDS download script targeting the crspm schema.

Changes:

  • Adds monthly satellite characteristic computations (e.g., SUE, ABR, RE) and a Polars-based rolling window engine for daily→monthly rolling characteristics.
  • Adds a merge + backfill stage to combine accounting characteristics with satellites and CRSP monthly returns/ME.
  • Adds an impute + rank + output stage that preserves size_grp metadata in ranked outputs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
chars_ciz_monthly/sue.py Computes quarterly SUE and populates it forward to monthly dates.
chars_ciz_monthly/rolling_chars.py Computes rolling daily-window characteristics and maps them to monthly windows.
chars_ciz_monthly/myre.py Computes IBES-based monthly forecast revisions (RE) using ICLINK + CRSP.
chars_ciz_monthly/merge_chars.py Merges accounting + satellites + rolling chars and backfills CRSP return/ME fields.
chars_ciz_monthly/impute_rank_output.py Reconciles annual/quarterly, shifts returns, imputes, ranks, and writes final outputs.
chars_ciz_monthly/iclink_ciz.sas Includes SAS macro source for generating the IBES–CRSP link table.
chars_ciz_monthly/functions.py Provides shared helpers (ffi codes, imputation, standardization, etc.).
chars_ciz_monthly/download_data.py Downloads required WRDS tables (Compustat/CRSP/IBES/CCM) into local parquet.
chars_ciz_monthly/accounting.py Computes accounting and momentum characteristics and produces monthly-aligned accounting outputs.
chars_ciz_monthly/abr.py Computes ABR around earnings announcements and populates to monthly.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread chars_ciz_monthly/sue.py
Comment on lines +87 to +97
def std_with_zero_handling(cols, min_valid=6):
"""Row-wise std of YoY EPS differences; returns None if < min_valid non-null, 0 if all equal."""
concat_expr = pl.concat_list(cols)
valid_count = concat_expr.list.eval(pl.element().is_not_null().cast(pl.Int32).sum()).list.first()
all_equal = concat_expr.list.max() == concat_expr.list.min()
std_val = concat_expr.list.eval(pl.element().std()).list.first()
return (
pl.when(valid_count < min_valid).then(pl.lit(None, dtype=pl.Float64))
.when(all_equal).then(pl.lit(0.0))
.otherwise(std_val)
)
Comment on lines +172 to +179
df.group_by(["permno", "group_number"])
.agg([
((col("vol") * col("prc").abs()).log()).std().alias("std_dolvol"),
pl.len().alias("n_obs"),
])
.filter(col("n_obs") >= min_obs)
.drop("n_obs")
)
Comment on lines +210 to +215
.with_columns([
(
(col("zero_count") + (1.0 / col("turn_sum")) / 11000)
* 63.0 / col("n_obs")
).alias("zerotrade")
])
Comment on lines +226 to +230
df.group_by(["permno", "group_number"])
.agg([
(col("ret").abs() / (col("prc").abs() * col("vol"))).mean().alias("ill"),
pl.len().alias("n_obs"),
])
Comment on lines +278 to +280
/* ********************************************************************************* */
/* ************* Material Copyright Wharton Research Data Services *************** */
/* ****************************** All Rights Reserved ****************************** */
Comment thread chars_ciz_monthly/sue.py
Comment on lines +147 to +148
# Keep first (most recent datadate) for each permno-date
df = df.unique(subset=["permno", "date"], keep="first")
Comment on lines +152 to +156
def _backfill_crsp(chars, crsp_fill):
"""Fill missing ret/retx/retadj/me from CRSP backfill table."""
chars = chars.join(crsp_fill, on=['permno', 'jdate'], how='left')
for col_name in ['ret', 'retx', 'me']:
fill_col = f'{col_name}_fill'
@Yuning598
Yuning598 merged commit 6fd14c2 into main Aug 8, 2026
1 check passed
@Yuning598
Yuning598 deleted the yuning598/chars-ciz-monthly branch August 8, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants