Skip to content

docs: FIX documentation + accuracy pass + release prep for 3.3.0#441

Merged
TexasCoding merged 2 commits into
mainfrom
chore/release-3.3.0
Jun 6, 2026
Merged

docs: FIX documentation + accuracy pass + release prep for 3.3.0#441
TexasCoding merged 2 commits into
mainfrom
chore/release-3.3.0

Conversation

@TexasCoding

Copy link
Copy Markdown
Owner

Summary

Release prep for 3.3.0 — documents the FIX subsystem (which shipped to main after 3.2.0 but was entirely undocumented), folds in a multi-agent documentation accuracy audit, and bumps the version. Additive release; no breaking changes.

A 7-agent audit (→ verify high/critical) reviewed every doc file against the code: 52 findings (20 critical / 12 high), dominated by the FIX gap, plus several genuine accuracy bugs in existing docs.

Version → 3.3.0

FIX documentation (was a complete gap)

  • New docs/fix.md — full guide: overview, auth (RSA-PSS reuse), clients (FixClient / MarginFixClient), the six session types, send/receive of typed messages, FixOrderBook, SettlementReassembler, on_decode_error, the FIX error hierarchy, and connectivity.
  • README FIX section + feature bullet; docs/index.md feature + nav row; mkdocs.yml nav; FIX error hierarchy in errors.md (+ autodoc); FIX reference autodoc in reference.md; FIX cross-references in authentication / configuration / environment-variables / perps / resources index.
  • Top-level exports: FixClient, MarginFixClient, FixConfig, FixEnvironment, FixSessionType re-exported from kalshi (consistent with PerpsClient); stale kalshi.fix package docstring refreshed.

Documentation accuracy fixes

  • fcm.md: document fcm.positions_all() — the page wrongly stated it didn't exist.
  • portfolio.md: document the subaccount parameter on the read methods.
  • markets.md: is_block_trade corrected to SDK v3.1.0 (was v3.20.0, the OpenAPI spec version).
  • index.md: WebSocket channel count corrected to 11 (matched websockets.md).
  • types.md: document OrderPrice and MultiplierDecimal.
  • environment-variables.md: passphrase is read by from_env() too; CHANGELOG 3.1.0 date aligned to 2026-06-04.

Verification

  • uv run ruff check . — clean
  • uv run mypy kalshi/ (strict) — clean (158 files)
  • uv run mkdocs build --strict — clean (nav, links, anchors, autodoc all resolve)
  • uv run pytest tests/4194 passed, 316 skipped (the 4 from_env failures are the pre-existing full-run env-leak flake; they pass in isolation)

🤖 Generated with Claude Code

Bump to 3.3.0 (pyproject + __init__) for the additive FIX subsystem (#402) and the
decode-routing (#432) and drift-test (#437) follow-ups. No breaking changes.

FIX documentation (the subsystem was entirely undocumented):
- new docs/fix.md guide; FIX section in README; FIX in the docs landing page
  features + "where to go next" + mkdocs nav; FIX error hierarchy in errors.md;
  FIX reference autodoc in reference.md; FIX cross-references in authentication /
  configuration / environment-variables / perps / resources index.
- re-export the FIX entry points (FixClient, MarginFixClient, FixConfig,
  FixEnvironment, FixSessionType) from the top-level kalshi package (consistent
  with PerpsClient); refresh the stale kalshi.fix package docstring.

Documentation accuracy fixes (from a multi-agent docs audit):
- fcm.md: document fcm.positions_all() (the page wrongly said it did not exist).
- portfolio.md: document the subaccount parameter on the read methods.
- markets.md: is_block_trade version corrected to SDK v3.1.0 (was v3.20.0 — the
  OpenAPI spec version, not the SDK version).
- index.md: WebSocket channel count corrected to 11 (matches websockets.md).
- types.md: document OrderPrice and MultiplierDecimal.
- environment-variables.md: the key passphrase is read by from_env() too.

Release metadata: CHANGELOG + ROADMAP 3.3.0 entries; CHANGELOG 3.1.0 date aligned
to 2026-06-04 (matching the release tag / ROADMAP).

ruff + mypy --strict clean; mkdocs build --strict clean; 4194 tests pass (the 4
from_env failures are the pre-existing full-run env-leak flake — they pass in
isolation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jun 6, 2026

Copy link
Copy Markdown

Code Review — PR #441: docs/FIX documentation + accuracy pass + 3.3.0 release prep

Summary: Documentation-only release prep (453 additions, 14 deletions, 20 files). Core work is the new docs/fix.md guide plus cross-referencing it from 10+ existing pages. Code changes are limited to adding FIX re-exports to kalshi/__init__.py and bumping the version in pyproject.toml.


What's good

  • Coverage is thorough. docs/fix.md walks auth, config, all session types, send/receive, order book, settlement reassembly, error handling, and connectivity — a reader can go from zero to a working session.
  • Accuracy fixes are real. FCM positions_all() was genuinely wrong in the old docs; the WebSocket channel count (13 → 11 typed subscribe_*) and the is_block_trade SDK version note are correct fixes.
  • Export pattern is consistent. FixClient / FixConfig / FixEnvironment / FixSessionType follow the same top-level re-export pattern as PerpsClient. __all__ is alphabetically maintained.
  • Version bump is consistentpyproject.toml and kalshi/__init__.py match.

Issues

1. Null propagation in settlement example — potential runtime error

docs/fix.md lines ~409–415:

async def on_message(raw):
    complete = reasm.add(decode_app_message(raw))  # MarketSettlementReport | None until whole

decode_app_message returns None for any message type it doesn't recognise (heartbeat ACKs at the app layer, etc.). Calling reasm.add(None) on a non-settlement message will likely raise a TypeError or AttributeError at runtime, not silently skip it. The example should guard:

async def on_message(raw):
    msg = decode_app_message(raw)
    if msg is None:
        return
    complete = reasm.add(msg)

Users copying this verbatim will hit an error the first time a non-settlement frame arrives on the session.

2. Sessions table is missing order_groups() — "six session types" is contradicted

The CHANGELOG, ROADMAP, and README all say the FIX engine covers six session types: "order entry (NR/RT), drop copy, market data, order groups, post-trade settlement, and RFQ". But the sessions table in docs/fix.md has only five rows — there is no order_groups() factory row.

One of two things is true:

  • order_groups() is a real session factory and the table is simply missing it (easy fix: add the row), or
  • Order groups are messages exchanged on the order-entry session and the "six session types" language in the CHANGELOG/README is misleading (in which case those references should say "five session types + order-group messages").

Either way the current state leaves a reader confused about how to open an order-groups session.

3. Sync lambda as on_message callback — may fail at runtime

Market data example in docs/fix.md lines ~388–392:

async with client.market_data(on_message=lambda raw: book.apply(decode_app_message(raw))) as md:

Every other on_message example in the guide uses async def. If the session engine awaits the callback, this synchronous lambda will raise TypeError: object NoneType can't be used in 'await' expression at runtime. The example should either use async def consistently, or the guide should state explicitly that sync callbacks are accepted (and show both forms).

4. KALSHI_FIX_ALLOW_UNKNOWN_HOST mentioned in prose but absent from the table

docs/environment-variables.md (FIX section): the variable is called out in a sentence but not given a table row, while every other env var has one. Minor consistency gap that could trip up someone scanning the table.


Minor notes

  • asyncio.sleep(2) in examples is fine for illustration, but a brief parenthetical ("in production, use an asyncio.Event rather than a fixed sleep") would prevent users from cargo-culting timing-based coordination.
  • The kalshi/fix/__init__.py docstring update is accurate and the old "foundation layer" language has been appropriately retired.

Verdict

Items 1 and 3 are the highest-priority fixes — users copying those code snippets verbatim will hit runtime errors. Item 2 is a factual inconsistency that will generate support questions. Item 4 is polish. Everything else in the PR is a clear improvement. Recommend addressing 1–3 before merge.

…ccuracy

- fix.md settlement example: guard `decode_app_message` with
  `isinstance(msg, MarketSettlementReport)` — SettlementReassembler.add() expects
  a settlement report, so feeding it None / another message type would raise.
- fix.md market-data example: replace the sync `lambda` on_message with an
  `async def` (the session awaits the callback; a sync callable fails at runtime)
  and note that on_message must be async.
- Correct "six session types … order groups" → there is no order_groups()
  session factory; order groups are messages on the order-entry session. Now
  "five session types (order entry NR/RT, drop copy, market data, post-trade, RFQ)
  + order-group management over the order-entry session" across README, docs
  index, fix.md (table note), CHANGELOG, ROADMAP. (The fix.md sessions table was
  already correct with 5 rows.)
- fix.md: note the illustrative `asyncio.sleep` should be an asyncio.Event in
  real code.

Not changed: KALSHI_FIX_ALLOW_UNKNOWN_HOST is documented in prose in the FIX env
section (a single FIX-only escape hatch; kept inline rather than a 1-row table).

mkdocs build --strict clean; ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jun 6, 2026

Copy link
Copy Markdown

Code Review — PR #441: FIX documentation + accuracy pass + release prep 3.3.0

Overview

This is a docs-and-release-prep PR: the only runnable code changes are five new re-exports in kalshi/__init__.py and an updated docstring in kalshi/fix/__init__.py. Everything else is documentation. The FIX subsystem itself shipped earlier; this PR documents it properly and corrects several accuracy bugs discovered by the multi-agent audit.

Overall quality is high. The new docs/fix.md is well-structured and practical, the error hierarchy table is clear, and the session comparison table (prediction vs. margin) is exactly what users need. A few items worth addressing:


Issues

Missing env-var table entry (environment-variables.md)

KALSHI_FIX_ALLOW_UNKNOWN_HOST is referenced in prose in docs/fix.md under Connectivity:

"a non-loopback host outside Kalshi's known FIX endpoints must be opted into with allow_unknown_host=True"

...and named explicitly as KALSHI_FIX_ALLOW_UNKNOWN_HOST=1 in environment-variables.md's new FIX prose section — but it never appears in a table row. The existing pattern (KALSHI_ALLOW_UNKNOWN_HOST and KALSHI_KLEAR_ALLOW_UNKNOWN_HOST both have explicit table rows) sets a precedent that FIX should follow for consistency and discoverability.

on_message raw parameter type not shown

Both the README snippet and docs/fix.md use raw with no type annotation:

async def on_message(raw) -> None:
    msg = decode_app_message(raw)

The prose says "each inbound application message as a raw RawMessage" in one place, but users writing their own handlers won't know the concrete type from the examples alone. Adding raw: RawMessage in the callback signatures (and importing RawMessage in the snippet) would help — or at minimum a short prose line pointing to the type before the first example.

Silent None return from decode_app_message — needs a stronger callout

Current wording:

decode_app_message(raw) returns None for both an unregistered message type and a malformed known message.

In an order-entry context this means a malformed execution report is silently dropped unless on_decode_error is registered. The mitigation is documented but only in the Error handling section, after users have already written their on_message handler. Consider a !!! warning admonition in the Sending and receiving section so the footgun is visible at the point of first use.


Minor

  • asyncio.sleep(2) example: Already has an "illustration only" note with the asyncio.Event recommendation. Good, no change needed.
  • decode_app_message_strict: Mentioned in the error section but has no code example. A two-liner showing the raise-on-error path would help users who prefer that style. Low priority.
  • Changelog verbosity: The 3.3.0 entry reads more like a release announcement than a changelog entry. Style-only, not blocking.
  • 3.1.0 date correction (2026-06-032026-06-04): Looks correct.

Code changes (kalshi/__init__.py)

The five new re-exports are correct and follow the established pattern (PerpsClient etc.):

from kalshi.fix import FixClient, FixConfig, FixEnvironment, FixSessionType
from kalshi.perps.fix import MarginFixClient

All five appear in __all__ in alphabetical order. Version bump is consistent across pyproject.toml and kalshi/__init__.py. No concerns.


Verdict

Approve with the env-var table gap as the one item I would fix before merge — the two existing *_ALLOW_UNKNOWN_HOST entries set a clear precedent, and the FIX equivalent is already referenced in prose in the same file. The raw type annotation and decode_app_message footgun callout are quality-of-life improvements worth filing as follow-up issues if not addressed here.

@TexasCoding TexasCoding merged commit bff73a1 into main Jun 6, 2026
5 checks passed
@TexasCoding TexasCoding deleted the chore/release-3.3.0 branch June 6, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant