Designing a Reusable Signal Library
A signal library is the difference between every researcher reinventing feature code from scratch and a desk that can test a new idea in an afternoon — but only if the library enforces the same point-in-time and versioning discipline every individual signal needs.
Prerequisites: From Raw Data Field to Tradeable Signal, Point-in-Time Data
The first signal a researcher builds is usually a script: pull a data field, transform it, test it against forward returns, done. The tenth signal is where this stops working. Every researcher's script re-derives its own universe filter, its own lag convention, its own way of handling a stock that delists mid-sample — and small inconsistencies between scripts mean two "signals" that look uncorrelated in a backtest are secretly built on different survivorship assumptions, not different ideas. A signal library is the shared code and shared conventions that stop this from happening: one way to define the universe, one way to lag a feature, one place a signal's history lives, so that a new idea can be tested against exactly the same rules as every signal already in production.
What a library actually standardises
A signal library is not a folder of functions — it is an agreement on a handful of interfaces that every signal must obey.
Universe and calendar. Every signal is computed on the same trading calendar and the same point-in-time universe definition (which names existed, were liquid enough, and were not restricted, as of each date). If one researcher's script includes delisted names and another's doesn't, comparing their signals' Sharpe ratios is comparing two different experiments.
Timestamp and lag conventions. The library owns the rule for "when could this have been known" (see From Raw Data Field to Tradeable Signal) and applies it uniformly, so no individual signal can quietly skip the lag and produce a look-ahead-inflated backtest.
A common output schema. Every signal, regardless of the underlying data, resolves to the same shape: one value per name per date, with a defined missing-value convention. This is what makes signals combinable — a blender or a portfolio construction step can consume any signal in the library without custom glue code.
Versioning and lineage. When a signal's transform changes, the old version does not silently disappear; it is versioned, so a backtest run last month can still be reproduced exactly (see Feature Versioning and Backfill Safety).
A signal library's value is not the code it saves typing — it's the errors it makes structurally impossible: no signal can leak future information, no two signals can be compared on different universes, and no backtest becomes unreproducible because someone edited a script in place.
A worked example
Suppose a desk has 40 existing signals and a researcher wants to add signal 41: a "days since last analyst upgrade" feature. Without a library, this researcher writes a fresh pipeline — pulls analyst data, decides on a lag, picks a universe, and backtests. Two things commonly go wrong at exactly this point: the universe used happens to exclude a batch of small caps that were dropped for an unrelated reason months ago (making the new signal's Sharpe look better than it would on the live universe), and the lag convention differs slightly from the desk standard, adding a half-day of look-ahead.
With a library, the researcher instead writes only the transform: given the raw analyst-revision table (already ingested, already point-in-time-correct), compute days since last upgrade, and register it. The library applies the shared universe filter, the shared lag rule, and the shared output schema automatically. Signal 41 can then be immediately compared to signals 1 through 40 on identical footing, and a downstream step that combines the top 10 signals into a composite (see Blending Alpha Signals with Machine Learning) can consume it without any custom code.
Think of this curve as a stand-in for the cost of adding the n-th signal to a desk. Without shared infrastructure, that cost grows roughly linearly or worse — each new signal re-pays the fixed cost of getting the universe, lag and schema right. With a library, the curve should look closer to flat: the fixed cost was paid once, and each new signal only pays for what's genuinely new about it. Drag the exponent down toward zero and picture that as the payoff of good infrastructure — diminishing marginal cost per idea tested.
A useful test of whether a "library" is really one: can a new researcher, on their first day, add a signal without reading anyone else's individual script? If not, the shared interfaces aren't actually shared — they're just convention, and convention erodes.
Where it breaks in practice
Libraries decay when the interface is too rigid for a genuinely novel signal — say, one that needs a non-standard lag because the data itself arrives on an irregular schedule — and researchers route around it with one-off code "just this once." Every one-off is a signal that isn't actually comparable to the rest of the library, and a portfolio built by blending library signals with one-off signals inherits whatever inconsistency the one-off carries. The fix is not to forbid exceptions but to make the exception itself a first-class, versioned part of the library, so it inherits the same lineage and reproducibility guarantees as everything else.
A signal library that enforces point-in-time correctness at ingestion but lets individual signal code re-lag or re-filter the universe downstream has not actually solved the leakage problem — it has just moved the place where it can go wrong one layer deeper, and made it harder to audit because the bug is no longer visible in any one script.
Related concepts
Practice in interviews
Further reading
- Isichenko, Quantitative Portfolio Management (ch. 3, signal construction)
- Kakushadze & Serur, 151 Trading Strategies (appendix on infrastructure)