Skip to main content

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

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

ssi_sdk-3.0.2.tar.gz (42.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ssi_sdk-3.0.2-py3-none-any.whl (49.9 kB view details)

Uploaded Python 3

File details

Details for the file ssi_sdk-3.0.2.tar.gz.

File metadata

  • Download URL: ssi_sdk-3.0.2.tar.gz
  • Upload date:
  • Size: 42.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for ssi_sdk-3.0.2.tar.gz
Algorithm Hash digest
SHA256 025a35a1ecc52d5f9aaa37c1cbc730e3395e81806d84a28fd7b826375171ae5d
MD5 5ad72628b10223cf6e471407e3a4b79c
BLAKE2b-256 38b6494e91fe6c083405cff67d45aba7c4d72dc64bf3c25ace034b648e6371f1

See more details on using hashes here.

File details

Details for the file ssi_sdk-3.0.2-py3-none-any.whl.

File metadata

  • Download URL: ssi_sdk-3.0.2-py3-none-any.whl
  • Upload date:
  • Size: 49.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for ssi_sdk-3.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 da522b9b35c1e7b0b46315b2dd314760edaf7ea72eb7f9d5850d886cc1d4477e
MD5 45cbef79a7c7cfbdd1981a2b302be24c
BLAKE2b-256 adbc846b61a7f89044338d23300479db30e330f70afbce2bae405edf0f18e5ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page