| Bot Trading Python Kết Nối SSI/DNSE: Đặt Lệnh Tự Động Chứng Khoán Việt Nam

Tự động hóa giao dịch chứng khoán Việt Nam đã trở thành hiện thực với các API từ SSI và DNSE. Bài viết này hướng dẫn bạn xây dựng bot trading Python kết nối sàn Việt Nam — từ đăng nhập đến đặt lệnh tự động.

Tại Sao Cần Bot Trading?

  • Không bỏ lỡ tín hiệu: Bot chạy 9:00–14:45, không cần ngồi theo dõi
  • Loại bỏ cảm xúc: Mua/bán theo quy tắc định sẵn, không FOMO hay panic sell
  • Tốc độ: Đặt lệnh trong milliseconds khi có tín hiệu
  • Backtested: Chiến lược đã được kiểm tra trước khi chạy thật

Lựa Chọn Broker: SSI vs DNSE

SSI FastConnect DNSE iBoard API
API chính thức ✅ Có ✅ Có
Phí API Miễn phí Miễn phí
Python SDK ✅ Có Cần tự viết wrapper
Dữ liệu realtime ✅ Websocket ✅ REST API
Phí giao dịch ~0.15% ~0.15–0.2%

Cài Đặt SSI FastConnect SDK

pip install ssi-fc-data

Kết Nối SSI và Lấy Dữ Liệu Realtime

from ssi_fc_data import fc_md_client, model

# Thông tin đăng nhập SSI (lấy tại SSI iBoard → Cài đặt → API)
config = model.Config(
    Url="https://fc-data.ssi.com.vn/",
    ConsumerID="your_consumer_id",
    ConsumerSecret="your_consumer_secret"
)

client = fc_md_client.MarketDataClient(config)

# Lấy dữ liệu intraday OHLCV
def get_intraday(symbol, resolution="1"):
    data = client.iboard(
        symbol=symbol,
        look_back=100,
        resolution=resolution
    )
    return data

df = get_intraday("VNM")
print(df.tail(5))

Đặt Lệnh Qua SSI Trading API

import requests
import json

SSI_TRADE_URL = "https://trade.ssi.com.vn/rest/v2"

class SSITrader:
    def __init__(self, access_token, account_no):
        self.token      = access_token
        self.account_no = account_no
        self.headers    = {
            "Authorization": f"Bearer {self.token}",
            "Content-Type":  "application/json"
        }

    def get_balance(self):
        r = requests.get(
            f"{SSI_TRADE_URL}/Account/Balance",
            headers=self.headers,
            params={"account": self.account_no}
        )
        return r.json()

    def get_positions(self):
        r = requests.get(
            f"{SSI_TRADE_URL}/Position",
            headers=self.headers,
            params={"account": self.account_no}
        )
        return r.json()

    def place_order(self, symbol, side, quantity, price, order_type="LO"):
        """
        side: "B" (Buy) hoặc "S" (Sell)
        order_type: "LO" (Limit), "MP" (Market Price)
        """
        payload = {
            "account":     self.account_no,
            "instrumentID": symbol,
            "market":      "VN",
            "buySell":     side,
            "orderType":   order_type,
            "price":       price,
            "quantity":    quantity
        }
        r = requests.post(
            f"{SSI_TRADE_URL}/Order/NewOrder",
            headers=self.headers,
            json=payload
        )
        return r.json()

    def cancel_order(self, order_id):
        payload = {
            "account":  self.account_no,
            "orderID":  order_id
        }
        r = requests.post(
            f"{SSI_TRADE_URL}/Order/CancelOrder",
            headers=self.headers,
            json=payload
        )
        return r.json()

# Sử dụng
trader = SSITrader(access_token="...", account_no="...")

Bot Hoàn Chỉnh: Chiến Lược RSI Tự Động

import time
import pandas as pd
from datetime import datetime

