Open-source project
electkismet/eltdx avatar
electkismet/eltdx

eltdx: a Tongdaxin market data client with a Rust core

通达信A股行情协议 Python 库,MCP,支持快照、分时、逐笔、K 线、集合竞价、特殊指标等接口。适合作为量化数据源,支持其他语言通过HTTP或WebSocket调用

628 stars245 forksRustNOASSERTION

At a glance

What is it?
eltdx exposes the Tongdaxin quote protocol for A-share market data to Python, with the 7709 command handling, connection pool, push handling and heartbeats implemented in Rust. It ships MCP tools and an HTTP and WebSocket gateway for other languages, and it is licensed for non-commercial research only.
Who is it for?
eltdx suits a researcher or hobbyist building local quantitative tooling against A-share data who wants a maintained protocol implementation, typed models and a path to expose the data to an editor or agent through MCP. It does not suit a commercial product, a paid service or anything that resells the data, because the bundled licence is a non-commercial research licence rather than an open source grant.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A protocol client, not a data vendor

eltdx is a Python library for the Tongdaxin online quote protocol, aimed at A-share research. It fetches quotes, intraday minute data, transaction detail, K lines, call auction data, company information and theme or sector information, and it can expose those through MCP tools.

The architecture changed substantially in version 3.0. The README states that 3.0 keeps the existing Python API and return models while moving the core of 21 commands into Rust: the 7709 command packing and parsing, the connection pool, pin handling, push frames, heartbeats and shutdown. In other words, the Python surface you program against stayed stable while the wire handling was rewritten in a systems language.

That split is the interesting engineering claim. Python remains the language of the API and of the models, so notebooks and scripts read naturally, but the connection management and the byte level protocol work happen in Rust. The repository reflects that literally: the top level holds Cargo.toml, Cargo.lock, rust-toolchain.toml, a src/ directory for the Python side, a crates/ directory for the Rust side, and pyproject.toml for the package metadata.

The project also names its own inspirations, thanking two earlier Python implementations of the same protocol.

The licence forbids the commercial use most products would want

This is the first thing to read, because the badge on the README says Non-Commercial Research License and the terms are specific.

The project states it is developed only for personal learning, protocol compatibility and data parsing research. The project itself, derived products, and data obtained through the project are prohibited from being used for any commercial activity, for paid services, for production services, for resale, or for any other commercial purpose, and the user bears any data, loss or legal responsibility that results. Access to third party servers and services is the user's own responsibility under the relevant law and service agreements, and the project must not be used to infringe rights, violate regulations or abuse third party services.

The licence field is a custom one that GitHub cannot classify, and the terms live in the LICENSE file at the repository root. There is no open source grant here in the usual sense, and no version of the Apache, MIT or BSD text applies. That is a deliberate position rather than an oversight, and it is defensible for a project that speaks a commercial vendor's protocol, but it means the answer to can I ship this in my product is written in the LICENSE file and not in the README's feature list.

The Apache style permissiveness you might expect from a modern Python library is simply not there, even though the package is typed, and no legal reading of these terms is offered here.

Installing: wheels first, Rust only as a fallback

The normal install is a single command, and the point of the packaging is that most people never need a Rust toolchain.

bash
pip install eltdx

Version 3.0 publishes five cp310-abi3 wheels covering CPython 3.10 to 3.14 on Windows x64, manylinux x64 and ARM64, and macOS x64 and ARM64. When one of those wheels matches your platform you do not need Rust installed at all.

The fallback is a source build, and the README is direct about the cost. A platform with no matching wheel attempts to compile from the sdist, which needs a Rust 1.89 toolchain, and 3.0 does not provide a pure Python 7709 fallback. PyPy, free threaded CPython, musllinux and other unlisted combinations are outside the launch support range.

That last point has a practical consequence for CI. If your build matrix includes musllinux or a free threaded interpreter, this package will not install from a wheel there, and there is no pure Python path to fall back to. The alternatives are to exclude those platforms from the matrix or to build the extension yourself, which means carrying a Rust toolchain in the image.

