mostlyright.core.schemas.earnings_fact
Earnings-fact schema (schema.finance.fact.v1).
One row per (ticker, call_id, term, occurrence) mention counted from an
earnings call. This is the settlement-flipping load-bearing contract: the
two venues (Kalshi, Polymarket) resolve the SAME fact rows through different
filters (see 27-RESEARCH-MARKETS-RULES-STT.md §2), so the schema must carry
every taxonomy dimension both venues key on.
Two surfaces live here:
validate_kalshi_counted_occurrence
: The fail-closed Kalshi-count hook. A Kalshi-counted occurrence
MUST carry role_source ∈ {transcript_structural, transcript_self_id, roster_match} AND speaker_role ∈ {company_executive, operator_ir}.
Un-anchorable occurrences are EXCLUDED from the Kalshi count (recall loss
accepted to avoid mis-settlement) but RETAINED for the Polymarket
any-speaker count. ColumnSpec carries no regex/cross-field rule
(core/schema.py), so this is a module-level hook mirroring
validate_satellite_station.
validate_ticker
: The ticker-identity hook, raising EarningsFactCorruptError for a
malformed ticker — mirrors validate_satellite_station.
EarningsFactSchema
: The full schema.finance.fact.v1 shape contract.
delivery vs source (satellite precedent). delivery (enum
{live, hosted}, default "live") is INFORMATIONAL LINEAGE ONLY — the
delivery channel, NOT source identity. The per-row source overlay column is
the validator-required source-identity column. Both the live STT path and the
hosted feed produce rows from the SAME upstream public call audio, so they share
one source identity ("earnings_call"), exactly as satellite’s noaa_goes.
Streaming fields (additive). resolution_status carries the
extra "provisional" value for live early-signal fact deltas, and the
is_final / spoken_at markers are ADDITIVE/optional so a batch (post-call)
row is unchanged. is_final denotes STT-segment finality ONLY — a counted
fact delta is is_final=True yet still
resolution_status="provisional". Settlement/research authority is gated on
resolution_status / source ONLY, never on is_final;
validate_kalshi_counted_occurrence is mode-agnostic (applies identically to
live and batch).
Module Attributes
Section titled “Module Attributes”DELIVERY_VALUES | Delivery-channel lineage. |
|---|---|
ROLE_SOURCE_VALUES | role_source — the provenance of the speaker-role attribution. |
SPEAKER_ROLE_VALUES | Speaker role of the occurrence (RESEARCH-MARKETS §2.1(4)). |
COUNTING_MODE_VALUES | Counting mode (RESEARCH-MARKETS §2.1(2)). |
SEGMENT_VALUES | Call segment of the occurrence (RESEARCH-MARKETS §2.1(5)). |
WINDOW_SCOPE_VALUES | Time-window scope a market resolves over (RESEARCH-MARKETS §2.1(5)). |
MATCH_RULE_VALUES | Term match rule (RESEARCH-MARKETS §2.1(3)). |
COMPOUND_TYPE_VALUES | Compound-type axis (RESEARCH-MARKETS §2.1(3) “Compound words — REAL CROSS-VENUE DIVERGENCE” + §2.2 “Closed-compound divergence”). |
KALSHI_AUTOCOUNT_COMPOUND_TYPES | Venue auto-count membership over COMPOUND_TYPE_VALUES. |
RESOLUTION_STATUS_VALUES | Resolution status (RESEARCH-MARKETS §2.1(6)). |
KALSHI_COUNTABLE_ROLE_SOURCES | Fail-closed membership sets. |
Functions
Section titled “Functions”validate_kalshi_counted_occurrence(…[, strict]) | Fail-closed Kalshi-count rule. |
|---|---|
validate_kalshi_counted_rows(rows, *[, strict]) | Cross-field guard: a stored kalshi_counted=True MUST be derivable. |
validate_ticker(ticker) | Validate an earnings-fact row’s ticker identity. |
Classes
Section titled “Classes”EarningsFactSchema() | schema.finance.fact.v1 — one row per counted mention occurrence. |
|---|
mostlyright.core.schemas.earnings_fact.COMPOUND_TYPE_VALUES : tuple[str, …] = (‘standalone’, ‘open’, ‘hyphenated’, ‘closed’, ‘affix_derivation’)
Section titled “mostlyright.core.schemas.earnings_fact.COMPOUND_TYPE_VALUES : tuple[str, …] = (‘standalone’, ‘open’, ‘hyphenated’, ‘closed’, ‘affix_derivation’)”Compound-type axis (RESEARCH-MARKETS §2.1(3) “Compound words — REAL
CROSS-VENUE DIVERGENCE” + §2.2 “Closed-compound divergence”). This is a
SEPARATE per-occurrence axis from MATCH_RULE_VALUES — do NOT overload
the match-rule enum with these values. A hyphenated compound counts for the
bare term on BOTH venues; a closed (unhyphenated) compound (wildfire for
fire) diverges: Kalshi No, Polymarket candidate-only in v1. An affix
derivation (joyful for joy) counts for NEITHER venue.
mostlyright.core.schemas.earnings_fact.COUNTING_MODE_VALUES : tuple[str, …] = (‘boolean_ge1’, ‘threshold_ge_n’, ‘exact_n’, ‘range’)
Section titled “mostlyright.core.schemas.earnings_fact.COUNTING_MODE_VALUES : tuple[str, …] = (‘boolean_ge1’, ‘threshold_ge_n’, ‘exact_n’, ‘range’)”Counting mode (RESEARCH-MARKETS §2.1(2)). mention_count is the integer
primary tally; boolean is DERIVED as count >= 1 (boolean markets are
boolean_ge1 with threshold_n == 1).
mostlyright.core.schemas.earnings_fact.DELIVERY_VALUES : tuple[str, …] = (‘live’, ‘hosted’)
Section titled “mostlyright.core.schemas.earnings_fact.DELIVERY_VALUES : tuple[str, …] = (‘live’, ‘hosted’)”Delivery-channel lineage. INFORMATIONAL ONLY — not source
identity. Mirrors SATELLITE_DELIVERY_VALUES.
class mostlyright.core.schemas.earnings_fact.EarningsFactSchema
Section titled “class mostlyright.core.schemas.earnings_fact.EarningsFactSchema”Bases: Schema
schema.finance.fact.v1 — one row per counted mention occurrence.
Carries the six RESEARCH-MARKETS §2 taxonomy dimensions (term match rule,
counting mode, speaker scope, window scope, time, tie-break/resolution) plus
the role_source provenance and the derived kalshi_counted
flag, so the SAME fact rows resolve correctly under each venue’s wording.
mention_count is the integer PRIMARY tally; the boolean (“said ≥ 1”) is
derived as mention_count >= 1 — storing only a bool cannot settle
Polymarket “say X 5+ times” threshold brackets (RESEARCH-MARKETS §2.1(2)).
schema_id: ClassVar[str]
Section titled “schema_id: ClassVar[str]”mostlyright.core.schemas.earnings_fact.KALSHI_AUTOCOUNT_COMPOUND_TYPES : frozenset[str] = frozenset({‘hyphenated’, ‘open’, ‘standalone’})
Section titled “mostlyright.core.schemas.earnings_fact.KALSHI_AUTOCOUNT_COMPOUND_TYPES : frozenset[str] = frozenset({‘hyphenated’, ‘open’, ‘standalone’})”Venue auto-count membership over COMPOUND_TYPE_VALUES. Both
venues auto-count standalone/open/hyphenated in v1. closed is a
candidate-only type — it never auto-counts; instead it surfaces for human
review when it could flip a Polymarket outcome (fact_builder), and it is
excluded from the Kalshi count entirely (Kalshi says No on a closed compound).
affix_derivation is in NEITHER set (counts for no venue).
mostlyright.core.schemas.earnings_fact.KALSHI_COUNTABLE_ROLE_SOURCES : frozenset[str] = frozenset({‘roster_match’, ‘transcript_self_id’, ‘transcript_structural’})
Section titled “mostlyright.core.schemas.earnings_fact.KALSHI_COUNTABLE_ROLE_SOURCES : frozenset[str] = frozenset({‘roster_match’, ‘transcript_self_id’, ‘transcript_structural’})”Fail-closed membership sets. A Kalshi-counted occurrence MUST satisfy BOTH. Anything outside is excluded from the Kalshi count (retained for Polymarket’s any-speaker count).
mostlyright.core.schemas.earnings_fact.MATCH_RULE_VALUES : tuple[str, …] = (‘exact’, ‘plural_possessive_ok_no_tense’, ‘lemma’, ‘regex’)
Section titled “mostlyright.core.schemas.earnings_fact.MATCH_RULE_VALUES : tuple[str, …] = (‘exact’, ‘plural_possessive_ok_no_tense’, ‘lemma’, ‘regex’)”Term match rule (RESEARCH-MARKETS §2.1(3)). Kalshi accepts exact/plural/ possessive but NOT verb-tense inflections.
mostlyright.core.schemas.earnings_fact.RESOLUTION_STATUS_VALUES : tuple[str, …] = (‘pending’, ‘provisional’, ‘resolved_yes’, ‘resolved_no’, ‘no_qualifying_event’, ‘voided’, ‘disputed’)
Section titled “mostlyright.core.schemas.earnings_fact.RESOLUTION_STATUS_VALUES : tuple[str, …] = (‘pending’, ‘provisional’, ‘resolved_yes’, ‘resolved_no’, ‘no_qualifying_event’, ‘voided’, ‘disputed’)”Resolution status (RESEARCH-MARKETS §2.1(6)). "provisional"
marks a LIVE early-signal fact delta — NOT a settlement/research source;
authority is gated on this column + source, never on
is_final.
mostlyright.core.schemas.earnings_fact.ROLE_SOURCE_VALUES : tuple[str, …] = (‘transcript_structural’, ‘transcript_self_id’, ‘roster_match’, ‘diarization_advisory’)
Section titled “mostlyright.core.schemas.earnings_fact.ROLE_SOURCE_VALUES : tuple[str, …] = (‘transcript_structural’, ‘transcript_self_id’, ‘roster_match’, ‘diarization_advisory’)”role_source — the provenance of the speaker-role attribution. EXACTLY four values. Acoustic diarization is advisory only (it mis-clusters analyst Q&A as exec); only the three transcript-anchored sources are Kalshi-countable.
mostlyright.core.schemas.earnings_fact.SEGMENT_VALUES : tuple[str, …] = (‘operator_intro’, ‘prepared_remarks’, ‘qa’, ‘closing’)
Section titled “mostlyright.core.schemas.earnings_fact.SEGMENT_VALUES : tuple[str, …] = (‘operator_intro’, ‘prepared_remarks’, ‘qa’, ‘closing’)”Call segment of the occurrence (RESEARCH-MARKETS §2.1(5)).
mostlyright.core.schemas.earnings_fact.SPEAKER_ROLE_VALUES : tuple[str, …] = (‘company_executive’, ‘company_ir’, ‘operator_ir’, ‘operator_moderator’, ‘sell_side_analyst’, ‘other_external’, ‘unknown’)
Section titled “mostlyright.core.schemas.earnings_fact.SPEAKER_ROLE_VALUES : tuple[str, …] = (‘company_executive’, ‘company_ir’, ‘operator_ir’, ‘operator_moderator’, ‘sell_side_analyst’, ‘other_external’, ‘unknown’)”Speaker role of the occurrence (RESEARCH-MARKETS §2.1(4)). Drives the speaker-scope divergence between Kalshi (company-reps-incl-operator) and Polymarket (any speaker).
mostlyright.core.schemas.earnings_fact.WINDOW_SCOPE_VALUES : tuple[str, …] = (‘full_call’, ‘prepared_remarks_only’, ‘qa_only’, ‘press_release_only’, ‘full_event_incl_release’)
Section titled “mostlyright.core.schemas.earnings_fact.WINDOW_SCOPE_VALUES : tuple[str, …] = (‘full_call’, ‘prepared_remarks_only’, ‘qa_only’, ‘press_release_only’, ‘full_event_incl_release’)”Time-window scope a market resolves over (RESEARCH-MARKETS §2.1(5)).
mostlyright.core.schemas.earnings_fact.validate_kalshi_counted_occurrence(role_source, speaker_role, , strict=False)
Section titled “mostlyright.core.schemas.earnings_fact.validate_kalshi_counted_occurrence(role_source, speaker_role, , strict=False)”Fail-closed Kalshi-count rule.
Returns True iff the occurrence is anchorable for the Kalshi count:
role_source ∈ KALSHI_COUNTABLE_ROLE_SOURCES AND
speaker_role ∈ KALSHI_COUNTABLE_SPEAKER_ROLES. Returns False for
EVERY other (role_source, speaker_role) pair — un-anchorable occurrences are
excluded from the Kalshi count (recall loss accepted to avoid
mis-settlement) but stay countable for Polymarket’s any-speaker rule.
This is the boolean a fact row’s kalshi_counted column is derived from.
It is mode-agnostic: live (resolution_status="provisional") and batch
occurrences are filtered identically. is_final (STT finality) NEVER
gates this rule.
When strict=True and the occurrence is un-anchorable, raises
KalshiCountRuleViolationError (carrying the offending fields) — used at
a write-site asserting an occurrence is Kalshi-counted.
mostlyright.core.schemas.earnings_fact.validate_kalshi_counted_rows(rows, , strict=True)
Section titled “mostlyright.core.schemas.earnings_fact.validate_kalshi_counted_rows(rows, , strict=True)”Cross-field guard: a stored kalshi_counted=True MUST be derivable.
The schema validator checks kalshi_counted only as a bool dtype — it
cannot see that a stored True is consistent with the row’s
role_source / speaker_role. Settlement authority would then trust
the boolean as-is, letting a row assert kalshi_counted=True while
role_source="diarization_advisory" or the speaker is an analyst.
This post-validation hook re-derives the flag from
validate_kalshi_counted_occurrence() and confirms it matches the
stored value for EVERY row. A row claiming kalshi_counted=True whose
(role_source, speaker_role) is un-anchorable raises
KalshiCountRuleViolationError (fail-closed) when strict;
a row that under-counts (stored False while the pair is anchorable) is
a contract bug too and raises EarningsFactCorruptError.
Returns the number of rows checked. Mirrors validate_satellite_station
as a module-level hook (ColumnSpec has no cross-field rule).
mostlyright.core.schemas.earnings_fact.validate_ticker(ticker)
Section titled “mostlyright.core.schemas.earnings_fact.validate_ticker(ticker)”Validate an earnings-fact row’s ticker identity.
Returns the ticker unchanged when valid (so call sites can use it inline).
Raises EarningsFactCorruptError for a non-string or an empty
string — mirrors validate_satellite_station. The acceptable ticker
shape is intentionally permissive (issuers like BRK.B carry a dot); the
contract enforced here is only non-empty-string.