Real-time position synchronization for Shioaji
Project description
sj_sync
Real-time position synchronization for Shioaji.
Overview
sj_sync provides real-time position tracking using deal callbacks instead of repeatedly calling api.list_positions(). This approach:
- Reduces API calls: Initialize once with
list_positions(), then update via callbacks - More responsive: Positions update immediately when deals are executed
- Tracks all details: Supports cash, margin trading, short selling, day trading, and futures/options
Features
- ✅ Real-time updates via
OrderState.StockDealandOrderState.FuturesDealcallbacks - ✅ Multiple trading types: Cash, margin trading, short selling, day trading settlement
- ✅ Futures/options support: Tracks futures and options positions
- ✅ Yesterday's quantity tracking: Maintains
yd_quantityfor each position - ✅ Automatic cleanup: Removes positions when quantity reaches zero
- ✅ Multi-account support: Properly isolates positions across different accounts
- ✅ Pydantic models: Type-safe position objects
Installation
uv add sj-sync
Or with pip:
pip install sj-sync
Usage
import shioaji as sj
from sj_sync import PositionSync
# Initialize and login
api = sj.Shioaji()
api.login("YOUR_API_KEY", "YOUR_SECRET_KEY")
# Create PositionSync (auto-loads positions and registers callbacks)
sync = PositionSync(api)
# Get all positions
positions = sync.list_positions()
for pos in positions:
print(f"{pos.code}: {pos.direction} {pos.quantity}")
# Get positions for specific account
stock_positions = sync.list_positions(account=api.stock_account)
futures_positions = sync.list_positions(account=api.futopt_account)
# Positions auto-update when orders are filled!
Position Models
StockPosition
class StockPosition(BaseModel):
code: str # Stock code (e.g., "2330")
direction: Action # Action.Buy or Action.Sell
quantity: int # Current position quantity
yd_quantity: int # Yesterday's position quantity
cond: StockOrderCond # Cash, MarginTrading, or ShortSelling
FuturesPosition
class FuturesPosition(BaseModel):
code: str # Contract code (e.g., "TXFJ4")
direction: Action # Action.Buy or Action.Sell
quantity: int # Current position quantity
API Reference
PositionSync
__init__(api: sj.Shioaji)
Initialize with Shioaji API instance. Automatically:
- Loads all positions from all accounts
- Registers deal callback for real-time updates
list_positions(account: Optional[Account] = None, unit: Unit = Unit.Common) -> Union[List[StockPosition], List[FuturesPosition]]
Get current positions.
Args:
account: Account to filter.Noneuses default account (stock_account first, then futopt_account if no stock)unit:Unit.Common(lots) orUnit.Share(shares) - for compatibility, not used in real-time tracking
Returns:
- Stock account:
List[StockPosition] - Futures account:
List[FuturesPosition] None(default): Prioritizes stock_account, falls back to futopt_account
Example:
# Get default account positions
positions = sync.list_positions()
# Get specific account positions
stock_positions = sync.list_positions(account=api.stock_account)
futures_positions = sync.list_positions(account=api.futopt_account)
on_order_deal_event(state: OrderState, data: Dict)
Callback for order deal events. Automatically registered on init.
Handles:
OrderState.StockDeal: Stock deal eventsOrderState.FuturesDeal: Futures/options deal events
How It Works
-
Initialization:
- Calls
api.list_accounts()to get all accounts - Loads positions for each account via
api.list_positions(account) - Registers
on_order_deal_eventcallback
- Calls
-
Real-time Updates:
- When orders are filled, Shioaji triggers the callback
- Callback updates internal position dictionaries
- Buy deals increase quantity (or create new position)
- Sell deals decrease quantity
- Zero quantity positions are automatically removed
-
Position Storage:
- Stock positions:
{account_key: {(code, cond): StockPosition}} - Futures positions:
{account_key: {code: FuturesPosition}} - Account key =
broker_id + account_id
- Stock positions:
Development
Setup
git clone https://github.com/yvictor/sj_sync.git
cd sj_sync
uv sync
Run Tests
# All tests
uv run pytest tests/ -v
# With coverage
uv run pytest --cov=sj_sync --cov-report=html
Code Quality
# Linting
uv run ruff check src/ tests/
# Formatting
uv run ruff format src/ tests/
# Type checking
uv run zuban check src/
CI/CD
Every push and pull request triggers automated:
- ✅ Code quality checks (ruff, zuban)
- ✅ All 32 tests (unit + BDD)
- ✅ Coverage report to Codecov
- ✅ Build verification
See CI Setup Guide for details.
Testing
The project includes comprehensive pytest tests covering:
Unit Tests (18 tests):
- ✅ Position initialization from
list_positions() - ✅ Buy/sell deal events
- ✅ Day trading scenarios
- ✅ Margin trading and short selling
- ✅ Futures/options deals
- ✅ Multi-account support
- ✅ Edge cases and error handling
BDD Tests (14 scenarios in Chinese):
- ✅ 當沖交易 (Day trading offset rules)
- ✅ 融資融券 (Margin/short trading with yesterday's positions)
- ✅ 混合場景 (Complex mixed trading scenarios)
- ✅ Correct handling of
yd_quantityandyd_offset_quantity
Run tests with:
# All tests (32 total)
uv run pytest tests/ -v
# With coverage report
uv run pytest --cov=sj_sync --cov-report=html --cov-report=term-missing
View coverage report:
open htmlcov/index.html # macOS
xdg-open htmlcov/index.html # Linux
License
MIT License
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass (
pytest,zuban check,ruff check) - Submit a pull request
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 Distribution
Built Distribution
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 sj_sync-0.1.0.tar.gz.
File metadata
- Download URL: sj_sync-0.1.0.tar.gz
- Upload date:
- Size: 8.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d80e4e43f18fd4741e80c0155aade2847ede1cc70f71a4a01d5e6968f6ede5d8
|
|
| MD5 |
21b3f25f276f34e17b95226b300c6d7a
|
|
| BLAKE2b-256 |
3668484fea6ceddd25880f2b96f50b52d20889ac07da7b19f5fedeed365a4972
|
Provenance
The following attestation bundles were made for sj_sync-0.1.0.tar.gz:
Publisher:
publish.yml on Yvictor/sj_sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sj_sync-0.1.0.tar.gz -
Subject digest:
d80e4e43f18fd4741e80c0155aade2847ede1cc70f71a4a01d5e6968f6ede5d8 - Sigstore transparency entry: 700816711
- Sigstore integration time:
-
Permalink:
Yvictor/sj_sync@c60719214b09303265aa81b302ee38442a97e7ce -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Yvictor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c60719214b09303265aa81b302ee38442a97e7ce -
Trigger Event:
push
-
Statement type:
File details
Details for the file sj_sync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sj_sync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cc035c3fad98b3e431ba0fcdb2e2696df00e9f82df0f8947607e89cdb05e42b
|
|
| MD5 |
637427dc5801f4061d8ea160845b0ed5
|
|
| BLAKE2b-256 |
d1f06ba215015bed90c781561b4d6e0904ea3beb2c75bacea78c25d0a4c21263
|
Provenance
The following attestation bundles were made for sj_sync-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Yvictor/sj_sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sj_sync-0.1.0-py3-none-any.whl -
Subject digest:
5cc035c3fad98b3e431ba0fcdb2e2696df00e9f82df0f8947607e89cdb05e42b - Sigstore transparency entry: 700816743
- Sigstore integration time:
-
Permalink:
Yvictor/sj_sync@c60719214b09303265aa81b302ee38442a97e7ce -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Yvictor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c60719214b09303265aa81b302ee38442a97e7ce -
Trigger Event:
push
-
Statement type: