Skip to content

mostlyright.markets.earnings.pit

Point-in-time alignment + leakage wiring for earnings facts (Phase 27, 27-06).

Two safety primitives keep earnings facts backtest-faithful:

align_event_date(event_date, ticker) : Calendar-date-only coercion (a datetime is rejected — the coerceContractDate-style guard copied from kalshi_nhigh) followed by an hq-timezone re-projection of the call instant to the issuer’s HQ-local calendar date (dailyExtremes-style ±1-UTC-day correction). A call that airs at 03:00 UTC on Jul 1 is still the evening of Jun 30 in Los Angeles — the settlement/contract date must be the hq-local date, not the UTC date.

knowledge_time_for(transcript_available_at) + assert_earnings_no_leakage : The load-bearing PIT invariant (D-27.11): knowledge_time = transcript availability (POST-call), NOT event_date. A backtest standing at an as_of before the transcript posted must NOT see the mention — a mention spoken on the call is not knowable until the transcript is published. We REUSE mostlyright.core.assert_no_leakage() + KnowledgeView (do not reimplement); this module only supplies the earnings-specific knowledge_time derivation and a thin wrapper.

If knowledge_time were ever set to event_date (the call date) instead of transcript availability, a backtest could “see” a mention before the call aired — the exact leak this module exists to forbid.

LIVE_STREAM_SOURCEThe live delivery-channel source id (D-27.16, 27-12).
PROVISIONAL_RESOLUTION_STATUSThe provisional resolution status carried by a live counted fact delta.
AUTHORITATIVE_SOURCEThe single authoritative post-call DELIVERY-CHANNEL source id (the ONLY valid backtest / settlement delivery channel).
align_event_date(event_date, ticker, *[, …])Coerce + hq-tz-correct an earnings event_date to the issuer-local date.
assert_earnings_no_leakage(df, as_of)Raise LeakageError if any fact row leaks past as_of.
assert_not_backtest_source(df)Raise if a DataFrame carrying provisional/live rows feeds a BACKTEST.
assert_settlement_source(df)Raise if a DataFrame carrying provisional/live rows feeds SETTLEMENT.
knowledge_time_for(transcript_available_at)Return the tz-aware UTC knowledge_time for a transcript availability.
live_knowledge_time(published_at, *[, spoken_at])Return the tz-aware UTC live knowledge_time = published_at.
live_knowledge_view(df, as_of)Return a KnowledgeView over the AUTHORITATIVE rows only.

mostlyright.markets.earnings.pit.AUTHORITATIVE_SOURCE = ‘earnings.hosted’

Section titled “mostlyright.markets.earnings.pit.AUTHORITATIVE_SOURCE = ‘earnings.hosted’”

The single authoritative post-call DELIVERY-CHANNEL source id (the ONLY valid backtest / settlement delivery channel). NOTE: this is the delivery-channel id, which is what a live/provisional row is tagged with in its source column (earnings.hosted.stream); an authoritative post-call frame’s per-row source overlay is the SHARED identity "earnings_call" (see EarningsAdapter). The firewall works by a NEGATIVE mask (reject the provisional earnings.hosted.stream / provisional rows), never a positive equality check against this constant — so the label is used only in error text, and the mismatch with "earnings_call" carries no leakage risk.

mostlyright.markets.earnings.pit.LIVE_STREAM_SOURCE = ‘earnings.hosted.stream’

Section titled “mostlyright.markets.earnings.pit.LIVE_STREAM_SOURCE = ‘earnings.hosted.stream’”

The live delivery-channel source id (D-27.16, 27-12). Rows tagged this way are PROVISIONAL live deltas — firewalled out of every backtest AND settlement read.

mostlyright.markets.earnings.pit.PROVISIONAL_RESOLUTION_STATUS = ‘provisional’

Section titled “mostlyright.markets.earnings.pit.PROVISIONAL_RESOLUTION_STATUS = ‘provisional’”

The provisional resolution status carried by a live counted fact delta.

mostlyright.markets.earnings.pit.align_event_date(event_date, ticker, , call_instant=None)

Section titled “mostlyright.markets.earnings.pit.align_event_date(event_date, ticker, , call_instant=None)”

Coerce + hq-tz-correct an earnings event_date to the issuer-local date.

  • Parameters:
    • event_date (date) – The calendar date the call airs / the market settles for. Must be a datetime.date with NO time component — a datetime is rejected (the time component would break the date-equality settlement match, mirroring kalshi_nhigh).
    • ticker (str) – The issuer ticker; its IANA HQ timezone is looked up in TICKER_HQ_TIMEZONE.
    • call_instant (str | None) – Optional ISO-8601 UTC instant of the call. When given, the event date is re-projected to the HQ-local calendar date of that instant (dailyExtremes-style ±1-UTC-day correction) — so a call that straddles a UTC day boundary lands on the correct local date. The re-projected hq-local date must be within ±1 calendar day of the supplied event_date; a larger divergence raises ValueError (it signals a mis-paired (event_date, call_instant) at the call site rather than a legitimate UTC-boundary shift). When omitted, event_date is returned unchanged (after coercion).
  • Return type: date
  • Returns: The HQ-local calendar datetime.date.
  • Raises:
    • TypeErrorevent_date is a datetime (or any non-date).
    • KeyErrorticker is not in TICKER_HQ_TIMEZONE.
    • ValueErrorcall_instant is naive, OR the re-projected hq-local date diverges from event_date by more than one calendar day.

