IPO Availability Timestamping
Separate Listing Events from Research Knowledge
Install and import#
npm install fintech-algorithmsimport { calculate } from "fintech-algorithms/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping";Signature#
calculate(data)Decides when a newly listed security first became usable — not when it was listed, but when enough history existed to satisfy the policy a strategy actually applies.
Parameters#
| Name | Type | Notes |
|---|---|---|
data | { query: object; policies: Policy[]; records: Record[] } | policies states the seasoning rules — minimum trading days, minimum float, minimum liquidity — so the availability date follows from a declared rule rather than a hard-coded constant. |
Returns#
{ effectiveAt, knownAt, identity, policyId, status, policySatisfied, effectiveGateAt, … }
The date the security became eligible under the named policy, plus which gate was the binding one.
Errors#
- When the referenced policy does not exist — throws
Complexity: time O(records),
space O(1).
Worked example#
verified This is the worked example published in the article, replayed by the test suite on every run. The output cannot drift.
Input#
{
"query": {
"issuerId": "ISSUER-SYN-001",
"instrumentId": "INSTRUMENT-SYN-001",
"listingId": "LISTING-SYN-XNAS",
"effectiveAt": "2025-05-13T13:36:10Z",
"knownAt": "2025-05-13T13:36:10Z",
"policyId": "POLICY-SYN-IPO-RESEARCH"
},
"policies": [
{
"policyId": "POLICY-SYN-IPO-RESEARCH",
"revision": 1,
"state": "active",
"effectiveAt": "2025-05-01T00:00:00Z",
"availableAt": "2025-05-01T00:05:00Z",
"sourceId": "SYN-RESEARCH-GOVERNANCE",
"context": "traditional_ipo",
"marketPhase": "regular",
"requiredEventTypes": [
"registration_effective",
"listing_notice",
"first_eligible_session",
"first_observed_trade",
"vendor_release",
"local_ingestion"
]
},
{
"policyId": "POLICY-SYN-IPO-RESEARCH",
"revision": 2,
"state": "active",
"effectiveAt": "2025-05-01T00:00:00Z",
"availableAt": "2025-05-14T09:00:00Z",
"sourceId": "SYN-RESEARCH-GOVERNANCE",
"context": "traditional_ipo",
"marketPhase": "regular",
"requiredEventTypes": [
"registration_effective",
"listing_notice",
"first_eligible_session",
"first_observed_quote",
"first_observed_trade",
"vendor_release"
]
}
],
"records": [
{
"eventId": "EV-FILING",
"revision": 1,
"state": "active",
"eventType": "issuer_filing",
"issuerId": "ISSUER-SYN-001",
"instrumentId": "INSTRUMENT-SYN-001",
"listingId": "LISTING-SYN-XNAS",
"marketPhase": "all",
"effectiveAt": "2025-05-05T14:00:00Z",
"availableAt": "2025-05-05T14:03:00Z",
"clockOwner": "regulator",
"sourceId": "SYN-REGULATOR-FILING"
},
{
"eventId": "EV-EFFECT",
"revision": 1,
"state": "active",
"eventType": "registration_effective",
"issuerId": "ISSUER-SYN-001",
"instrumentId": "INSTRUMENT-SYN-001",
"listingId": "LISTING-SYN-XNAS",
"marketPhase": "all",
"effectiveAt": "2025-05-08T12:00:00Z",
"availableAt": "2025-05-08T12:02:00Z",
"clockOwner": "regulator",
"sourceId": "SYN-REGULATOR-EFFECT"
},
{
"eventId": "EV-LIST",
"revision": 1,
"state": "active",
"eventType": "listing_notice",
"issuerId": "ISSUER-SYN-001",
"instrumentId": "INSTRUMENT-SYN-001",
"listingId": "LISTING-SYN-XNAS",
"marketPhase": "all",
"effectiveAt": "2025-05-13T13:30:00Z",
"availableAt": "2025-05-08T15:10:00Z",
"clockOwner": "exchange",
"sourceId": "SYN-EXCHANGE-NOTICE"
}
]
}Call#
calculate(data)Returns#
object with 4 fields: status, effectiveGateAt, knowledgeGateAt, missingEventTypes
{
"status": "resolved",
"effectiveGateAt": "2025-05-13T13:36:00Z",
"knowledgeGateAt": "2025-05-13T13:36:05Z",
"missingEventTypes": []
}Diagrams#
Calculation flow#
Causal IPO evidence flow
flowchart TD
Q["Query: identity, effectiveAt, knownAt, policyId"] --> P["Keep policy revisions available by knownAt"]
P --> PA{"Applicable active policy?"}
PA -->|No| MI["Incomplete: missing policy"]
PA -->|Yes| E["Keep event revisions available by knownAt"]
E --> V["Validate known immutable revision chains"]
V --> I["Match issuer, instrument, listing, and market phase"]
I --> R{"Required clocks resolved and effective?"}
R -->|Missing or cancelled| INC["Incomplete"]
R -->|Conflicting timestamps| AMB["Ambiguous"]
R -->|Unsupported policy semantic| UNS["Unsupported"]
R -->|Yes| G["Resolved: effective gate plus knowledge gate"]
IPO evidence query state lifecycle
stateDiagram-v2
[*] --> SelectPolicy
SelectPolicy --> Incomplete: policy missing or cancelled
SelectPolicy --> SelectEvidence: policy active and applicable
SelectEvidence --> Incomplete: required evidence missing, cancelled, or future-effective
SelectEvidence --> Ambiguous: required timestamps or identity links conflict
SelectEvidence --> Unsupported: policy semantic does not fit listing context
SelectEvidence --> Resolved: every required clock effective and known
Resolved --> LaterKnownQuery: correction becomes available
LaterKnownQuery --> SelectPolicy
Incomplete --> [*]
Ambiguous --> [*]
Unsupported --> [*]
Resolved --> [*]
How it works#
This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.
References#
- R1 - SEC: Determine the Status of My Filing
- R2 - SEC: Webmaster Frequently Asked Questions
- R3 - Airbnb 2020 Form 10-K
- R4 - Airbnb final prospectus filing index
- R5 - Airbnb pricing announcement hosted by Nasdaq
- R6 - Nasdaq Listing Rule IM-5315-1
- R7 - Nasdaq Daily List product description