johnnybt-trading
Runtime foundation for the johnnybt trading systems.
Four capabilities over one Tokio runtime, so a Python trading process gets
concurrency without Python threads and without Python subprocesses: a timer, an
embedded RESP server, an HTTP server, and async SQLite with a SQLAlchemy
dialect. Everything asynchronous returns an ordinary awaitable, so it composes
with asyncio like any other library.
There are no Python dependencies. Every capability is compiled into the extension module — a foundation that dragged a web framework and a database driver in behind it would not be a foundation.
pip install johnnybt-trading
# the SQLAlchemy dialect is optional
pip install "johnnybt-trading[sqlalchemy]"
Requires Python 3.14. That is the only version this is built against and
tested on; the extension is compiled abi3, but nothing below 3.14 is claimed
or supported.
Prebuilt wheels: Linux (x86_64, aarch64, musl x86_64), macOS (x86_64, arm64), Windows (x64) — one wheel per platform.
Timer
every ticks in Rust. A callback that runs long is a measured skip, not a
silent drift, and never an overlapping run — the counters say which happened.
import johnnybt_trading as jbt
handle = jbt.every(0.2, tick, on_error=report, fire_immediately=True)
...
print(handle.fired, handle.skipped, handle.failed)
await handle.stop()
RESP server
RedisServer speaks enough Redis to be a real one to a client that cannot
install anything to speak something else — which is the situation when the
process on the far side is a broker terminal.
server = jbt.RedisServer(bind="127.0.0.1:6381", password=None, databases=16)
address = await server.start()
...
await server.stop()
Pub/sub is on the same object: server.publish(channel, payload) and
server.subscribe(channel). A slow subscriber loses its oldest message rather
than stalling the publisher.
HTTP server
Axum routing into Python coroutine handlers, plus a static directory served straight off disk.
server = jbt.HttpServer(bind="127.0.0.1:8080", on_error=report)
server.route("GET", "/healthz", lambda request: jbt.Response(200, b"ok"))
# Big files never enter Python: Range, conditional GET and compression for free.
server.static_dir("/assets", "dist/assets", cache_seconds=31536000, immutable=True)
address = await server.start()
SQLite
One connection per actor thread, ?-style parameters, and an event log that
lives in the same database — which is what lets an event and the fact it
describes commit together.
db = await jbt.connect("trades.db")
await db.execute("CREATE TABLE fills (id INTEGER PRIMARY KEY, code TEXT)")
await db.execute("INSERT INTO fills (code) VALUES (?)", ["002105.SZ"])
await db.create_event_schema()
await db.append_event("orders", "filled", b'{"code": "002105.SZ"}')
for event in await db.read_events("orders", after=0):
...
The SQLAlchemy async dialect registers itself, so sqlite+jbt:// resolves
without an explicit call:
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("sqlite+jbt:///trades.db")
Pub/sub or event log?
Both ship, and they answer different questions. Pub/sub tells whoever is listening now — nothing is kept, a subscriber that was not there missed it. The event log tells whoever reads later — appended in order, read from a cursor, and durable in the same transaction as the change it describes.
Development
uv sync --all-extras --dev
uv run maturin develop --uv
uv run pytest
cargo test --lib
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file johnnybt_trading-0.1.0.tar.gz.
File metadata
- Download URL: johnnybt_trading-0.1.0.tar.gz
- Upload date:
- Size: 128.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15d995569eaca5aa0e9c006c4d871317db53829470155cdeef2f0f636482121b
|
|
| MD5 |
a874fb153f984373f2d84c1e07f971fd
|
|
| BLAKE2b-256 |
a505dde7bc94a371e5c3d2b625657b24422819e45d6b0cb030862e415e41283d
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 2.8 MB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec87cb9a82fa28d6fee35165bb6f3f96b2f1fb33e396c3411313108f61e18991
|
|
| MD5 |
cce16dee494ae35d7faff4bd4e09eac5
|
|
| BLAKE2b-256 |
46f35a080a41b13c03f4697ffae29f6da20b0c686748b2187f582e254fd48795
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.11+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4da840c71ee111862417beb1380962e532ef8dcc675d2dd20d12f26efe2562f5
|
|
| MD5 |
ddb4172429ec88cd00b231cf3e8f788c
|
|
| BLAKE2b-256 |
4d5ffc033038327e6fa1d6c51ba0bb0a58ebf549be31557d9d2132fa73657290
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 2.9 MB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3d9c8adf1d6c4147ac15dcc313e9dc7cb34b1579007651e80f61d18ab66a118
|
|
| MD5 |
5000245bb0b94775ebb04bf723161af5
|
|
| BLAKE2b-256 |
8285c44f6a66cd1aab7cfeaf568aa65c69140935b6d4cbcc1b6b4790fedbc2b7
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 2.8 MB
- Tags: CPython 3.11+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
858bdeadf373eeba371e34e822d2229b465038f8494cf857618886e4b1ea0d79
|
|
| MD5 |
a2821cc8451a51082e4b90e4594fc74d
|
|
| BLAKE2b-256 |
f6aedfb2b1870eaea1714b280dc78965e7493d9e8ad57a1a5ea0ee5aa55057ae
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.7 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d13b1c3ff1fda793496b5f1cf8d3c335dca144cd84552e506f0aa46b09ad12b
|
|
| MD5 |
c2018be7bb611ebcf703b9c1da3a0e41
|
|
| BLAKE2b-256 |
0d46e57ba45540de339b3f5c4f5246c320cb90c850e8c72e0c962b3635fec716
|
File details
Details for the file johnnybt_trading-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: johnnybt_trading-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 2.8 MB
- Tags: CPython 3.11+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f416c8ac609737f1f91ba96a736bad7b0b1f05cd9c32618e1e41b0c41fcc9f38
|
|
| MD5 |
37c6bf4db2ad186bf2ebc661fc104992
|
|
| BLAKE2b-256 |
a4e5539e5814f2e77ff9b80175957a244a91904f41b600bcb8b5e9ada9c9426f
|