mostlyright.markets.earnings.pit.assert_earnings_no_leakage(df, as_of)

Section titled “mostlyright.markets.earnings.pit.assert_earnings_no_leakage(df, as_of)”

Raise LeakageError if any fact row leaks past as_of.

Thin wrapper over mostlyright.core.assert_no_leakage() — the df MUST carry a tz-aware UTC knowledge_time column = transcript availability (post-call), so a backtest standing at as_of cannot see a mention before the transcript posted. as_of is a mostlyright.core.TimePoint.

  • Return type: None
  • Parameters: df (DataFrame)

mostlyright.markets.earnings.pit.assert_not_backtest_source(df)

Section titled “mostlyright.markets.earnings.pit.assert_not_backtest_source(df)”

Raise if a DataFrame carrying provisional/live rows feeds a BACKTEST.

LOAD-BEARING (codex P1). A backtester cannot read source="earnings.hosted.stream" / resolution_status="provisional" rows — they are the live trading feed, not backtest history. Pair with live_knowledge_view() (which excludes them from as_of()) so a provisional row can neither be handed in whole NOR survive a knowledge-time filter.

  • Return type: None
  • Parameters: df (DataFrame)

mostlyright.markets.earnings.pit.assert_settlement_source(df)

Section titled “mostlyright.markets.earnings.pit.assert_settlement_source(df)”

Raise if a DataFrame carrying provisional/live rows feeds SETTLEMENT.

LOAD-BEARING, the SECOND guard (codex P1). A market can NEVER settle on a provisional live count — only an authoritative post-call earnings.hosted (final, settled) row is a valid settlement/resolution source. Filtering the backtest read alone is insufficient; the settlement path needs its own guard. Invoke this at the markets earnings/ resolver’s settlement evaluation so a provisional row cannot resolve a market.

  • Return type: None
  • Parameters: df (DataFrame)

mostlyright.markets.earnings.pit.knowledge_time_for(transcript_available_at)

Section titled “mostlyright.markets.earnings.pit.knowledge_time_for(transcript_available_at)”

Return the tz-aware UTC knowledge_time for a transcript availability.

knowledge_time = transcript availability (POST-call), NOT event_date. This is the single point where the earnings PIT invariant is materialized: the timestamp a backtest is allowed to “know” the facts from a call.

  • Raises: ValueErrortranscript_available_at is naive (no timezone) — a naive knowledge_time would silently mis-order against the tz-aware as_of cutoff used by the leakage layer.
  • Return type: Timestamp
  • Parameters: transcript_available_at (str | Timestamp | datetime)

mostlyright.markets.earnings.pit.live_knowledge_time(published_at, , spoken_at=None)

Section titled “mostlyright.markets.earnings.pit.live_knowledge_time(published_at, , spoken_at=None)”

Return the tz-aware UTC live knowledge_time = published_at.

For a LIVE row the moment it became knowable is the STT-finalization / publish wallclock (published_at), NOT the aired spoken_at (event_time) and NOT post-call transcript availability (codex P2 / D-27.16). A row’s mention is knowable the instant the STT segment is finalized and published to the stream.

  • Parameters:
    • published_at (str | Timestamp | datetime) – The STT-finalization / publish wallclock (tz-aware).
    • spoken_at (str | Timestamp | datetime | None) – The aired event time (tz-aware). When given, the function asserts published_at >= spoken_at — a publish that predates the aired instant is impossible and signals a mis-paired row.
  • Return type: Timestamp
  • Returns: published_at normalized to tz-aware UTC.
  • Raises: ValueErrorpublished_at is naive, or published_at < spoken_at.

mostlyright.markets.earnings.pit.live_knowledge_view(df, as_of)

Section titled “mostlyright.markets.earnings.pit.live_knowledge_view(df, as_of)”

Return a KnowledgeView over the AUTHORITATIVE rows only.

Excludes provisional/live rows (source="earnings.hosted.stream" / resolution_status="provisional") BEFORE constructing the view, so a backtest as_of() read over a mixed frame returns ONLY authoritative post-call earnings.hosted rows with knowledge_time <= as_of. Reuses mostlyright.core.KnowledgeView (does not reimplement filtering); this wrapper only supplies the provisional-exclusion firewall.

  • Parameters:
    • df (DataFrame) – A mixed frame carrying a tz-aware UTC knowledge_time column.
    • as_of – The as-of cutoff (mostlyright.core.TimePoint).
  • Returns: A KnowledgeView whose dataframe() excludes provisional rows.