Rust implementation of Shioaji trading API for Taiwan financial markets
Project description
Shioaji Python Bindings
Python bindings for the high-performance rshioaji Rust library - a next-generation client for Taiwan stock market data.
Features
- High Performance: Built on the Rust rshioaji core library for maximum throughput
- Type Safe: Full type annotations and comprehensive error handling
- Real-time Data: Support for stock ticks, bid/ask quotes, and futures/options data
- Multi-exchange: TSE, OTC, OES, and TAIFEX support
- Sync & Async: Both synchronous and asynchronous clients available
- Callback Support: Register callbacks for real-time data processing
Installation
Development Install (from source)
# Clone the repository
git clone <repository-url>
cd rshioaji/python
# Build and install with uv
uv build
uv run python examples/snapshot.py
Production Install (when published)
pip install shioaji
Quick Start
Sync Client
import shioaji
# Create client in simulation mode
api = shioaji.Shioaji(simulation=True)
# Login
api.login("your_api_key", "your_secret_key")
# Create a contract for Taiwan Semiconductor (2330)
contract = shioaji.BaseContract("STK", "TSE", "2330")
# Get snapshots
snapshots = api.snapshots([contract])
for snap in snapshots:
print(f"{snap.code}: {snap.close}")
# Subscribe to real-time tick data
api.subscribe(contract, "tick")
Async Client
import asyncio
import shioaji
async def main():
api = shioaji.ShioajiAsync(simulation=True)
await api.login("your_api_key", "your_secret_key")
contract = shioaji.BaseContract("STK", "TSE", "2330")
snapshots = await api.snapshots([contract])
await api.subscribe(contract, "tick")
asyncio.run(main())
API Reference
Shioaji (Sync Client)
class Shioaji:
def __init__(self, simulation: bool = False, proxy: str = None)
# Auth
def login(self, key: str, secret_key: str) -> List[Account]
def logout(self) -> None
def usage(self) -> UsageOut
def list_accounts(self) -> List[Account]
# Data
def snapshots(self, contracts: List[BaseContract], timeout: int = 30) -> List[Snapshot]
# Stream
def subscribe(self, contract: BaseContract, quote_type: str, intraday_odd: bool = False)
def get_tick_stk_v1_receiver(self) -> TickSTKv1Receiver
def get_bidask_stk_v1_receiver(self) -> BidAskSTKv1Receiver
def get_tick_fop_v1_receiver(self) -> TickFOPv1Receiver
def get_bidask_fop_v1_receiver(self) -> BidAskFOPv1Receiver
# Callbacks
def set_on_tick_stk_v1_callback(self, callback: Callable[[TickSTKv1], None])
def set_on_bidask_stk_v1_callback(self, callback: Callable[[BidAskSTKv1], None])
def set_on_tick_fop_v1_callback(self, callback: Callable[[TickFOPv1], None])
def set_on_bidask_fop_v1_callback(self, callback: Callable[[BidAskFOPv1], None])
def clear_on_tick_stk_v1_callback(self)
def clear_on_bidask_stk_v1_callback(self)
def clear_on_tick_fop_v1_callback(self)
def clear_on_bidask_fop_v1_callback(self)
ShioajiAsync (Async Client)
class ShioajiAsync:
def __init__(self, simulation: bool = False, proxy: str = None)
# Auth (all async)
async def login(self, key: str, secret_key: str) -> List[Account]
async def logout(self) -> None
async def usage(self) -> UsageOut
async def list_accounts(self) -> List[Account]
# Data (all async)
async def snapshots(self, contracts: List[BaseContract], timeout: int = 30) -> List[Snapshot]
# Stream (all async)
async def subscribe(self, contract: BaseContract, quote_type: str, intraday_odd: bool = False)
async def get_tick_stk_v1_receiver(self) -> TickSTKv1Receiver
async def get_bidask_stk_v1_receiver(self) -> BidAskSTKv1Receiver
BaseContract
class BaseContract:
def __init__(self, security_type: str, exchange: str, code: str, target_code: str = None)
# Properties
security_type: str # "STK", "FUT", "OPT", "IND"
exchange: str # "TSE", "OTC", "OES", "TAIFEX"
code: str # Security code (e.g., "2330")
target_code: str # Optional target code
Snapshot
class Snapshot:
ts: int # Timestamp
code: str # Security code
exchange: str # Exchange
open: float # Open price
high: float # High price
low: float # Low price
close: float # Close price
tick_type: TickType # Buy/Sell/None
change_price: float # Price change
change_rate: float # Change rate
change_type: ChangeType # LimitUp/Up/Unchanged/Down/LimitDown
volume: int # Volume
total_volume: int # Total volume
Stream Data Types
class TickSTKv1:
exchange: Exchange
code: str
date: tuple[int, int, int] # (year, month, day)
time: tuple[int, int, int, int] # (hour, minute, second, microsecond)
close: str
volume: int
tick_type: int
simtrade: bool
class BidAskSTKv1:
exchange: Exchange
code: str
bid_price: List[str]
bid_volume: List[int]
ask_price: List[str]
ask_volume: List[int]
Examples
Callback-based Real-time Data
import shioaji
api = shioaji.Shioaji(simulation=True)
api.login("api_key", "secret_key")
def on_tick(tick):
print(f"Tick: {tick.code} @ {tick.close}")
def on_bidask(bidask):
print(f"BidAsk: {bidask.code} Bid={bidask.bid_price[0]}")
api.set_on_tick_stk_v1_callback(on_tick)
api.set_on_bidask_stk_v1_callback(on_bidask)
contract = shioaji.BaseContract("STK", "TSE", "2330")
api.subscribe(contract, "tick")
api.subscribe(contract, "bid_ask")
# Callbacks run in background threads
import time
time.sleep(60)
Receiver-based Data Polling
import shioaji
api = shioaji.Shioaji(simulation=True)
api.login("api_key", "secret_key")
contract = shioaji.BaseContract("STK", "TSE", "2330")
api.subscribe(contract, "tick")
receiver = api.get_tick_stk_v1_receiver()
# Poll for data
while True:
tick = receiver.try_recv()
if tick:
print(f"Tick: {tick.code} @ {tick.close}")
Snapshots
import shioaji
api = shioaji.Shioaji(simulation=True)
api.login("api_key", "secret_key")
contracts = [
shioaji.BaseContract("STK", "TSE", "2330"), # TSMC
shioaji.BaseContract("STK", "TSE", "2317"), # Hon Hai
shioaji.BaseContract("FUT", "TAIFEX", "TXFB6"), # Futures
]
snapshots = api.snapshots(contracts)
for snap in snapshots:
print(f"{snap.code}: close={snap.close}, volume={snap.total_volume}")
Supported Markets
| Exchange | Description |
|---|---|
| TSE | Taiwan Stock Exchange |
| OTC | Over-the-Counter |
| OES | Order Entry System |
| TAIFEX | Taiwan Futures Exchange |
Quote Types
| Type | Description |
|---|---|
| tick | Real-time transaction data |
| bid_ask | Best bid/ask quotes |
Security Types
| Type | Description |
|---|---|
| STK | Stocks |
| FUT | Futures |
| OPT | Options |
| IND | Indices |
Performance Optimization
Latency Comparison
Based on our benchmarks (120s, ~88 FOP ticks):
| Method | P50 Latency | Notes |
|---|---|---|
try_recv() polling |
Fastest | Tight loop, highest CPU |
| Sync callback | ~5µs slower | Dedicated thread |
| Async + uvloop | ~6µs slower | Recommended for async |
| Async (default) | ~136µs slower | Default asyncio overhead |
Using uvloop (Recommended for Async)
For async users, we strongly recommend using uvloop to eliminate asyncio event loop overhead:
# Install uvloop
pip install uvloop
# or with uv
uv add uvloop
import asyncio
import uvloop
import shioaji
# Install uvloop before running async code
uvloop.install()
async def main():
api = shioaji.ShioajiAsync()
await api.login("api_key", "secret_key")
contract = shioaji.BaseContract("STK", "TSE", "2330")
await api.subscribe(contract, "tick")
receiver = await api.get_tick_stk_v1_receiver()
while True:
tick = await receiver.recv()
print(f"Tick: {tick.code} @ {tick.close}")
asyncio.run(main())
Low-Latency Options
For the lowest latency requirements:
Option 1: Sync Callback (Simple)
api = shioaji.Shioaji()
api.set_on_tick_stk_v1_callback(on_tick)
api.subscribe(contract, "tick")
Option 2: try_recv() Polling (Fastest)
receiver = await api.get_tick_stk_v1_receiver()
while True:
tick = receiver.try_recv() # Non-blocking, bypasses asyncio
if tick:
process(tick)
Latency Sources
Data Flow (Async recv):
Solace → Rust Parser → kanal channel → future_into_py → asyncio → Python
│
┌─────────┴─────────┐
│ Latency Source │
├───────────────────┤
│ call_soon_threadsafe (~50µs)
│ Python event loop scheduling (~50µs)
│ asyncio.Future callback (~20µs)
└───────────────────┘
│
uvloop optimizes this entire section
to ~5µs total
Development
Building from Source
cd python
# Build the package
uv build
# Run example
uv run python examples/snapshot.py
uv run python examples/callback.py
Architecture
The Python bindings are built using:
- PyO3: Rust-Python FFI bindings
- maturin: Build tool for Rust-based Python extensions
- Tokio: Async runtime for handling real-time data streams
- rshioaji: Core Rust library for market data processing
License
This project is licensed under the same terms as the main rshioaji project.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 rshioaji-1.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rshioaji-1.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 35.8 MB
- Tags: CPython 3.14t, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a75a762695d76f9c8c89ae6fd2cdb625a8c106a7b89e69c2144feef375aa4bc8
|
|
| MD5 |
b8e0d7feb51084b03fd47a6d8d3865b2
|
|
| BLAKE2b-256 |
579fcd8c9dc8bdb8ec9a98cea37438f4ffdef893206e799461145f034916dcc2
|
Provenance
The following attestation bundles were made for rshioaji-1.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on Sinotrade/rshioaji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rshioaji-1.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
a75a762695d76f9c8c89ae6fd2cdb625a8c106a7b89e69c2144feef375aa4bc8 - Sigstore transparency entry: 1251998993
- Sigstore integration time:
-
Permalink:
Sinotrade/rshioaji@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Sinotrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rshioaji-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl.
File metadata
- Download URL: rshioaji-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl
- Upload date:
- Size: 31.4 MB
- Tags: CPython 3.14t, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8ddfa9144c15e2a01aca1d642618797189d6dd48c210cc1d37d42d353654e75
|
|
| MD5 |
578f73a3327dda8c45e87f42dd7b02d1
|
|
| BLAKE2b-256 |
312d850f397518400b4eb3113dd3621a5a9f9e11fbd577cdc6a83de755f52e63
|
Provenance
The following attestation bundles were made for rshioaji-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl:
Publisher:
release.yml on Sinotrade/rshioaji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rshioaji-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl -
Subject digest:
a8ddfa9144c15e2a01aca1d642618797189d6dd48c210cc1d37d42d353654e75 - Sigstore transparency entry: 1251999110
- Sigstore integration time:
-
Permalink:
Sinotrade/rshioaji@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Sinotrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rshioaji-1.5.1-cp37-abi3-win_amd64.whl.
File metadata
- Download URL: rshioaji-1.5.1-cp37-abi3-win_amd64.whl
- Upload date:
- Size: 37.6 MB
- Tags: CPython 3.7+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1aaf3c5a8c77e708e3c5e03476580df87a25dedb6ee3d3749f9b6ff5005be6b
|
|
| MD5 |
c0ed93a2d47474e619a2138b99ee4c24
|
|
| BLAKE2b-256 |
643b6655c740dfc6fa3ebe509bc3d123d78df3fabe0d8d3f2920fd1c848742ce
|
Provenance
The following attestation bundles were made for rshioaji-1.5.1-cp37-abi3-win_amd64.whl:
Publisher:
release.yml on Sinotrade/rshioaji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rshioaji-1.5.1-cp37-abi3-win_amd64.whl -
Subject digest:
d1aaf3c5a8c77e708e3c5e03476580df87a25dedb6ee3d3749f9b6ff5005be6b - Sigstore transparency entry: 1251999238
- Sigstore integration time:
-
Permalink:
Sinotrade/rshioaji@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Sinotrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rshioaji-1.5.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rshioaji-1.5.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 35.8 MB
- Tags: CPython 3.7+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8bf30918938179e87df0555b108153c44a7def2ce32da6c774b90ca9a37f742
|
|
| MD5 |
2c685bba6cf4deb33e5015800edb1164
|
|
| BLAKE2b-256 |
4c00045bf16150677042a9002dd4ce6d9571c0c132515fec827430b2ba72b5f5
|
Provenance
The following attestation bundles were made for rshioaji-1.5.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on Sinotrade/rshioaji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rshioaji-1.5.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
a8bf30918938179e87df0555b108153c44a7def2ce32da6c774b90ca9a37f742 - Sigstore transparency entry: 1251998840
- Sigstore integration time:
-
Permalink:
Sinotrade/rshioaji@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Sinotrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rshioaji-1.5.1-cp37-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: rshioaji-1.5.1-cp37-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 31.4 MB
- Tags: CPython 3.7+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2214c7e4219b15e8f0d7c1312e0dde818689471416f07ddbb242f51d04f5b8a7
|
|
| MD5 |
ff5dac84e623c31af4463c0c7b507dd4
|
|
| BLAKE2b-256 |
f3b1de0d82a81b8d98040dc855c3130719c8dd89dfdf92b5cc140b9483542674
|
Provenance
The following attestation bundles were made for rshioaji-1.5.1-cp37-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on Sinotrade/rshioaji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rshioaji-1.5.1-cp37-abi3-macosx_11_0_arm64.whl -
Subject digest:
2214c7e4219b15e8f0d7c1312e0dde818689471416f07ddbb242f51d04f5b8a7 - Sigstore transparency entry: 1251998689
- Sigstore integration time:
-
Permalink:
Sinotrade/rshioaji@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Sinotrade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d0cecd2c2e096289d663fc9ca3ac732bca3aafa -
Trigger Event:
workflow_dispatch
-
Statement type: