Skip to content

refactor: rename root to symbol and exp_date to expiration to match v3 vendor surface#468

Closed
userFRM wants to merge 5 commits into
mainfrom
fix/467-rename-root-symbol
Closed

refactor: rename root to symbol and exp_date to expiration to match v3 vendor surface#468
userFRM wants to merge 5 commits into
mainfrom
fix/467-rename-root-symbol

Conversation

@userFRM
Copy link
Copy Markdown
Owner

@userFRM userFRM commented May 4, 2026

Summary

Closes #467.

Rename the public-API fields on the SDK to match the v3 vendor surface
documented in the vendor migration guide:

  • Contract.root -> Contract.symbol
  • Contract.exp_date -> Contract.expiration
  • OptionContract.root -> OptionContract.symbol
  • FlatFileRow.root -> FlatFileRow.symbol
  • IndexEntry.root -> IndexEntry.symbol, IndexEntry.exp -> IndexEntry.expiration

Plus the matching constructor / parameter renames (Contract::stock(symbol),
Contract::option(symbol, expiration, ...), Contract::option_raw(...),
FlatFileRow::from_decoded(symbol, expiration, ...)).

Bumps the workspace to 8.0.25 (patch on the v8 line) and tdbe to 0.12.6.

What changed

Public Rust types

  • crates/tdbe/src/types/tick.rsOptionContract.symbol.
  • crates/thetadatadx/src/fpss/protocol.rsContract.symbol,
    Contract.expiration; constructor + method param renames; the
    internal byte-level decoder keeps the wire-spec local names (root,
    exp_date) so the file still diffs cleanly against the upstream
    binary protocol, but the struct construction now binds to the v3 names.
  • crates/thetadatadx/src/flatfiles/decoded_row.rsFlatFileRow.symbol.
  • crates/thetadatadx/src/flatfiles/index.rsIndexEntry.symbol, IndexEntry.expiration.
  • crates/thetadatadx/src/flatfiles/writer.rs — flat-file CSV / JSONL
    contract-prefix headers go from root,expiration,... to symbol,expiration,....

Schema + generators

  • crates/thetadatadx/tick_schema.tomlOptionContract column renamed.
  • crates/thetadatadx/build_support/fpss_events/{python,typescript,go_structs,ffi_rust,ffi_c}.rs
    emit Contract.symbol / Contract.expiration on every binding +
    the regenerated FFI converter stages a contract_symbol_cstring.
  • crates/thetadatadx/build_support/ticks/go.rs updates the
    OptionContract source-expression dispatch.
  • crates/thetadatadx/build_support/sdk_surface/templates/go/next_event_body.go.tmpl
    reads c.symbol / c.expiration off the C ABI struct and assigns
    Symbol / Expiration on the Go-side *Contract.
  • crates/thetadatadx/build_support/endpoints/render/templates/cpp/option_contracts_convert.cpp.tmpl
    assigns c.symbol on the C++ OptionContract value type.

Regenerated bindings

  • ffi/src/{fpss_event_structs,fpss_event_converter,types,streaming}.rs.
  • sdks/python/src/{fpss_event_classes,tick_classes,tick_arrow}.rs.
  • sdks/typescript/src/{fpss_event_classes,tick_classes}.rs + index.d.ts.
  • sdks/go/{fpss_event_structs,fpss_event_structs.h.inc,fpss_methods,tick_converters,tick_ffi_mirrors,tick_structs}.go.
  • sdks/cpp/include/{thetadx.h,thetadx.hpp,fpss_event_structs.h.inc} + sdks/cpp/src/historical.cpp.inc.
  • crates/thetadatadx/src/frames_generated.rs.
  • tools/cli/src/raw_headers_generated.rs.

Tools + outputs

  • tools/{cli,mcp,server} — option-contract rendering reads .symbol,
    REST + MCP + WS JSON outputs emit "symbol" / "expiration" keys
    on every contract payload, the WS regression test pins the symbol key.

CHANGELOG + docs

  • CHANGELOG.md and docs-site/docs/changelog.md get a [8.0.25] - 2026-05-04
    entry under ### Changed citing the vendor migration guide and
    including a Rust migration snippet for downstream consumers.
  • docs-site/docs/{getting-started,streaming}/*.md examples updated to
    use contract.symbol / contract.expiration. The historical
    CHANGELOG entries (feat(v8): parsed Contract on every FPSS event + ergonomics + control codes 4/10/13/31 #389 v8.0.0) are intentionally preserved verbatim.

The wire format is unchanged. The decoder still resolves both v2 and
v3 response columns through the existing ("root", "symbol") alias
in crates/thetadatadx/src/decode.rs.

Test plan

Local CI gate (all five passing):

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace
  • cargo deny check
  • cargo run -p thetadatadx --bin generate_sdk_surfaces --features config-file -- --check

Plus the same checks on every sub-workspace (sdks/python, sdks/typescript,
tools/server, tools/mcp).

userFRM added 5 commits May 4, 2026 23:43
Match the v3 vendor surface for the public OptionContract field. The
binary wire format is unchanged. See:
https://docs.thetadata.us/Articles/Getting-Started/v2-migration-guide.html#_5-parameter-mapping

Closes #467
…t and exp_date

- Contract.root -> .symbol, Contract.exp_date -> .expiration on the
  fpss::protocol public type.
- Contract::stock / index / rate / option / option_raw constructors
  rename their first positional parameter to symbol; option() renames
  exp_date to expiration.
- FlatFileRow.root -> .symbol; flat-file CSV / JSONL contract-prefix
  headers go from "root,expiration,..." to "symbol,expiration,...".
- IndexEntry.root -> .symbol, IndexEntry.exp -> .expiration (crate-
  private, but mirrored for consistency).
- tick_schema.toml updates the OptionContract column from root to
  symbol so every generator-emitted SDK surface follows.
- Internal byte-level decoder locals keep the wire-spec names (root /
  exp_date) so the parser still diffs cleanly against the upstream
  binary protocol; the public field assignments use the v3 names.

Closes #467
Update the per-language emitters under crates/thetadatadx/build_support
so the regenerated SDK output uses the v3 vendor field names:

- fpss_events::python emits Contract.symbol / Contract.expiration on
  the pyo3 #[pyclass].
- fpss_events::typescript emits Contract.symbol / Contract.expiration
  on the napi-rs #[napi(object)] struct.
- fpss_events::go_structs emits Contract.Symbol / Contract.Expiration
  on the Go SDK struct.
- fpss_events::ffi_rust + ffi_c emit TdxContract.symbol /
  TdxContract.has_expiration / TdxContract.expiration on the C ABI
  mirror; the converter stages the CString as
  contract_symbol_cstring and reads contract.symbol /
  contract.expiration off the core type.
- ticks::go updates the OptionContract source-expression dispatch to
  emit symbol-keyed Go converters.
- The Go cgo template (next_event_body.go.tmpl) and the C++
  option_contracts_convert template assign .symbol on the Go /
  C++ public types instead of .root.

Closes #467
Carries the v3 surface rename through every committed generator output
plus a handful of hand-written companion files:

- ffi/src: TdxContract.symbol / .has_expiration / .expiration in
  fpss_event_structs.rs; TdxOptionContract.symbol in types.rs; the
  fpss_event_converter passes contract.symbol / contract.expiration
  through to the C ABI structs; streaming.rs tracing fields use
  symbol = %contract.symbol.
- sdks/python/src: regenerated Contract pyclass + OptionContract
  pyclass + tick_arrow column buffers use symbol / expiration.
- sdks/typescript/src + index.d.ts: regenerated Contract napi struct +
  OptionContract napi struct + dispatcher arms use symbol / expiration;
  the TypeScript declaration mirrors the renamed fields.
- sdks/go: regenerated fpss_event_structs.go (Contract.Symbol /
  Contract.Expiration), fpss_event_structs.h.inc, fpss_methods.go,
  tick_converters.go, tick_structs.go (OptionContract.Symbol). The
  hand-written tick_ffi_mirrors.go cOptionContract mirror is updated
  to match the new C ABI field name.
- sdks/cpp: thetadx.h TdxOptionContract.symbol; thetadx.hpp
  OptionContract.symbol with updated layout-asserts comment;
  fpss_event_structs.h.inc TdxContract.symbol /
  TdxContract.has_expiration / .expiration; historical.cpp.inc
  reads c.symbol off the C ABI struct.
- tools/cli, tools/mcp, tools/server: option-contract rendering uses
  the new symbol field; REST + MCP + WS JSON outputs emit
  "symbol" / "expiration" keys on every contract payload; the WS
  format snapshot regression test pins the symbol key.
- crates/thetadatadx/src/frames_generated.rs: regenerated
  OptionContract Arrow / Polars column emitters use col_symbol and
  the "symbol" Field name.

Closes #467
Patch bump on the v8 line (v8 is patch-only on every change). Updates
the workspace + every sub-workspace + every package.json + the cpp
CMakeLists.txt project version, refreshes Cargo.lock everywhere, and
adds the 8.0.25 entry to CHANGELOG.md and docs-site/docs/changelog.md
naming the renamed fields and citing the vendor v3 migration guide.

Doc-site streaming / quickstart pages updated to use contract.symbol /
contract.expiration in the example callbacks; CHANGELOG history is
preserved verbatim (v8.0.0 release notes still describe the
historical contract.root surface).

Closes #467
userFRM added a commit that referenced this pull request May 5, 2026
PR #470 ships before PR #468; reclaim the next sequential patch
(8.0.25) so release tags stay chronological. PR #468 will be
rebased to 8.0.26 once this lands.
userFRM added a commit that referenced this pull request May 5, 2026
* fix(fpss): treat Windows ERROR_IO_PENDING as transient read

On Windows the overlapped socket layer surfaces in-flight reads as
ERROR_IO_PENDING (raw OS error 997) rather than WSAEWOULDBLOCK. Rust
std maps 997 to ErrorKind::Uncategorized, so the existing kind matches
in fpss/io_loop.rs::is_read_timeout and the two retry arms in
fpss/framing.rs (pre-header and mid-payload) treated it as fatal.
Python users on Windows saw FPSS read error error=IO error: Overlapped
I/O operation is in progress. (os error 997) spam followed by a
reconnect storm.

Centralise transient-read detection in framing::is_transient_read,
which matches WouldBlock | TimedOut plus raw_os_error() == Some(997)
(ERROR_IO_PENDING). All three sites delegate to it so the I/O loop
drains queued commands and retries the way it does on Linux and macOS.

Tests: unit test pinning the helper on os_error(997), plus three
integration-style tests against the existing mock readers covering the
pre-header propagate-as-Io path and the mid-header / mid-payload
retry-and-recover paths under raw OS error 997.

Bumps tdbe 0.12.5 -> 0.12.7 and the workspace 8.0.24 -> 8.0.26.

Closes #469

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

* release: rebump to 8.0.25 (tdbe 0.12.6) — chronological release order

PR #470 ships before PR #468; reclaim the next sequential patch
(8.0.25) so release tags stay chronological. PR #468 will be
rebased to 8.0.26 once this lands.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@userFRM
Copy link
Copy Markdown
Owner Author

userFRM commented May 6, 2026

Superseded by PR #484. Original branch could not be rebased onto the SSOT refactor (#475) cleanly because OptionContract is now schema-driven; #484 is the schema-first redo.

@userFRM userFRM closed this May 6, 2026
@userFRM userFRM deleted the fix/467-rename-root-symbol branch May 6, 2026 08:21
@userFRM
Copy link
Copy Markdown
Owner Author

userFRM commented May 6, 2026

Superseded by PR #484 — original branch could not be rebased onto the SSOT refactor.

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.

fix(public-api): rename root → symbol and exp_date → expiration to match v3 vendor surface

1 participant