Python SDK for SSI trading platform
Project description
SSI Python SDK
Python SDK cho nền tảng giao dịch chứng khoán SSI. Hỗ trợ REST API và WebSocket streaming, cả đồng bộ (sync) và bất đồng bộ (async).
Yêu cầu: Python 3.10+
Mục lục
- Cài đặt
- Cấu hình
- Khởi tạo Client
- Xác thực
- Tài khoản
- Dữ liệu thị trường
- Danh mục đầu tư
- Giao dịch
- Streaming realtime
- Xử lý lỗi
- Cấu hình nâng cao
Cài đặt
pip install ssi-sdk
Cấu hình
Tạo đối tượng Config với thông tin xác thực:
from ssi_sdk import Config
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
private_key="YOUR_PRIVATE_KEY",
)
Tất cả tuỳ chọn cấu hình:
| Tham số | Kiểu | Mặc định | Mô tả |
|---|---|---|---|
client_id |
str |
(bắt buộc) | Client ID xác thực |
api_key |
str |
"" |
API key từ SSI |
api_secret |
str |
"" |
API secret từ SSI |
private_key |
str |
"" |
Private key cho ký lệnh giao dịch |
api_url |
str |
"https://api.ssi.com.vn" |
URL REST API |
streaming_url |
str |
"wss://api.ssi.com.vn/ws/v3" |
URL WebSocket streaming |
timeout |
int |
60 |
Timeout request (giây) |
max_retries |
int |
5 |
Số lần retry tối đa |
retry_delay |
float |
2.0 |
Delay cơ sở giữa các lần retry (exponential backoff, giây) |
rate_limit_per_second |
int |
10 |
Giới hạn request/giây (0 = không giới hạn) |
log_level |
str |
"INFO" |
Mức log: DEBUG, INFO, WARNING, ERROR, CRITICAL |
Khởi tạo Client
SDK cung cấp 2 client: SSIClient (đồng bộ) và AsyncSSIClient (bất đồng bộ). Cả hai có cùng API.
Async Client (khuyến nghị)
import asyncio
from ssi_sdk import AsyncSSIClient, Config
async def main():
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
private_key="YOUR_PRIVATE_KEY",
)
async with AsyncSSIClient(config) as client:
# Xác thực
await client.authenticate(otp="222222")
# Kết nối WebSocket (cần cho streaming)
await client.connect()
# Sử dụng các service...
accounts = await client.account.get_account_info()
print(accounts)
asyncio.run(main())
Sync Client
from ssi_sdk import SSIClient, Config
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
private_key="YOUR_PRIVATE_KEY",
)
with SSIClient(config) as client:
client.authenticate(otp="222222")
accounts = client.account.get_account_info()
print(accounts)
Chỉ dùng REST (không cần WebSocket)
Nếu không cần streaming, chỉ cần gọi authenticate() mà không cần connect():
client = SSIClient(config)
client.authenticate(otp="222222")
# Sử dụng market_data, account, portfolio, trading bình thường
client.disconnect()
Truyền config bằng keyword arguments
client = SSIClient(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
private_key="YOUR_PRIVATE_KEY",
timeout=60,
log_level="DEBUG",
)
1. Xác thực
Truy cập qua client.token_manager hoặc dùng client.authenticate().
1.1. Xác thực với OTP
# Cách nhanh: dùng client.authenticate()
client.authenticate(otp="222222")
# Hoặc dùng token_manager trực tiếp
token = client.token_manager.authenticate(otp="222222")
print(f"Access token: {token.access_token}")
print(f"Expires at: {token.expires_at}")
1.2. Yêu cầu gửi OTP
result = client.token_manager.request_otp()
print(result)
1.3. Làm mới token
token = client.token_manager.refresh()
1.4. Tự động đảm bảo xác thực
# Tự động refresh nếu token hết hạn, hoặc yêu cầu OTP nếu cần
access_token = client.token_manager.ensure_authenticated(otp="222222")
2. Tài khoản
Truy cập qua client.account.
2.1. Lấy danh sách tài khoản
accounts = client.account.get_account_info()
for acc in accounts:
print(f"{acc.account_no} - {acc.customer_name} ({acc.accounts})")
Trả về: list[Account]
3. Dữ liệu thị trường
Truy cập qua client.market_data.
3.1. Dữ liệu OHLC (nến)
SDK cung cấp các method OHLC theo từng timeframe:
Lấy dữ liệu trong ngày (không cần truyền ngày):
| Method | Timeframe |
|---|---|
get_ohlc_1minute(symbol) |
1 phút |
get_ohlc_3minute(symbol) |
3 phút |
get_ohlc_5minute(symbol) |
5 phút |
get_ohlc_15minute(symbol) |
15 phút |
get_ohlc_1hour(symbol) |
1 giờ |
# OHLC 1 phút trong ngày
ohlc = client.market_data.get_ohlc_1minute("SSI")
for candle in ohlc:
print(f"{candle.trading_date}: O={candle.open} H={candle.high} L={candle.low} C={candle.close} V={candle.volume}")
Lấy dữ liệu lịch sử (truyền khoảng ngày + phân trang):
| Method | Timeframe |
|---|---|
get_ohlc_1minute_historical(symbol, from_date, to_date, page, size) |
1 phút |
get_ohlc_3minute_historical(symbol, from_date, to_date, page, size) |
3 phút |
get_ohlc_5minute_historical(symbol, from_date, to_date, page, size) |
5 phút |
get_ohlc_15minute_historical(symbol, from_date, to_date, page, size) |
15 phút |
get_ohlc_1hour_historical(symbol, from_date, to_date, page, size) |
1 giờ |
get_ohlc_1day_historical(symbol, from_date, to_date, page, size) |
1 ngày |
get_ohlc_1week_historical(symbol, from_date, to_date, page, size) |
1 tuần |
get_ohlc_1month_historical(symbol, from_date, to_date, page, size) |
1 tháng |
# OHLC 1 ngày lịch sử
ohlc = client.market_data.get_ohlc_1day_historical(
symbol="SSI",
from_date="2026/03/27 00:00:00",
to_date="2026/03/27 00:00:00",
page=1,
size=100,
)
Tham số historical:
| Tham số | Kiểu | Mặc định | Mô tả |
|---|---|---|---|
symbol |
str |
(bắt buộc) | Mã chứng khoán |
from_date |
str |
(bắt buộc) | Ngày bắt đầu |
to_date |
str |
(bắt buộc) | Ngày kết thúc |
page |
int |
1 |
Trang |
size |
int |
1000 |
Số bản ghi/trang |
3.2. Danh sách chỉ số thị trường
# Lấy tất cả chỉ số
indices = client.market_data.get_indexes()
# Lấy theo sàn
from ssi_sdk.enums import Board
indices = client.market_data.get_indexes_by_board(Board.HOSE)
for idx in indices:
print(f"{idx.index_code} - {idx.index_name}")
3.3. Tổng hợp chỉ số (Index Summary)
# Summary hiện tại
summary = client.market_data.get_index_summary("VNINDEX")
print(f"{summary.index_value} ({summary.change:+.2f})")
# Summary lịch sử
summary = client.market_data.get_index_summary_historical("VNINDEX", "2025/01/15")
# Summary theo sàn
summary = client.market_data.get_board_summary(Board.HOSE)
# Summary sàn lịch sử
summary = client.market_data.get_board_summary_historical(Board.HOSE, "2025/01/15")
3.4. Thông tin chứng khoán
# Lấy thông tin 1 mã
info = client.market_data.get_securities_info("SSI")
print(f"{info.symbol} ({info.market}): Trần={info.ceiling} Sàn={info.floor} TC={info.ref_price}")
# Lấy theo chỉ số
securities = client.market_data.get_securities_info_by_index("VN30")
# Lấy theo sàn
securities = client.market_data.get_securities_info_by_board(Board.HOSE)
4. Danh mục đầu tư
Truy cập qua client.portfolio.
4.1. Số dư tài khoản
# Số dư tài khoản cơ sở
equity_balance = client.portfolio.get_equity_balance("1234561")
print(f"Cash: {equity_balance.cash}")
# Số dư tài khoản phái sinh
derivative_balance = client.portfolio.get_derivative_balance("1234568")
4.2. Vị thế (Positions)
# Vị thế cơ sở
positions = client.portfolio.get_equity_positions("1234561")
for pos in positions:
print(f"{pos.symbol}: {pos.total} cp | Giá TB: {pos.avg_price}")
# Vị thế phái sinh
derivative_positions = client.portfolio.get_derivative_positions("1234568")
# Chỉ vị thế mở phái sinh
open_pos = client.portfolio.get_open_derivative_positions("1234568")
# Chỉ vị thế đóng phái sinh
closed_pos = client.portfolio.get_closed_derivative_positions("1234568")
4.3. Sổ lệnh (Order Book)
# Lệnh trong ngày
today_orders = client.portfolio.get_today_orders("1234561")
for order in today_orders:
print(order)
# Lệnh lịch sử
historical_orders = client.portfolio.get_historical_orders(
"1234561",
from_date="2025/01/01",
to_date="2025/01/31",
)
4.4. PPMMR (Purchasing Power / Margin Maintenance Ratio)
# PPMMR cơ sở
equity_ppmmr = client.portfolio.get_equity_ppmmr("1234561")
# PPMMR phái sinh
derivative_ppmmr = client.portfolio.get_derivative_ppmmr("1234568")
5. Giao dịch
Truy cập qua client.trading.
5.1. Đặt lệnh
from ssi_sdk.enums import OrderSide, OrderType
# Lệnh giới hạn (LO)
result = client.trading.place_limit_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.BUY,
quantity=100,
price=66000,
)
print(f"Order: {result}")
# Lệnh thị trường (MTL)
result = client.trading.place_market_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.BUY,
quantity=100,
)
# Lệnh ATO (mở cửa)
result = client.trading.place_ato_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.BUY,
quantity=100,
)
# Lệnh ATC (đóng cửa)
result = client.trading.place_atc_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.SELL,
quantity=100,
)
# Lệnh tuỳ chỉnh (chọn order_type)
result = client.trading.place_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.BUY,
quantity=100,
price=66000,
order_type=OrderType.LO,
)
Loại lệnh (OrderType):
| Giá trị | Mô tả |
|---|---|
OrderType.LO |
Lệnh giới hạn (Limit Order) |
OrderType.MTL |
Lệnh thị trường (Market To Limit) |
OrderType.MP |
Lệnh thị trường (Market Price) |
OrderType.ATO |
Lệnh mở cửa (At The Open) |
OrderType.ATC |
Lệnh đóng cửa (At The Close) |
OrderType.MOK |
Match Or Kill |
OrderType.MAK |
Match And Kill |
OrderType.PLO |
Post Lunch Order |
5.2. Sửa lệnh
Chỉ có thể sửa giá hoặc số lượng (không đồng thời).
# Sửa giá theo client_request_id
result = client.trading.modify_order_price(
account_no="1234561",
client_request_id="REQ123",
price=68000,
)
# Sửa giá theo order_id
result = client.trading.modify_order_price_by_order_id(
account_no="1234561",
order_id="ORD123",
price=68000,
)
# Sửa số lượng theo client_request_id
result = client.trading.modify_order_quantity(
account_no="1234561",
client_request_id="REQ123",
quantity=200,
)
# Sửa số lượng theo order_id
result = client.trading.modify_order_quantity_by_order_id(
account_no="1234561",
order_id="ORD123",
quantity=200,
)
5.3. Huỷ lệnh
# Huỷ theo client_request_id
result = client.trading.cancel_order(
account_no="1234561",
client_request_id="REQ123",
)
# Huỷ theo order_id
result = client.trading.cancel_order_by_order_id(
account_no="1234561",
order_id="ORD123",
)
5.4. Sức mua/bán tối đa
# Với giá cụ thể
max_bs = client.trading.get_max_buy_sell(
account_no="1234561",
symbol="SSI",
price=66000,
)
print(f"Max buy: {max_bs.max_buy_quantity}")
print(f"Max sell: {max_bs.max_sell_quantity}")
# Với giá thị trường
max_bs = client.trading.get_max_buy_sell_at_market_price(
account_no="1234561",
symbol="SSI",
)
6. Streaming realtime
Truy cập qua client.streaming. Cần gọi client.connect() trước.
6.1. Thiết lập callback
# Callback nhận dữ liệu thị trường
def on_market_data(msg):
print(f"Market data: {msg}")
# Callback nhận dữ liệu giao dịch (order status, portfolio)
def on_trading_data(msg):
print(f"Trading: {msg}")
client.streaming.on_data = on_market_data
client.streaming.on_trading = on_trading_data
Các message type nhận được qua on_data:
| Topic | Message Type | Mô tả |
|---|---|---|
trade.* |
TradeMessage |
Dữ liệu khớp lệnh |
quote.* |
QuoteMessage |
Dữ liệu giá (bid/ask) |
room.* |
ForeignRoomMessage |
Room nước ngoài |
market.* |
MarketStatusMessage |
Trạng thái thị trường |
put.* |
PutMessage |
Thoả thuận |
oddlot.* |
OddLotMessage |
Lô lẻ |
Các message type nhận được qua on_trading:
| Topic | Message Type | Mô tả |
|---|---|---|
order.* |
OrderStatusMessage |
Trạng thái lệnh |
portfolio.* |
PortfolioMessage |
Thay đổi danh mục |
6.2. Subscribe dữ liệu thị trường
# Subscribe tất cả kênh (trade + quote + room) cho mã
client.streaming.subscribe_symbol(["SSI", "HPG", "VIC"])
# Subscribe từng kênh riêng
client.streaming.subscribe_symbol_trade(["SSI", "HPG"])
client.streaming.subscribe_symbol_quote(["SSI", "HPG"])
client.streaming.subscribe_symbol_room(["SSI", "HPG"])
client.streaming.subscribe_symbol_put_through(["SSI"])
client.streaming.subscribe_symbol_odd_lot(["SSI"])
# Subscribe theo sàn
from ssi_sdk.enums import Board
client.streaming.subscribe_board([Board.HOSE, Board.HNX])
# Subscribe theo chỉ số
client.streaming.subscribe_index(["VNINDEX", "VN30"])
6.3. Unsubscribe
client.streaming.unsubscribe_symbol(["SSI", "HPG"])
client.streaming.unsubscribe_symbol_trade(["SSI"])
client.streaming.unsubscribe_symbol_quote(["SSI"])
client.streaming.unsubscribe_symbol_room(["SSI"])
client.streaming.unsubscribe_symbol_put_through(["SSI"])
client.streaming.unsubscribe_symbol_odd_lot(["SSI"])
client.streaming.unsubscribe_board([Board.HOSE])
client.streaming.unsubscribe_index(["VNINDEX"])
6.4. Subscribe giao dịch (order status & portfolio)
# Subscribe trạng thái lệnh (tất cả tài khoản)
client.streaming.subscribe_order_status()
# Subscribe cho tài khoản cụ thể
client.streaming.subscribe_order_status(account_no="1234561")
# Subscribe portfolio
client.streaming.subscribe_portfolio()
client.streaming.subscribe_portfolio(account_no="1234561")
6.5. Heartbeat
client.streaming.ping()
6.6. Ví dụ streaming hoàn chỉnh (async)
import asyncio
from ssi_sdk import AsyncSSIClient, Config
from ssi_sdk.enums import Board
async def main():
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
private_key="YOUR_PRIVATE_KEY",
)
async with AsyncSSIClient(config) as client:
await client.authenticate(otp="222222")
await client.connect()
# Đăng ký callback
client.streaming.on_data = lambda msg: print(f"Data: {msg}")
client.streaming.on_trading = lambda msg: print(f"Trading: {msg}")
# Subscribe
await client.streaming.subscribe_symbol(["SSI", "HPG"])
await client.streaming.subscribe_order_status()
# Chờ nhận dữ liệu
await client.streaming.wait()
asyncio.run(main())
7. Xử lý lỗi
SDK sử dụng hệ thống exception phân cấp:
from ssi_sdk import SSIError
try:
client.authenticate(otp="wrong_otp")
except SSIError as e:
print(f"Lỗi: {e.message} (code: {e.code})")
Các exception:
| Exception | Mô tả |
|---|---|
SSIError |
Base exception cho tất cả lỗi SDK |
AuthenticationError |
Xác thực thất bại (sai credentials, token hết hạn) |
APIError |
API trả về lỗi — có thêm status_code, response_body |
WebSocketError |
Lỗi kết nối hoặc giao tiếp WebSocket |
ValidationError |
Lỗi validate input |
RateLimitError |
Vượt quá giới hạn request — có thêm retry_after |
from ssi_sdk.exceptions import APIError, AuthenticationError, RateLimitError
try:
result = client.trading.place_limit_order(
account_no="1234561",
symbol="SSI",
side=OrderSide.BUY,
quantity=100,
price=68000,
)
except AuthenticationError:
print("Cần xác thực lại")
except RateLimitError as e:
print(f"Rate limited, retry sau {e.retry_after}s")
except APIError as e:
print(f"API error {e.status_code}: {e.message}")
Debug logging
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
log_level="DEBUG",
)
Tuỳ chỉnh retry & rate limit
config = Config(
client_id="YOUR_CLIENT_ID",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
max_retries=3,
retry_delay=1.0,
rate_limit_per_second=5,
)
API Reference
Enums
from ssi_sdk.enums import (
OrderSide, # BUY, SELL
OrderType, # LO, MTL, MP, ATO, ATC, MOK, MAK, PLO
OrderStatus, # PENDING_APPROVAL, READY, SENT, QUEUED, FILLED, PARTIAL_FILLED,
# PARTIAL_CANCELLED, PENDING_MODIFY, PENDING_CANCEL,
# CANCELLED, REJECTED, EXPIRED, PRE_SESSION
Board, # HOSE, HNX, UPCOM
Timeframe, # MINUTE_1, MINUTE_3, MINUTE_5, MINUTE_15, HOUR_1,
# DAY_1, WEEK_1, MONTH_1
)
Services
| Service | Truy cập | Mô tả |
|---|---|---|
token_manager |
client.token_manager |
Xác thực, OTP, refresh token |
account |
client.account |
Thông tin tài khoản |
market_data |
client.market_data |
OHLC, chỉ số, chứng khoán |
portfolio |
client.portfolio |
Số dư, vị thế, sổ lệnh, PPMMR |
trading |
client.trading |
Đặt/sửa/huỷ lệnh, sức mua/bán |
streaming |
client.streaming |
Streaming realtime qua WebSocket |
Project details
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 ssi_sdk-3.0.1.tar.gz.
File metadata
- Download URL: ssi_sdk-3.0.1.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d877a244505ae31f4ae4bfca9ba35bf66c16718f5b566d7736afedca3a77bd89
|
|
| MD5 |
e51877324b6641c002973803d0c3de68
|
|
| BLAKE2b-256 |
f13caa7c162e1ede5c4c61dfc201f0618622810bc6f39fbf78489e0fce151242
|
File details
Details for the file ssi_sdk-3.0.1-py3-none-any.whl.
File metadata
- Download URL: ssi_sdk-3.0.1-py3-none-any.whl
- Upload date:
- Size: 48.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce66519401fa7a528c30760dbfba0d8616ca3c3c1851dc075722711dd754bc81
|
|
| MD5 |
54b9d7f1972789837545ff6a5fa33780
|
|
| BLAKE2b-256 |
b4b74283df13629ea342acbd13bf48f1a8c95046ad8e83d144e7a5e55d0f9db5
|