mostlyright.core.schemas.earnings_fact
mostlyright.core.schemas.earnings_fact
Section titled “mostlyright.core.schemas.earnings_fact”Earnings-fact schema (schema.earnings_fact.v1) — Phase 27 (27-01).
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 (D-27.11). 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.earnings_fact.v1 shape contract.
delivery vs source (D-27.2/D-27.6, 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 (27-10 Task 1, 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 (D-27.14/
D-27.16) — a counted fact delta is is_final=True yet still
resolution_status="provisional". Settlement/backtest 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 (D-27.2/D-27.6). |
|---|---|
ROLE_SOURCE_VALUES | D-27.11 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 (D-30; 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 (D-30). |
RESOLUTION_STATUS_VALUES | Resolution status (RESEARCH-MARKETS §2.1(6)). |
KALSHI_COUNTABLE_ROLE_SOURCES | D-27.11 fail-closed membership sets. |
Functions
Section titled “Functions”validate_kalshi_counted_occurrence(…[, strict]) | Fail-closed Kalshi-count rule (D-27.11). |
|---|---|
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.earnings_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 (D-30; 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 (D-27.2/D-27.6). 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.earnings_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 D-27.11 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)).
COLUMNS : ClassVar[list[ColumnSpec]] = [ColumnSpec(name=‘ticker’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘call_id’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘provider event id for the call’), ColumnSpec(name=‘term_canonical’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘canonical market term (§2.1(3) term.canonical)’), ColumnSpec(name=‘term_accepted_forms’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘JSON-encoded list of accepted surface forms (exploded slash + plural/possessive) — §2.1(3) term.accepted_forms’), ColumnSpec(name=‘term_match_rule’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘exact’, ‘plural_possessive_ok_no_tense’, ‘lemma’, ‘regex’), notes=‘§2.1(3) term.match_rule (plural/possessive OK, NOT tense)’), ColumnSpec(name=‘compound_type’, dtype=‘enum’, units=None, nullable=True, enum_values=(‘standalone’, ‘open’, ‘hyphenated’, ‘closed’, ‘affix_derivation’), notes=“D-30 §2.1(3) per-occurrence compound axis — SEPARATE from term_match_rule (do NOT overload MATCH_RULE_VALUES). standalone/open/hyphenated auto-count on both venues; closed is Polymarket candidate-only + Kalshi-No; affix_derivation counts for neither. Nullable: pre-fix rows omit it (default ‘standalone’)”), ColumnSpec(name=‘matched_surface_form’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“the actually-spoken string (§2.1(3)) — kept verbatim so each occurrence is auditable against each venue’s stricter/looser rule”), ColumnSpec(name=‘mention_count’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘PRIMARY integer tally (§2.1(2)); boolean is derived as >= 1 — storing only a bool cannot settle threshold brackets’), ColumnSpec(name=‘counting_mode’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘boolean_ge1’, ‘threshold_ge_n’, ‘exact_n’, ‘range’), notes=‘§2.1(2) counting_mode; boolean markets = boolean_ge1 (n=1)’), ColumnSpec(name=‘threshold_n’, dtype=‘int64’, units=None, nullable=True, enum_values=None, notes=‘§2.1(2) threshold_n (inclusive >= N); null for non-threshold modes’), ColumnSpec(name=‘speaker_role’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘company_executive’, ‘company_ir’, ‘operator_ir’, ‘operator_moderator’, ‘sell_side_analyst’, ‘other_external’, ‘unknown’), notes=‘§2.1(4) speaker_role — drives Kalshi/Polymarket scope divergence’), ColumnSpec(name=‘speaker_name’, dtype=‘string’, units=None, nullable=True, enum_values=None, notes=‘§2.1(4) speaker_name; nullable when unattributed’), ColumnSpec(name=‘role_source’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘transcript_structural’, ‘transcript_self_id’, ‘roster_match’, ‘diarization_advisory’), notes=‘D-27.11 provenance of the role attribution; only the three transcript-anchored values are Kalshi-countable (diarization is advisory only)’), ColumnSpec(name=‘segment’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘operator_intro’, ‘prepared_remarks’, ‘qa’, ‘closing’), notes=‘§2.1(5) call segment of the occurrence’), ColumnSpec(name=‘offset_seconds’, dtype=‘int64’, units=‘seconds’, nullable=True, enum_values=None, notes=‘§2.1(5) seconds into the call (audit trail); nullable’), ColumnSpec(name=‘confidence’, dtype=‘float64’, units=None, nullable=False, enum_values=None, notes=‘0..1 STT/attribution confidence (§2.1(6)) — flags borderline hits’), ColumnSpec(name=‘window_scope’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘full_call’, ‘prepared_remarks_only’, ‘qa_only’, ‘press_release_only’, ‘full_event_incl_release’), notes=‘§2.1(5) time-window scope a market resolves over’), ColumnSpec(name=‘resolution_status’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘pending’, ‘provisional’, ‘resolved_yes’, ‘resolved_no’, ‘no_qualifying_event’, ‘voided’, ‘disputed’), notes=“§2.1(6) resolution_status; ‘provisional’ = live early-signal delta (27-10, D-27.16) — NOT a settlement/backtest source”), ColumnSpec(name=‘kalshi_counted’, dtype=‘bool’, units=None, nullable=False, enum_values=None, notes=‘derived via validate_kalshi_counted_occurrence (D-27.11 fail-closed) — True iff role_source + speaker_role are anchorable’), ColumnSpec(name=‘is_final’, dtype=‘bool’, units=None, nullable=True, enum_values=None, notes=‘STT-segment finality ONLY (D-27.14/D-27.16); a provisional fact delta is is_final=True. NEVER gates settlement authority. Optional — batch rows omit/default True’), ColumnSpec(name=‘spoken_at’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘aired/event_time wallclock of the words (27-10, D-27.16); optional streaming marker — null on batch rows’), ColumnSpec(name=‘event_time’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=‘call air time (event-time)’), ColumnSpec(name=‘as_of_time’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘knowledge-time = transcript availability post-call (NOT event_date); for a live row stamped at STT-finalization/publish time and >= spoken_at (D-27.16); nullable’), ColumnSpec(name=‘source’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“per-row source-identity overlay == ‘earnings_call’ (D-27.2)”), ColumnSpec(name=‘delivery’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘live’, ‘hosted’), notes=‘delivery-channel lineage {live,hosted}; NOT source identity (D-27.2)’)]
Section titled “COLUMNS : ClassVar[list[ColumnSpec]] = [ColumnSpec(name=‘ticker’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘call_id’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘provider event id for the call’), ColumnSpec(name=‘term_canonical’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘canonical market term (§2.1(3) term.canonical)’), ColumnSpec(name=‘term_accepted_forms’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘JSON-encoded list of accepted surface forms (exploded slash + plural/possessive) — §2.1(3) term.accepted_forms’), ColumnSpec(name=‘term_match_rule’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘exact’, ‘plural_possessive_ok_no_tense’, ‘lemma’, ‘regex’), notes=‘§2.1(3) term.match_rule (plural/possessive OK, NOT tense)’), ColumnSpec(name=‘compound_type’, dtype=‘enum’, units=None, nullable=True, enum_values=(‘standalone’, ‘open’, ‘hyphenated’, ‘closed’, ‘affix_derivation’), notes=“D-30 §2.1(3) per-occurrence compound axis — SEPARATE from term_match_rule (do NOT overload MATCH_RULE_VALUES). standalone/open/hyphenated auto-count on both venues; closed is Polymarket candidate-only + Kalshi-No; affix_derivation counts for neither. Nullable: pre-fix rows omit it (default ‘standalone’)”), ColumnSpec(name=‘matched_surface_form’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“the actually-spoken string (§2.1(3)) — kept verbatim so each occurrence is auditable against each venue’s stricter/looser rule”), ColumnSpec(name=‘mention_count’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘PRIMARY integer tally (§2.1(2)); boolean is derived as >= 1 — storing only a bool cannot settle threshold brackets’), ColumnSpec(name=‘counting_mode’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘boolean_ge1’, ‘threshold_ge_n’, ‘exact_n’, ‘range’), notes=‘§2.1(2) counting_mode; boolean markets = boolean_ge1 (n=1)’), ColumnSpec(name=‘threshold_n’, dtype=‘int64’, units=None, nullable=True, enum_values=None, notes=‘§2.1(2) threshold_n (inclusive >= N); null for non-threshold modes’), ColumnSpec(name=‘speaker_role’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘company_executive’, ‘company_ir’, ‘operator_ir’, ‘operator_moderator’, ‘sell_side_analyst’, ‘other_external’, ‘unknown’), notes=‘§2.1(4) speaker_role — drives Kalshi/Polymarket scope divergence’), ColumnSpec(name=‘speaker_name’, dtype=‘string’, units=None, nullable=True, enum_values=None, notes=‘§2.1(4) speaker_name; nullable when unattributed’), ColumnSpec(name=‘role_source’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘transcript_structural’, ‘transcript_self_id’, ‘roster_match’, ‘diarization_advisory’), notes=‘D-27.11 provenance of the role attribution; only the three transcript-anchored values are Kalshi-countable (diarization is advisory only)’), ColumnSpec(name=‘segment’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘operator_intro’, ‘prepared_remarks’, ‘qa’, ‘closing’), notes=‘§2.1(5) call segment of the occurrence’), ColumnSpec(name=‘offset_seconds’, dtype=‘int64’, units=‘seconds’, nullable=True, enum_values=None, notes=‘§2.1(5) seconds into the call (audit trail); nullable’), ColumnSpec(name=‘confidence’, dtype=‘float64’, units=None, nullable=False, enum_values=None, notes=‘0..1 STT/attribution confidence (§2.1(6)) — flags borderline hits’), ColumnSpec(name=‘window_scope’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘full_call’, ‘prepared_remarks_only’, ‘qa_only’, ‘press_release_only’, ‘full_event_incl_release’), notes=‘§2.1(5) time-window scope a market resolves over’), ColumnSpec(name=‘resolution_status’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘pending’, ‘provisional’, ‘resolved_yes’, ‘resolved_no’, ‘no_qualifying_event’, ‘voided’, ‘disputed’), notes=“§2.1(6) resolution_status; ‘provisional’ = live early-signal delta (27-10, D-27.16) — NOT a settlement/backtest source”), ColumnSpec(name=‘kalshi_counted’, dtype=‘bool’, units=None, nullable=False, enum_values=None, notes=‘derived via validate_kalshi_counted_occurrence (D-27.11 fail-closed) — True iff role_source + speaker_role are anchorable’), ColumnSpec(name=‘is_final’, dtype=‘bool’, units=None, nullable=True, enum_values=None, notes=‘STT-segment finality ONLY (D-27.14/D-27.16); a provisional fact delta is is_final=True. NEVER gates settlement authority. Optional — batch rows omit/default True’), ColumnSpec(name=‘spoken_at’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘aired/event_time wallclock of the words (27-10, D-27.16); optional streaming marker — null on batch rows’), ColumnSpec(name=‘event_time’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=‘call air time (event-time)’), ColumnSpec(name=‘as_of_time’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘knowledge-time = transcript availability post-call (NOT event_date); for a live row stamped at STT-finalization/publish time and >= spoken_at (D-27.16); nullable’), ColumnSpec(name=‘source’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“per-row source-identity overlay == ‘earnings_call’ (D-27.2)”), ColumnSpec(name=‘delivery’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘live’, ‘hosted’), notes=‘delivery-channel lineage {live,hosted}; NOT source identity (D-27.2)’)]”schema_id : ClassVar[str] = ‘schema.earnings_fact.v1’
Section titled “schema_id : ClassVar[str] = ‘schema.earnings_fact.v1’”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 (D-30). 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’})”D-27.11 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" (27-10 Task 1)
marks a LIVE early-signal fact delta — NOT a settlement/backtest source
(D-27.16); 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’)”D-27.11 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 (D-27.11).
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
KalshiCountRuleViolation (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
KalshiCountRuleViolation (D-27.11 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.