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 to a research system — not when it was listed, but whether every event type a named, versioned policy requires had become effective for the evaluated instant and known by the research cutoff. The answer is data-readiness evidence; it never establishes investability, tradability, liquidity, offering eligibility, or returns.
Parameters#
| Name | Type | Notes |
|---|---|---|
data | { query: Query; policies: Policy[]; records: EventRecord[]; identityLinks?: IdentityLink[] } | query fixes the issuer/instrument/listing identity, the effectiveAt instant being evaluated, the knownAt research cutoff, and the policyId. Each policies revision names, in requiredEventTypes, which of the ten supported clocks must be present — from issuer_filing through local_ingestion. There is no minimum-trading-day, free-float, or liquidity threshold anywhere in the contract. records are immutable, revisioned event observations carrying both an effectiveAt and an availableAt. identityLinks is consulted only for a de_spac policy context. |
Returns#
{ effectiveAt, knownAt, identity, policyId, status, policySatisfied, policy, effectiveGateAt, knowledgeGateAt, missingPolicy, missingEventTypes, pendingEffectiveEventTypes, ambiguousEventTypes, supplementalAmbiguousEventTypes, cancelledEventTypes, unsupportedReasons, identityContinuityStatus, identityContinuityEvidence, evidence, doesNotEstablish }
status is resolved, incomplete, ambiguous, or unsupported. effectiveGateAt and knowledgeGateAt are populated only when the status is resolved: the latest effective instant and the latest availability instant among the policy and its required events — the binding gates. The remaining lists name which event types were missing, future-effective, conflicting, or cancelled. doesNotEstablish is returned on every call.
Errors#
- When the input is malformed: a missing or empty required string, a timestamp without a UTC offset, a non-positive or non-contiguous revision, an unknown event type, context, state or market phase, a clockOwner that does not own that event's clock, a revision that changes immutable identity, a revision whose availability does not increase, or a record reactivated after cancellation — throws
- When the referenced policyId has no revision that is both effective for the evaluated instant and known by the cutoff — returns status
incompletewithmissingPolicy: true; it does not throw
Complexity: time O(r log r) for r records known at the cutoff: each event's revision chain is sorted before its current revision is taken, then a fixed set of ten event types is resolved from those current revisions,
space O(r).
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