miniQMT (XunTou Minimalist Quantitative Terminal)
miniQMT is a lightweight quantitative trading terminal developed by XunTou Technology, designed specifically for external Python integration. It runs as a local Windows service and provides market data and trading capabilities through the XtQuant Python SDK (xtdata + xttrade).
⚠️ Requires miniQMT permission from your broker. Contact your securities firm to enable it. Multiple domestic brokers support it (Guojin, Huaxin, Zhongtai, East Money, Guosen, Founder, etc.).
miniQMT Overview
- Lightweight QMT client that runs as a background service on Windows
- Provides a market data server + trading server for external Python programs
- Python scripts connect via local TCP through the
xtquant SDK (xtdata for market data, xttrade for trade execution)
- Supports: A-shares, ETFs, convertible bonds, futures, options, margin trading
- Some brokers offer free Level 2 data with miniQMT
Architecture
Python script (any IDE: VS Code, PyCharm, Jupyter, etc.)
↓ xtquant SDK (pip install xtquant)
├── xtdata ──TCP──→ miniQMT (market data service)
└── xttrade ──TCP──→ miniQMT (trading service)
↓
Broker trading system
How to Get miniQMT
- Open a securities account with a broker that supports QMT
- Apply for miniQMT permission (some brokers require minimum assets, e.g., 50k–100k CNY)
- Download and install the QMT client from your broker
- Launch in miniQMT mode (minimalist mode) and log in
Usage Workflow
1. Start miniQMT
Launch the QMT client in minimalist mode and log in. The miniQMT interface is very simple — just a login window.
2. Install xtquant
pip install xtquant
3. Connect to Market Data with Python
from xtquant import xtdata
# Connect to the local miniQMT market data service
xtdata.connect()
# Download historical data (must download before first access)
xtdata.download_history_data('000001.SZ', '1d', start_time='20240101', end_time='20240630')
# Get K-line data (returns a dict of DataFrames keyed by stock code)
data = xtdata.get_market_data_ex(
[], ['000001.SZ'], period='1d',
start_time='20240101', end_time='20240630',
dividend_type='front' # Forward-adjusted
)
print(data['000001.SZ'].tail())
4. Connect to Trading Service with Python
from xtquant import xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
# path must point to the userdata_mini folder under the QMT installation directory
path = r'D:\券商QMT\userdata_mini'
# session_id must be unique for each strategy/script
session_id = 123456
xt_trader = XtQuantTrader(path, session_id)
# Register callback to receive real-time push notifications
class MyCallback(XtQuantTraderCallback):
def on_disconnected(self):
print('Disconnected — reconnection required')
def on_stock_order(self, order):
print(f'Order update: {order.stock_code} status={order.order_status} msg={order.status_msg}')
def on_stock_trade(self, trade):
print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')
def on_order_error(self, order_error):
print(f'Order error: {order_error.error_msg}')
xt_trader.register_callback(MyCallback())
xt_trader.start()
connect_result = xt_trader.connect() # Returns 0 on success, non-zero on failure
account = StockAccount('your_account')
xt_trader.subscribe(account) # Subscribe to account for push notifications
# Place a buy order
order_id = xt_trader.order_stock(
account, '000001.SZ', xtconstant.STOCK_BUY, 100,
xtconstant.FIX_PRICE, 11.50, 'my_strategy', 'test_order'
)
# order_id > 0 means success, -1 means failure
miniQMT vs Full QMT Comparison
| Feature |
miniQMT |
QMT (Full Version) |
| Python |
External Python (any version) |
Built-in Python (version restricted) |
| IDE |
Any (VS Code, PyCharm, Jupyter, etc.) |
Built-in editor only |
| Third-party libraries |
All pip packages (pandas, numpy, etc.) |
Built-in libraries only |
| Interface |
Minimalist (login window only) |
Full trading UI + charts |
| Market data |
Via xtdata API |
Built-in + xtdata API |
| Trading |
Via xttrade API |
Built-in + xttrade API |
| Resource usage |
Lightweight (~50 MB RAM) |
Heavy (full GUI, ~500 MB+) |
| Debugging |
Full IDE debugging support |
Limited |
| Use case |
Automated strategies, external integration |
Visual analysis + manual trading |
| Connection |
One-time connection, no auto-reconnect |
Persistent connection |
Data Capabilities (via xtdata)
| Category |
Details |
| K-line |
tick, 1m, 5m, 15m, 30m, 1h, 1d, 1w, 1mon — supports adjustment (forward / backward / proportional) |
| Tick |
Real-time tick data with 5-level bid/ask, volume, turnover, trade count |
| Level 2 |
l2quote (real-time snapshot), l2order (order-by-order), l2transaction (trade-by-trade), l2quoteaux (aggregate buy/sell), l2orderqueue (order queue), l2thousand (1000-level order book), fullspeedorderbook (full-speed 20-level) |
| Financials |
Balance sheet, income statement, cash flow statement, per-share metrics, share structure, top 10 shareholders / free-float holders, shareholder count |
| Reference |
Trading calendar, holidays, sector lists, index constituents & weights, ex-dividend data, contract info |
| Real-time |
Single-stock subscription (subscribe_quote), market-wide push (subscribe_whole_quote) |
| Special |
Convertible bond info, IPO subscription data, ETF creation/redemption lists, announcements & news, consecutive limit-up tracking, snapshot indicators (volume ratio / price velocity), high-frequency IOPV |
Data Access Patterns
download_history_data() → get_market_data_ex() # Historical data: download to local cache first, then read from cache
subscribe_quote() → callback # Real-time data: subscribe and receive via callback
get_full_tick() # Snapshot data: get latest tick for the entire market
Trading Capabilities (via xttrade)
| Category |
Operations |
| Stocks |
Buy/sell (sync and async), limit/market/best price orders |
| ETF |
Buy/sell, creation/redemption |
| Convertible bonds |
Buy/sell |
| Futures |
Open long/close long/open short/close short |
| Options |
Buy/sell open/close, covered open/close, exercise, lock/unlock |
| Margin trading |
Margin buy, short sell, buy to cover, direct return, sell to repay, direct repayment, special margin/short |
| IPO |
New share/bond subscription, query subscription quota |
| Cancel |
Cancel by order_id or broker contract number (sync and async) |
| Query |
Assets, orders, trades, positions, futures position summary |
| Credit query |
Credit assets, liability contracts, margin-eligible securities, available-to-short data, collateral |
| Bank-broker transfer |
Bank to securities, securities to bank (sync and async) |
| Smart algorithms |
VWAP and other algorithmic execution |
| Securities lending |
Query available securities, apply for lending, manage contracts |
Account Types
StockAccount('id') # Regular stock account
StockAccount('id', 'CREDIT') # Credit account (margin trading)
StockAccount('id', 'FUTURE') # Futures account
Key Trading Callbacks
| Callback |
Triggered When |
on_stock_order(order) |
Order status change (submitted, partially filled, fully filled, cancelled, rejected) |
on_stock_trade(trade) |
Trade execution report |
on_stock_position(position) |
Position change |
on_stock_asset(asset) |
Asset/fund change |
on_order_error(error) |
Order placement failure |
on_cancel_error(error) |
Order cancellation failure |
on_disconnected() |
Disconnected from miniQMT |
Order Status Codes
| Value |
Status |
| 48 |
Not submitted |
| 50 |
Submitted |
| 54 |
Cancelled |
| 55 |
Partially filled |
| 56 |
Fully filled |
| 57 |
Rejected |
Common Broker Paths
# Guojin Securities
path = r'D:\国金证券QMT交易端\userdata_mini'
# Huaxin Securities
path = r'D:\华鑫证券\userdata_mini'
# Zhongtai Securities
path = r'D:\中泰证券\userdata_mini'
# East Money
path = r'D:\东方财富证券QMT交易端\userdata_mini'
Stock Code Format
| Market |
Example |
| Shanghai A-shares |
600000.SH |
| Shenzhen A-shares |
000001.SZ |
| Beijing Stock Exchange |
430047.BJ |
| Indices |
000001.SH (SSE Composite), 399001.SZ (SZSE Component) |
| CFFEX Futures |
IF2401.IF |
| SHFE Futures |
ag2407.SF |
| Options |
10004358.SHO |
| ETF |
510300.SH |
| Convertible bonds |
113050.SH |
Full Example: Market Data + Trading Strategy
from xtquant import xtdata, xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
# === Callback class definition ===
class MyCallback(XtQuantTraderCallback):
def on_disconnected(self):
print('Disconnected')
def on_stock_trade(self, trade):
print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')
def on_order_error(self, order_error):
print(f'Error: {order_error.error_msg}')
# === 1. Connect to market data service ===
xtdata.connect()
# === 2. Download and retrieve historical data ===
stock = '000001.SZ'
xtdata.download_history_data(stock, '1d', start_time='20240101', end_time='20240630')
data = xtdata.get_market_data_ex(
[], [stock], period='1d',
start_time='20240101', end_time='20240630',
dividend_type='front' # Forward-adjusted
)
df = data[stock]
# === 3. Calculate simple moving average crossover signal ===
df['ma5'] = df['close'].rolling(5).mean() # 5-day MA
df['ma20'] = df['close'].rolling(20).mean() # 20-day MA
latest = df.iloc[-1] # Latest bar
prev = df.iloc[-2] # Previous bar
# === 4. Connect to trading service ===
path = r'D:\券商QMT\userdata_mini'
xt_trader = XtQuantTrader(path, 123456)
xt_trader.register_callback(MyCallback())
xt_trader.start()
if xt_trader.connect() != 0:
print('Connection failed!')
exit()
account = StockAccount('your_account')
xt_trader.subscribe(account) # Subscribe to account push notifications
# === 5. Execute trading signal ===
if prev['ma5'] <= prev['ma20'] and latest['ma5'] > latest['ma20']:
# Golden cross signal: 5-day MA crosses above 20-day MA, buy
order_id = xt_trader.order_stock(
account, stock, xtconstant.STOCK_BUY, 100,
xtconstant.LATEST_PRICE, 0, 'ma_cross', 'golden_cross'
)
print(f'Golden cross buy — {stock}, order_id={order_id}')
elif prev['ma5'] >= prev['ma20'] and latest['ma5'] < latest['ma20']:
# Death cross signal: 5-day MA crosses below 20-day MA, sell
order_id = xt_trader.order_stock(
account, stock, xtconstant.STOCK_SELL, 100,
xtconstant.LATEST_PRICE, 0, 'ma_cross', 'death_cross'
)
print(f'Death cross sell — {stock}, order_id={order_id}')
# === 6. Query results ===
asset = xt_trader.query_stock_asset(account)
print(f'Available cash: {asset.cash}, Total assets: {asset.total_asset}')
positions = xt_trader.query_stock_positions(account)
for pos in positions:
print(f'{pos.stock_code}: {pos.volume} shares, available={pos.can_use_volume}, cost={pos.open_price}')
Full Example: Real-Time Market Monitoring
from xtquant import xtdata
import threading
def on_tick(datas):
"""Tick data callback function"""
for code, tick in datas.items():
print(f'{code}: latest={tick["lastPrice"]}, volume={tick["volume"]}')
# Connect to market data service
xtdata.connect()
# Run subscription in a separate thread (xtdata.run() blocks the current thread)
def run_data():
xtdata.subscribe_quote('000001.SZ', period='tick', callback=on_tick)
xtdata.subscribe_quote('600000.SH', period='tick', callback=on_tick)
xtdata.run() # Blocks the thread, continuously receiving data
t = threading.Thread(target=run_data, daemon=True)
t.start()
# Main thread can perform trading or other operations
# ...
Usage Tips
- miniQMT runs on Windows only — Python scripts can run on the same or a different machine if TCP is reachable.
- miniQMT must remain logged in while your Python script is running.
connect() is a one-time connection — it does not auto-reconnect after disconnection; you need to implement reconnection logic yourself.
session_id must be unique per strategy — different Python scripts must use different session_ids.
- For real-time subscriptions,
xtdata.run() blocks the thread — run it in a separate thread and use the main thread for trading.
- Downloaded data is cached locally — subsequent reads are extremely fast.
- In push callbacks (
on_stock_order, etc.), use async query methods (e.g., query_stock_orders_async) to avoid deadlocks. Or enable set_relaxed_response_order_enabled(True).
- Some brokers offer free Level 2 data with miniQMT — check with your broker.
- Documentation: http://dict.thinktrader.net/nativeApi/start_now.html
Advanced Examples
Grid Trading Strategy
from xtquant import xtdata, xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
import threading
class GridCallback(XtQuantTraderCallback):
def on_stock_trade(self, trade):
print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')
def on_order_error(self, error):
print(f'Error: {error.error_msg}')
# Initialize trading
path = r'D:\券商QMT\userdata_mini'
xt_trader = XtQuantTrader(path, 100001)
xt_trader.register_callback(GridCallback())
xt_trader.start()
xt_trader.connect()
account = StockAccount('your_account')
xt_trader.subscribe(account)
# Grid parameters
stock = '000001.SZ'
grid_base = 11.0 # Base price
grid_step = 0.2 # Grid spacing
grid_shares = 100 # Shares per grid level
grid_levels = 5 # 5 levels above and below
last_grid = 0 # Current grid level
xtdata.connect()
def on_tick(datas):
global last_grid
for code, tick in datas.items():
price = tick['lastPrice']
# Calculate the current grid level for the price
current_grid = int((price - grid_base) / grid_step)
if current_grid < last_grid:
# Price dropped through grid line, buy
for _ in range(last_grid - current_grid):
xt_trader.order_stock(
account, code, xtconstant.STOCK_BUY, grid_shares,
xtconstant.LATEST_PRICE, 0, 'grid', f'网格买入_level{current_grid}'
)
last_grid = current_grid
elif current_grid > last_grid:
# Price rose through grid line, sell
for _ in range(current_grid - last_grid):
xt_trader.order_stock(
account, code, xtconstant.STOCK_SELL, grid_shares,
xtconstant.LATEST_PRICE, 0, 'grid', f'网格卖出_level{current_grid}'
)
last_grid = current_grid
# Start market data subscription
def run_data():
xtdata.subscribe_quote(stock, period='tick', callback=on_tick)
xtdata.run()
t = threading.Thread(target=run_data, daemon=True)
t.start()
xt_trader.run_forever()
Convertible Bond T+0 Intraday Trading
from xtquant import xtdata, xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
import threading
class CBCallback(XtQuantTraderCallback):
def on_stock_trade(self, trade):
print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')
path = r'D:\券商QMT\userdata_mini'
xt_trader = XtQuantTrader(path, 100002)
xt_trader.register_callback(CBCallback())
xt_trader.start()
xt_trader.connect()
account = StockAccount('your_account')
xt_trader.subscribe(account)
# Convertible bond code (convertible bonds support T+0 trading)
cb_code = '113050.SH'
buy_threshold = -0.5 # Buy when drop exceeds 0.5%
sell_threshold = 0.5 # Sell when gain exceeds 0.5%
position = 0
xtdata.connect()
def on_tick(datas):
global position
for code, tick in datas.items():
price = tick['lastPrice']
pre_close = tick['lastClose']
if pre_close == 0:
continue
pct_change = (price - pre_close) / pre_close * 100
# Drop reaches threshold, buy 10 lots
if pct_change <= buy_threshold and position == 0:
xt_trader.order_stock(
account, code, xtconstant.STOCK_BUY, 10,
xtconstant.LATEST_PRICE, 0, 'cb_t0', '可转债T0买入'
)
position = 10
# Gain reaches threshold, sell
elif pct_change >= sell_threshold and position > 0:
xt_trader.order_stock(
account, code, xtconstant.STOCK_SELL, position,
xtconstant.LATEST_PRICE, 0, 'cb_t0', '可转债T0卖出'
)
position = 0
def run_data():
xtdata.subscribe_quote(cb_code, period='tick', callback=on_tick)
xtdata.run()
t = threading.Thread(target=run_data, daemon=True)
t.start()
xt_trader.run_forever()
Scheduled IPO Subscription
from xtquant import xtdata, xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
import datetime
import time
class IPOCallback(XtQuantTraderCallback):
def on_stock_order(self, order):
print(f'IPO subscription: {order.stock_code} status={order.order_status} {order.status_msg}')
path = r'D:\券商QMT\userdata_mini'
xt_trader = XtQuantTrader(path, 100003)
xt_trader.register_callback(IPOCallback())
xt_trader.start()
xt_trader.connect()
account = StockAccount('your_account')
xt_trader.subscribe(account)
# Query IPO subscription quota
limits = xt_trader.query_new_purchase_limit(account)
print(f"Subscription quota: {limits}")
# Query today's IPO data
ipo_data = xt_trader.query_ipo_data()
if ipo_data:
for code, info in ipo_data.items():
print(f"New stock: {code} {info['name']} issue price={info['issuePrice']} max subscription={info['maxPurchaseNum']}")
# Subscribe at maximum allowed volume
max_vol = info['maxPurchaseNum']
if max_vol > 0:
order_id = xt_trader.order_stock(
account, code, xtconstant.STOCK_BUY, max_vol,
xtconstant.FIX_PRICE, info['issuePrice'], 'ipo', '新股申购'
)
print(f" Subscription submitted: order_id={order_id}")
else:
print("No IPOs available today")
社区与支持
由 大佬量化 (Boss Quant) 维护 — 量化交易教学与策略研发团队。
微信客服: bossquant1 · Bilibili · 搜索 大佬量化 on 微信公众号 / Bilibili / 抖音
1---2name: miniqmt3description: miniQMT Minimalist Quantitative Trading Terminal — Supports external Python for market data retrieval and programmatic trading via the xtquant SDK.4---56# miniQMT (XunTou Minimalist Quantitative Terminal)78miniQMT is a lightweight quantitative trading terminal developed by XunTou Technology, designed specifically for external Python integration. It runs as a local Windows service and provides market data and trading capabilities through the [XtQuant](http://dict.thinktrader.net/nativeApi/start_now.html) Python SDK (`xtdata` + `xttrade`).910> ⚠️ **Requires miniQMT permission from your broker**. Contact your securities firm to enable it. Multiple domestic brokers support it (Guojin, Huaxin, Zhongtai, East Money, Guosen, Founder, etc.).1112## miniQMT Overview1314- **Lightweight QMT client** that runs as a background service on Windows15- Provides a **market data server** + **trading server** for external Python programs16- Python scripts connect via local TCP through the `xtquant` SDK (xtdata for market data, xttrade for trade execution)17- Supports: A-shares, ETFs, convertible bonds, futures, options, margin trading18- Some brokers offer free **Level 2 data** with miniQMT1920## Architecture2122```23Python script (any IDE: VS Code, PyCharm, Jupyter, etc.)24 ↓ xtquant SDK (pip install xtquant)25 ├── xtdata ──TCP──→ miniQMT (market data service)26 └── xttrade ──TCP──→ miniQMT (trading service)27 ↓28 Broker trading system29```3031## How to Get miniQMT32331. Open a securities account with a broker that supports QMT342. Apply for miniQMT permission (some brokers require minimum assets, e.g., 50k–100k CNY)353. Download and install the QMT client from your broker364. Launch in miniQMT mode (minimalist mode) and log in3738## Usage Workflow3940### 1. Start miniQMT4142Launch the QMT client in minimalist mode and log in. The miniQMT interface is very simple — just a login window.4344### 2. Install xtquant4546```bash47pip install xtquant48```4950### 3. Connect to Market Data with Python5152```python53from xtquant import xtdata5455# Connect to the local miniQMT market data service56xtdata.connect()5758# Download historical data (must download before first access)59xtdata.download_history_data('000001.SZ', '1d', start_time='20240101', end_time='20240630')6061# Get K-line data (returns a dict of DataFrames keyed by stock code)62data = xtdata.get_market_data_ex(63 [], ['000001.SZ'], period='1d',64 start_time='20240101', end_time='20240630',65 dividend_type='front' # Forward-adjusted66)67print(data['000001.SZ'].tail())68```6970### 4. Connect to Trading Service with Python7172```python73from xtquant import xtconstant74from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback75from xtquant.xttype import StockAccount7677# path must point to the userdata_mini folder under the QMT installation directory78path = r'D:\券商QMT\userdata_mini'79# session_id must be unique for each strategy/script80session_id = 12345681xt_trader = XtQuantTrader(path, session_id)8283# Register callback to receive real-time push notifications84class MyCallback(XtQuantTraderCallback):85 def on_disconnected(self):86 print('Disconnected — reconnection required')87 def on_stock_order(self, order):88 print(f'Order update: {order.stock_code} status={order.order_status} msg={order.status_msg}')89 def on_stock_trade(self, trade):90 print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')91 def on_order_error(self, order_error):92 print(f'Order error: {order_error.error_msg}')9394xt_trader.register_callback(MyCallback())95xt_trader.start()96connect_result = xt_trader.connect() # Returns 0 on success, non-zero on failure9798account = StockAccount('your_account')99xt_trader.subscribe(account) # Subscribe to account for push notifications100101# Place a buy order102order_id = xt_trader.order_stock(103 account, '000001.SZ', xtconstant.STOCK_BUY, 100,104 xtconstant.FIX_PRICE, 11.50, 'my_strategy', 'test_order'105)106# order_id > 0 means success, -1 means failure107```108109---110111## miniQMT vs Full QMT Comparison112113| Feature | miniQMT | QMT (Full Version) |114|---|---|---|115| **Python** | External Python (any version) | Built-in Python (version restricted) |116| **IDE** | Any (VS Code, PyCharm, Jupyter, etc.) | Built-in editor only |117| **Third-party libraries** | All pip packages (pandas, numpy, etc.) | Built-in libraries only |118| **Interface** | Minimalist (login window only) | Full trading UI + charts |119| **Market data** | Via xtdata API | Built-in + xtdata API |120| **Trading** | Via xttrade API | Built-in + xttrade API |121| **Resource usage** | Lightweight (~50 MB RAM) | Heavy (full GUI, ~500 MB+) |122| **Debugging** | Full IDE debugging support | Limited |123| **Use case** | Automated strategies, external integration | Visual analysis + manual trading |124| **Connection** | One-time connection, no auto-reconnect | Persistent connection |125126---127128## Data Capabilities (via xtdata)129130| Category | Details |131|---|---|132| **K-line** | tick, 1m, 5m, 15m, 30m, 1h, 1d, 1w, 1mon — supports adjustment (forward / backward / proportional) |133| **Tick** | Real-time tick data with 5-level bid/ask, volume, turnover, trade count |134| **Level 2** | l2quote (real-time snapshot), l2order (order-by-order), l2transaction (trade-by-trade), l2quoteaux (aggregate buy/sell), l2orderqueue (order queue), l2thousand (1000-level order book), fullspeedorderbook (full-speed 20-level) |135| **Financials** | Balance sheet, income statement, cash flow statement, per-share metrics, share structure, top 10 shareholders / free-float holders, shareholder count |136| **Reference** | Trading calendar, holidays, sector lists, index constituents & weights, ex-dividend data, contract info |137| **Real-time** | Single-stock subscription (`subscribe_quote`), market-wide push (`subscribe_whole_quote`) |138| **Special** | Convertible bond info, IPO subscription data, ETF creation/redemption lists, announcements & news, consecutive limit-up tracking, snapshot indicators (volume ratio / price velocity), high-frequency IOPV |139140### Data Access Patterns141142```143download_history_data() → get_market_data_ex() # Historical data: download to local cache first, then read from cache144subscribe_quote() → callback # Real-time data: subscribe and receive via callback145get_full_tick() # Snapshot data: get latest tick for the entire market146```147148## Trading Capabilities (via xttrade)149150| Category | Operations |151|---|---|152| **Stocks** | Buy/sell (sync and async), limit/market/best price orders |153| **ETF** | Buy/sell, creation/redemption |154| **Convertible bonds** | Buy/sell |155| **Futures** | Open long/close long/open short/close short |156| **Options** | Buy/sell open/close, covered open/close, exercise, lock/unlock |157| **Margin trading** | Margin buy, short sell, buy to cover, direct return, sell to repay, direct repayment, special margin/short |158| **IPO** | New share/bond subscription, query subscription quota |159| **Cancel** | Cancel by order_id or broker contract number (sync and async) |160| **Query** | Assets, orders, trades, positions, futures position summary |161| **Credit query** | Credit assets, liability contracts, margin-eligible securities, available-to-short data, collateral |162| **Bank-broker transfer** | Bank to securities, securities to bank (sync and async) |163| **Smart algorithms** | VWAP and other algorithmic execution |164| **Securities lending** | Query available securities, apply for lending, manage contracts |165166### Account Types167168```python169StockAccount('id') # Regular stock account170StockAccount('id', 'CREDIT') # Credit account (margin trading)171StockAccount('id', 'FUTURE') # Futures account172```173174### Key Trading Callbacks175176| Callback | Triggered When |177|---|---|178| `on_stock_order(order)` | Order status change (submitted, partially filled, fully filled, cancelled, rejected) |179| `on_stock_trade(trade)` | Trade execution report |180| `on_stock_position(position)` | Position change |181| `on_stock_asset(asset)` | Asset/fund change |182| `on_order_error(error)` | Order placement failure |183| `on_cancel_error(error)` | Order cancellation failure |184| `on_disconnected()` | Disconnected from miniQMT |185186### Order Status Codes187188| Value | Status |189|---|---|190| 48 | Not submitted |191| 50 | Submitted |192| 54 | Cancelled |193| 55 | Partially filled |194| 56 | Fully filled |195| 57 | Rejected |196197---198199## Common Broker Paths200201```python202# Guojin Securities203path = r'D:\国金证券QMT交易端\userdata_mini'204# Huaxin Securities205path = r'D:\华鑫证券\userdata_mini'206# Zhongtai Securities207path = r'D:\中泰证券\userdata_mini'208# East Money209path = r'D:\东方财富证券QMT交易端\userdata_mini'210```211212## Stock Code Format213214| Market | Example |215|---|---|216| Shanghai A-shares | `600000.SH` |217| Shenzhen A-shares | `000001.SZ` |218| Beijing Stock Exchange | `430047.BJ` |219| Indices | `000001.SH` (SSE Composite), `399001.SZ` (SZSE Component) |220| CFFEX Futures | `IF2401.IF` |221| SHFE Futures | `ag2407.SF` |222| Options | `10004358.SHO` |223| ETF | `510300.SH` |224| Convertible bonds | `113050.SH` |225226---227228## Full Example: Market Data + Trading Strategy229230```python231from xtquant import xtdata, xtconstant232from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback233from xtquant.xttype import StockAccount234235# === Callback class definition ===236class MyCallback(XtQuantTraderCallback):237 def on_disconnected(self):238 print('Disconnected')239 def on_stock_trade(self, trade):240 print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')241 def on_order_error(self, order_error):242 print(f'Error: {order_error.error_msg}')243244# === 1. Connect to market data service ===245xtdata.connect()246247# === 2. Download and retrieve historical data ===248stock = '000001.SZ'249xtdata.download_history_data(stock, '1d', start_time='20240101', end_time='20240630')250data = xtdata.get_market_data_ex(251 [], [stock], period='1d',252 start_time='20240101', end_time='20240630',253 dividend_type='front' # Forward-adjusted254)255df = data[stock]256257# === 3. Calculate simple moving average crossover signal ===258df['ma5'] = df['close'].rolling(5).mean() # 5-day MA259df['ma20'] = df['close'].rolling(20).mean() # 20-day MA260latest = df.iloc[-1] # Latest bar261prev = df.iloc[-2] # Previous bar262263# === 4. Connect to trading service ===264path = r'D:\券商QMT\userdata_mini'265xt_trader = XtQuantTrader(path, 123456)266xt_trader.register_callback(MyCallback())267xt_trader.start()268if xt_trader.connect() != 0:269 print('Connection failed!')270 exit()271272account = StockAccount('your_account')273xt_trader.subscribe(account) # Subscribe to account push notifications274275# === 5. Execute trading signal ===276if prev['ma5'] <= prev['ma20'] and latest['ma5'] > latest['ma20']:277 # Golden cross signal: 5-day MA crosses above 20-day MA, buy278 order_id = xt_trader.order_stock(279 account, stock, xtconstant.STOCK_BUY, 100,280 xtconstant.LATEST_PRICE, 0, 'ma_cross', 'golden_cross'281 )282 print(f'Golden cross buy — {stock}, order_id={order_id}')283elif prev['ma5'] >= prev['ma20'] and latest['ma5'] < latest['ma20']:284 # Death cross signal: 5-day MA crosses below 20-day MA, sell285 order_id = xt_trader.order_stock(286 account, stock, xtconstant.STOCK_SELL, 100,287 xtconstant.LATEST_PRICE, 0, 'ma_cross', 'death_cross'288 )289 print(f'Death cross sell — {stock}, order_id={order_id}')290291# === 6. Query results ===292asset = xt_trader.query_stock_asset(account)293print(f'Available cash: {asset.cash}, Total assets: {asset.total_asset}')294295positions = xt_trader.query_stock_positions(account)296for pos in positions:297 print(f'{pos.stock_code}: {pos.volume} shares, available={pos.can_use_volume}, cost={pos.open_price}')298```299300## Full Example: Real-Time Market Monitoring301302```python303from xtquant import xtdata304import threading305306def on_tick(datas):307 """Tick data callback function"""308 for code, tick in datas.items():309 print(f'{code}: latest={tick["lastPrice"]}, volume={tick["volume"]}')310311# Connect to market data service312xtdata.connect()313314# Run subscription in a separate thread (xtdata.run() blocks the current thread)315def run_data():316 xtdata.subscribe_quote('000001.SZ', period='tick', callback=on_tick)317 xtdata.subscribe_quote('600000.SH', period='tick', callback=on_tick)318 xtdata.run() # Blocks the thread, continuously receiving data319320t = threading.Thread(target=run_data, daemon=True)321t.start()322323# Main thread can perform trading or other operations324# ...325```326327## Usage Tips328329- miniQMT runs on **Windows only** — Python scripts can run on the same or a different machine if TCP is reachable.330- miniQMT must remain **logged in** while your Python script is running.331- `connect()` is a **one-time connection** — it does not auto-reconnect after disconnection; you need to implement reconnection logic yourself.332- `session_id` must be **unique per strategy** — different Python scripts must use different session_ids.333- For real-time subscriptions, `xtdata.run()` blocks the thread — run it in a **separate thread** and use the main thread for trading.334- Downloaded data is **cached locally** — subsequent reads are extremely fast.335- In push callbacks (`on_stock_order`, etc.), use **async query methods** (e.g., `query_stock_orders_async`) to avoid deadlocks. Or enable `set_relaxed_response_order_enabled(True)`.336- Some brokers offer **free Level 2 data** with miniQMT — check with your broker.337- Documentation: http://dict.thinktrader.net/nativeApi/start_now.html338339---340341## Advanced Examples342343### Grid Trading Strategy344345```python346from xtquant import xtdata, xtconstant347from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback348from xtquant.xttype import StockAccount349import threading350351class GridCallback(XtQuantTraderCallback):352 def on_stock_trade(self, trade):353 print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')354 def on_order_error(self, error):355 print(f'Error: {error.error_msg}')356357# Initialize trading358path = r'D:\券商QMT\userdata_mini'359xt_trader = XtQuantTrader(path, 100001)360xt_trader.register_callback(GridCallback())361xt_trader.start()362xt_trader.connect()363account = StockAccount('your_account')364xt_trader.subscribe(account)365366# Grid parameters367stock = '000001.SZ'368grid_base = 11.0 # Base price369grid_step = 0.2 # Grid spacing370grid_shares = 100 # Shares per grid level371grid_levels = 5 # 5 levels above and below372last_grid = 0 # Current grid level373374xtdata.connect()375376def on_tick(datas):377 global last_grid378 for code, tick in datas.items():379 price = tick['lastPrice']380 # Calculate the current grid level for the price381 current_grid = int((price - grid_base) / grid_step)382383 if current_grid < last_grid:384 # Price dropped through grid line, buy385 for _ in range(last_grid - current_grid):386 xt_trader.order_stock(387 account, code, xtconstant.STOCK_BUY, grid_shares,388 xtconstant.LATEST_PRICE, 0, 'grid', f'网格买入_level{current_grid}'389 )390 last_grid = current_grid391392 elif current_grid > last_grid:393 # Price rose through grid line, sell394 for _ in range(current_grid - last_grid):395 xt_trader.order_stock(396 account, code, xtconstant.STOCK_SELL, grid_shares,397 xtconstant.LATEST_PRICE, 0, 'grid', f'网格卖出_level{current_grid}'398 )399 last_grid = current_grid400401# Start market data subscription402def run_data():403 xtdata.subscribe_quote(stock, period='tick', callback=on_tick)404 xtdata.run()405406t = threading.Thread(target=run_data, daemon=True)407t.start()408xt_trader.run_forever()409```410411### Convertible Bond T+0 Intraday Trading412413```python414from xtquant import xtdata, xtconstant415from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback416from xtquant.xttype import StockAccount417import threading418419class CBCallback(XtQuantTraderCallback):420 def on_stock_trade(self, trade):421 print(f'Trade filled: {trade.stock_code} {trade.traded_volume}@{trade.traded_price}')422423path = r'D:\券商QMT\userdata_mini'424xt_trader = XtQuantTrader(path, 100002)425xt_trader.register_callback(CBCallback())426xt_trader.start()427xt_trader.connect()428account = StockAccount('your_account')429xt_trader.subscribe(account)430431# Convertible bond code (convertible bonds support T+0 trading)432cb_code = '113050.SH'433buy_threshold = -0.5 # Buy when drop exceeds 0.5%434sell_threshold = 0.5 # Sell when gain exceeds 0.5%435position = 0436437xtdata.connect()438439def on_tick(datas):440 global position441 for code, tick in datas.items():442 price = tick['lastPrice']443 pre_close = tick['lastClose']444 if pre_close == 0:445 continue446 pct_change = (price - pre_close) / pre_close * 100447448 # Drop reaches threshold, buy 10 lots449 if pct_change <= buy_threshold and position == 0:450 xt_trader.order_stock(451 account, code, xtconstant.STOCK_BUY, 10,452 xtconstant.LATEST_PRICE, 0, 'cb_t0', '可转债T0买入'453 )454 position = 10455456 # Gain reaches threshold, sell457 elif pct_change >= sell_threshold and position > 0:458 xt_trader.order_stock(459 account, code, xtconstant.STOCK_SELL, position,460 xtconstant.LATEST_PRICE, 0, 'cb_t0', '可转债T0卖出'461 )462 position = 0463464def run_data():465 xtdata.subscribe_quote(cb_code, period='tick', callback=on_tick)466 xtdata.run()467468t = threading.Thread(target=run_data, daemon=True)469t.start()470xt_trader.run_forever()471```472473### Scheduled IPO Subscription474475```python476from xtquant import xtdata, xtconstant477from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback478from xtquant.xttype import StockAccount479import datetime480import time481482class IPOCallback(XtQuantTraderCallback):483 def on_stock_order(self, order):484 print(f'IPO subscription: {order.stock_code} status={order.order_status} {order.status_msg}')485486path = r'D:\券商QMT\userdata_mini'487xt_trader = XtQuantTrader(path, 100003)488xt_trader.register_callback(IPOCallback())489xt_trader.start()490xt_trader.connect()491account = StockAccount('your_account')492xt_trader.subscribe(account)493494# Query IPO subscription quota495limits = xt_trader.query_new_purchase_limit(account)496print(f"Subscription quota: {limits}")497498# Query today's IPO data499ipo_data = xt_trader.query_ipo_data()500if ipo_data:501 for code, info in ipo_data.items():502 print(f"New stock: {code} {info['name']} issue price={info['issuePrice']} max subscription={info['maxPurchaseNum']}")503 # Subscribe at maximum allowed volume504 max_vol = info['maxPurchaseNum']505 if max_vol > 0:506 order_id = xt_trader.order_stock(507 account, code, xtconstant.STOCK_BUY, max_vol,508 xtconstant.FIX_PRICE, info['issuePrice'], 'ipo', '新股申购'509 )510 print(f" Subscription submitted: order_id={order_id}")511else:512 print("No IPOs available today")513```514515---516517## 社区与支持518519由 **大佬量化 (Boss Quant)** 维护 — 量化交易教学与策略研发团队。520521微信客服: **bossquant1** · [Bilibili](https://space.bilibili.com/48693330) · 搜索 **大佬量化** on 微信公众号 / Bilibili / 抖音