class RSIBot:
    def __init__(self, trader, symbol, capital_per_trade=10_000_000):
        self.trader   = trader
        self.symbol   = symbol
        self.capital  = capital_per_trade
        self.position = 0  # số lượng cổ phiếu đang nắm
        self.log      = []

    def calc_rsi(self, prices, period=14):
        s = pd.Series(prices)
        delta = s.diff()
        gain  = delta.clip(lower=0).rolling(period).mean()
        loss  = (-delta.clip(upper=0)).rolling(period).mean()
        return (100 - (100 / (1 + gain/loss))).iloc[-1]

    def run(self):
        print(f"[{datetime.now()}] Bot khởi động: {self.symbol}")

        while True:
            now = datetime.now()

            # Chỉ chạy trong giờ giao dịch
            if not (9 <= now.hour < 14 or (now.hour == 14 and now.minute <= 45)):
                time.sleep(60)
                continue

            try:
                # Lấy dữ liệu giá gần nhất
                df = get_intraday(self.symbol, resolution="5")  # nến 5 phút
                prices = df['close'].tolist()

                if len(prices) < 20:
                    time.sleep(30)
                    continue

                current_price = prices[-1]
                rsi           = self.calc_rsi(prices)

                print(f"[{now.strftime('%H:%M')}] {self.symbol}: {current_price:,.0f} | RSI: {rsi:.1f}")

                # Logic giao dịch
                if rsi  0:
                        result = self.trader.place_order(self.symbol, "B", quantity, current_price)
                        if result.get('status') == 'success':
                            self.position = quantity
                            print(f"  ✅ MUA {quantity} {self.symbol} @ {current_price:,.0f}")

                elif rsi > 70 and self.position > 0:
                    # Tín hiệu BÁN
                    result = self.trader.place_order(self.symbol, "S", self.position, current_price)
                    if result.get('status') == 'success':
                        print(f"  ✅ BÁN {self.position} {self.symbol} @ {current_price:,.0f}")
                        self.position = 0

                # Stop loss 5%
                elif self.position > 0:
                    entry = self.capital / self.position
                    if current_price < entry * 0.95:
                        self.trader.place_order(self.symbol, "S", self.position, current_price)
                        print(f"  🛑 STOP LOSS @ {current_price:,.0f}")
                        self.position = 0

                time.sleep(60)  # kiểm tra mỗi 1 phút

            except Exception as e:
                print(f"  ⚠️ Lỗi: {e}")
                time.sleep(30)

# Khởi chạy bot
bot = RSIBot(trader, symbol="VNM", capital_per_trade=20_000_000)
bot.run()

Lưu Ý Quan Trọng

  • Test kỹ trước: Chạy paper trading (giả lập) ít nhất 2–4 tuần
  • Giới hạn vốn: Bot lỗi có thể đặt lệnh sai — đặt giới hạn tối đa/ngày
  • Logging: Ghi log tất cả lệnh để kiểm tra sau
  • Monitoring: Kết hợp Telegram bot để nhận thông báo ngay khi có lệnh

Kết Luận

Bot trading Python kết nối SSI/DNSE là hoàn toàn khả thi với trader Việt Nam. Bắt đầu đơn giản với 1 cổ phiếu, 1 chiến lược, vốn nhỏ — sau khi ổn định mới scale up.


📌 Muốn ứng dụng Python vào phân tích và giao dịch tài chính thực chiến?
Khóa Python Fintech — Phân Tích Dữ Liệu Lớn & Tự Động Hóa Giao Dịch tại Hướng Nghiệp Dữ Liệu giúp bạn thực hành với dữ liệu VnIndex, Binance API thật — không dạy lý thuyết hàn lâm.
📞 Hotline/Zalo: 0927 909 257

admin

admin

Biên tập viên, Hướng Nghiệp Dữ Liệu
738 Bài viết
15.4k Người theo dõi
120k+ Lượt đọc

Biên tập viên nội dung tại Hướng Nghiệp Dữ Liệu, phụ trách tổng hợp và biên soạn các bài viết về lập trình Python, dữ liệu và công nghệ.