Legislative disclosure data has a structural problem that no amount of feed quality fixes, and it is not the lag. It is that the analyst almost always finds the policy context after the filing rather than before it. A row appears, somebody searches for what that committee was doing that month, a plausible date turns up, and the note writes itself. That process cannot produce a wrong answer, which is exactly what disqualifies it as research.
The fix is unglamorous infrastructure. You maintain a standing calendar of legislative and regulatory dates, built forward, and you join filings to it. A hypothesis that was on the calendar before the filing arrived is testable. One assembled afterwards is not, and it will not survive the first serious question in an investment committee.
The join you are missing when a filing arrives
Consider the timing the module itself reports. At capture, average delay between transaction and filing stood at 32.5 days, against 696,750 indexed trades and 7,083 legislators in the roster, with 330 late filings in the compliance tally. So the disclosure arrives, on average, more than a month after the decision that produced it, and a meaningful tail arrives later than that.
That lag is usually discussed as a decay problem, which it is. The more damaging effect is epistemic. By the time you see the row, the policy record for that month is complete and public, which guarantees you can find something that fits. Retrospective context is free and worthless. Prospective context costs you a standing process and is the only version that supports attribution.
The asymmetry is worth stating precisely for a research meeting. Before the fact, you have a small number of scheduled dates and a large number of possible filings. After the fact, you have one filing and an unbounded set of candidate explanations. Only the first direction constrains anything.

What the calendar carries and what the schema has to hold
Scope first. The event types worth maintaining are the ones with dates that are known in advance and consequences that are sector-legible: committee markups, floor scheduling notices, budget scores and cost estimates, appropriations and authorisation deadlines, agency rulemaking milestones including comment period opens and closes, effective dates, and scheduled testimony. What unifies them is that a date exists before the outcome does.
The schema matters more than the sourcing, because the fields are what make the join auditable a year later.
| Field | Why it exists |
|---|---|
| event_id, event_type | Stable key and a controlled vocabulary, so you can count event types in attribution. |
| scheduled_date, certainty | Statutory, scheduled, or estimated. Most calendar failures are estimated dates treated as scheduled ones. |
| committee, chamber | The join key against the module's committee fit input. |
| sector_tags, ticker_universe | GICS level mapping plus an explicit ticker list, both written before the event, never widened afterwards. |
| source_url, captured_at, last_verified | Provenance. If it is not here you cannot defend the entry. |
| superseded_by, status | Dates move constantly. You need the original entry preserved, not overwritten. |
The last row is the one teams skip and then regret. If a markup slips three weeks and you update the date in place, you have silently destroyed the record of what you believed at the time. Append, never overwrite.
Joining it to the feed without importing a causal claim
The module's stated signal inputs include politician history, committee fit, size and timing, and it does cluster detection across politicians, parties and sectors. Committee fit plus a forward date is a natural join, and it is also the exact point where a research process can turn into an accusation if the language is sloppy.
Hold the discipline in the schema itself. The calendar records public policy dates. The feed records filings made under statutory disclosure regimes. The join produces a sector-level and date-level prior, and the output field should be named as a prior. It should never contain a field that encodes intent, knowledge or motive, because such a field cannot be populated from either data source and its presence in a table invites somebody downstream to treat it as a finding.
What the join legitimately supports is narrow and still useful: whether disclosed activity in a sector clusters ahead of scheduled events in that sector more than a randomised baseline would produce, measured across the whole roster rather than around individuals. Run it at cohort level. Cohort level is both the statistically sound unit, given that a single legislator generates too few observations to say anything, and the unit that keeps the output describing a system rather than a person.
Refresh cadence and who owns the staleness
The two sides of this join decay at completely different rates and pretending otherwise is how calendars rot.
The feed side is machine-maintained on a 15 minute refresh per the engine panel, sourced from official disclosure systems. The calendar side is human-maintained, and every entry starts decaying the moment it is written, because legislative schedules are provisional by nature. So the calendar needs the things any operational dataset needs and rarely gets in a research team: a named owner, a re-verification interval per certainty class, and an automatic status flag for any entry whose last_verified is older than that interval.
My rule of thumb is that statutory deadlines get verified monthly, scheduled events weekly inside a four week horizon, and estimated dates are excluded from any live signal until they are confirmed. An unverified estimated date should never be capable of generating a trade, and that has to be enforced by the pipeline rather than by an analyst's judgement on the day.
Note also the compliance side of the feed. With 330 late filings showing at capture, the filing timestamp and the transaction timestamp are different variables with different reliabilities. Join on transaction date for research and on filing date for anything you claim was actionable, and keep both columns. Conflating them will overstate every result you produce, and it is the first thing a competent reviewer will check.
What the calendar is worth in the post-mortem
The payoff shows up when a position goes wrong and you are asked to explain it. With a calendar, the answer has a shape: on this date we recorded this scheduled event with this certainty and this ticker universe, on that date filings clustered in that sector, we sized accordingly, the event slipped or the outcome differed, here is the entry as it stood. That is a process failure or a hypothesis failure, both of which are survivable and both of which teach you something. Without a calendar the honest answer is that the position looked good afterwards, which is not survivable.
Attribution improves for the same reason. Because event_type is a controlled field, you can eventually decompose results by category and discover that, say, rulemaking milestones carry whatever your process finds and floor scheduling carries nothing, which is a real allocation decision you cannot reach any other way.
The honest limits deserve their own line in the documentation. Unscheduled action has no date to anchor to and simply falls outside the method. Continuing resolutions and stopgaps vaporise appropriations deadlines that were the whole basis for an entry. Recess calendars shift everything downstream. And with a 32.5 day average disclosure lag, an event horizon shorter than about six weeks means the filings confirming your prior will arrive after the catalyst has already resolved, which makes the join useful for validating a framework and useless for trading that particular event. Write that constraint into the process document rather than rediscovering it in a review.