Skip to main content

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

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.

Metadata

Release files for rshioaji 1.5.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for rshioaji 1.5.13
File
rshioaji-1.5.13-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64 Details
rshioaji-1.5.13-cp314-cp314t-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 Details
rshioaji-1.5.13-cp37-abi3-win_amd64.whl CPython 3.7 abi3 Windows x86-64 Details
rshioaji-1.5.13-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.7 abi3 Linux glibc 2.17+ x86-64 Details
rshioaji-1.5.13-cp37-abi3-macosx_11_0_arm64.whl CPython 3.7 abi3 macOS 11.0+ ARM64 Details

Total release size: 179.1 MB

Release files / rshioaji-1.5.13-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rshioaji-1.5.13-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 37.2 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
72ed4232342f1251660c4352da54546b49cd3ff764b0c90c7af32da74d36c308
BLAKE2b-256 checksum
How to use checksums
051f841a03a738fced038967ad09843d47692d268929f56e304857593f6d4c56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 15, 2026.

Transparency log

Release files / rshioaji-1.5.13-cp314-cp314t-macosx_11_0_arm64.whl

Download URL rshioaji-1.5.13-cp314-cp314t-macosx_11_0_arm64.whl
Size 32.8 MB
Tags CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
b95eec4e308b560217b6b32dc641322f458c2e826758e8e91bdcdd1c1ff185d5
BLAKE2b-256 checksum
How to use checksums
045c4602a1c307566e7207f21421330a11e60912c12b46823ab8e310600ee527
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 15, 2026.

Transparency log

Release files / rshioaji-1.5.13-cp37-abi3-win_amd64.whl

Download URL rshioaji-1.5.13-cp37-abi3-win_amd64.whl
Size 39.1 MB
Tags CPython 3.7 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
e5fae84b9f5882499788ea38e3dacff9245153d8d07917464f20406c8e614a15
BLAKE2b-256 checksum
How to use checksums
d8d6c5711e52c00073cd722c4cf34896b223cca1ef88726ecc6393ad56431cd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 15, 2026.

Transparency log

Release files / rshioaji-1.5.13-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rshioaji-1.5.13-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 37.2 MB
Tags CPython 3.7 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
2f3faa0e2a1025b1e256d6407cf1a487c62ed87f06698fec4d4dafb36260b51a
BLAKE2b-256 checksum
How to use checksums
a6ebe2c05d9c6f012207a03c93d08e094beac4cc4452b1a1b148b99edbcbde3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 15, 2026.

Transparency log

Release files / rshioaji-1.5.13-cp37-abi3-macosx_11_0_arm64.whl

Download URL rshioaji-1.5.13-cp37-abi3-macosx_11_0_arm64.whl
Size 32.8 MB
Tags CPython 3.7 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1cf4b8d28c51ffb2d636b8a65602421f010dc33a40e89c2eaeb4c11b982146c9
BLAKE2b-256 checksum
How to use checksums
0d0f119d34f405a58a31ce721ab66c27ad879750e618b642afc136c241dae037
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 15, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page