The package declares requires-python of 3.10 or newer and ships no runtime dependencies at all, with dependencies listed as an empty list.

Two optional extras: MCP tools and a cross language gateway

The default install is a library and nothing else. The README states that pip install eltdx does not install FastAPI or Uvicorn and does not start any additional service.

If you want the MCP stdio tool server, you add the optional dependency.

bash
pip install "eltdx[mcp]"

Once started, the MCP tool server occupies the current terminal as a stdio service, launched with the eltdx-mcp entry point. It exposes common quote, F10, auction and documentation capabilities to MCP clients, which is how an editor or agent can query market data through the same client.

For callers in Java, Go, C# or Node.js, the gateway extra is the route, and it comes with a command you run.

bash
pip install "eltdx[http]"
eltdx-http

That gateway is a FastAPI service offering HTTP JSON, WebSocket RPC and real time subscriptions, so other languages can call the same data source without reimplementing the protocol. The distinction between the extras is worth keeping straight: mcp adds the tool server, http adds the network gateway, and neither is installed by default.

Source installs compile a private native extension

The development path is documented for anyone who wants to work on the code rather than consume it.

bash
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -U pip
pip install -e ".[dev,mcp]"

The important consequence is stated in the README: a source install compiles the private extension eltdx._native, and if the Python files and the native binary have mismatched ABI, the import fails immediately rather than silently falling back to an older implementation. That is a good failure mode. A silent fallback would let you run against a stale engine without noticing.

There is a second warning that will save somebody an afternoon. When developing from source you should always install into the current virtual environment first, because if an older eltdx is already present on the machine, a python -m eltdx... invocation may import the old package from site-packages instead of your working copy.

For a quick check after installing, the README points at two smoke command entry points.

bash
eltdx-smoke --help
eltdx-f10-smoke --help

And for a source checkout, the test suite is run with pytest.

bash
python -m pytest

The API is organised by the data you want, not by command

The feature map is the clearest documentation in the project, and it is organised around research tasks. Ordinary calls use the modular API and the Helpers, and the native 7709 commands and 7615 entries are what you read when you need to check a low level field.

The layers run Python and MCP, then the modular API and Helpers, then the native 7709 protocol or 7615 entry, then dataclasses, push frames and JSON.

The task list covers the stock universe including the latest stock list, ST names, suspended names and the code table, category quotes by market or sector, full realtime quotes with the complete five level depth, sector quotes and their member quotes, the incremental depth refresh and the push queue that reads unmatched realtime frames, K lines across minute, daily, weekly, monthly, quarterly and yearly periods with automatic paging and forward, backward or fixed point adjustment, delisted stock daily bars, intraday minute prices with volume and average price, the merged full transaction detail for the day, call auction data including the 09:25 match, capital change and ex-dividend records, financial basics, locally computed adjustment factors, special instrument limit tables, F10 company profiles, stock theme membership, a combined stock profile table, short line indicators, daily rankings, and chunked server file downloads.

The table also records where each call goes. Most read the 7709 native protocol, the F10 company profile uses a 7615 native entry, board quotes use the 0x06b9, 0x044d and 0x054c commands, delisted bars use 0x052B, and the local adjustment factors are computed locally under 0x000f. Connection management, the Rust connection pool, heartbeat, pin, push, cache and diagnostics sit in the Rust engine.

The Python package registers four console scripts: eltdx-smoke, eltdx-f10-smoke, eltdx-mcp and eltdx-http.

The Rust workspace and its lint policy

The Rust side is a cargo workspace with three members.

toml
[workspace]
resolver = "2"
members = [
  "crates/eltdx-protocol",
  "crates/eltdx-runtime",
  "crates/eltdx-python",
]

The division is by responsibility: the protocol crate, the runtime crate and the Python binding crate. The workspace package version is 3.2.3, the edition is 2021 and the minimum Rust version is 1.89, which matches the toolchain the README asks for when compiling from source.

The lint configuration is strict in a way that tells you something about the maintainers.

toml
[workspace.lints.rust]
unsafe_code = "forbid"

[workspace.lints.clippy]
dbg_macro = "deny"
todo = "deny"
unimplemented = "deny"
unwrap_used = "deny"
expect_used = "deny"

Unsafe code is forbidden outright, and the clippy lints deny leftover debug macros, todo markers, unimplemented branches, unwrap calls and expect calls. For a crate that parses bytes off the network and hands them to Python objects, banning panic paths in the parsing code is a meaningful choice rather than a stylistic one.

The dependency versions are pinned exactly, with tokio pulled in for the async runtime and pyo3 for the Python bindings. The Python package is built with maturin as the build backend, using the crates/eltdx-python manifest, with the Python source directory as src and the extension module named eltdx._native with pyo3 bindings.

Version history, breaking changes and the successor project

The recent releases are v3.2.1 and v3.2.2 on 2026-09-12 and v3.2.3 on 2026-10-05, and the last push to the repository was on 2026-10-21. The repository is not archived, and the release line is moving in step with the 3.x rewrite.

One earlier breaking change is documented in the README. Version 2.0.0 removed the legacy flat entry points of TdxClient and unified everything on the modular API and the Helpers, and the README advises reading the v2.0.0 migration notes before upgrading. That is the pattern to expect from this project: major versions reorganise the entry points, and the migration is documented separately.

The author also points at a successor project, AxData, which was iterated from eltdx and adds plugin based access to exchange, regulatory filing, financial portal and news sources on top of the Tongdaxin family, together with more local research oriented indicators. The recommendation in the README is that people who only need one source should stay with eltdx, because the AxData architecture is slower than eltdx's bare protocol path.

That is a useful piece of engineering judgement rather than marketing. The specialised client is faster because it does one thing, and the moment you need several sources you accept a plugin layer's overhead.

Editorial conclusion

eltdx suits a researcher or hobbyist building local quantitative tooling against A-share data who wants a maintained protocol implementation, typed models and a path to expose the data to an editor or agent through MCP. It does not suit a commercial product, a paid service or anything that resells the data, because the bundled licence is a non-commercial research licence rather than an open source grant. Verify first that your platform has a matching wheel for CPython 3.10 to 3.14, since the 3.0 line has no pure Python fallback and an unmatched platform must compile the Rust extension from source.

Frequently asked questions

Do I need Rust installed to use eltdx?

Only if no published wheel matches your platform. Version 3.0 ships cp310-abi3 wheels for CPython 3.10 to 3.14 on Windows x64, manylinux x64 and ARM64, and macOS x64 and ARM64, and matching a wheel means no Rust toolchain is needed. Otherwise the sdist is compiled and needs a Rust 1.89 toolchain.

Which Python versions does eltdx support?

The package declares requires-python of 3.10 or newer, and the classifiers list Python 3.10 through 3.14. PyPy, free threaded CPython and musllinux are outside the launch support range.

Can I use eltdx from a language other than Python?

Yes. Install the http extra with pip install "eltdx[http]" and run eltdx-http to start a FastAPI based gateway offering HTTP JSON, WebSocket RPC and real time subscriptions for callers in Java, Go, C#, Node.js and similar languages.

What does the eltdx licence allow?

It is a non-commercial research licence. The project is for personal learning, protocol compatibility and data parsing research, and the project, derived products and the data obtained through it may not be used for commercial activity, paid services, production services, resale or other commercial purposes.

How do I run the MCP tool server for eltdx?

Install the mcp extra with pip install "eltdx[mcp]" and run eltdx-mcp. The README notes that the started tool service occupies the current terminal as a stdio service.

Official sources

  1. electkismet/eltdx on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/electkismet-eltdx.svg)](https://hysenlabs.com/projects/electkismet-eltdx)

Was this useful?