| name | tqsdk |
| description | TqSdk — open-source Python SDK for futures/options trading by Shinny Tech, providing real-time quotes, backtesting, and live trading. |
| homepage | https://github.com/shinnytech/tqsdk-python |
TqSdk (Tianqin Quantitative SDK)
TqSdk is an open-source Python SDK by Shinny Tech for futures and options quantitative trading. It provides real-time market data, historical data, backtesting, and live trading through a unified async API.
Docs: https://doc.shinnytech.com/tqsdk/latest/
Free tier available (delayed quotes). Pro version for real-time data.
Installation
pip install tqsdk
Quick Start
from tqsdk import TqApi, TqAuth, TqBacktest
from datetime import date
api = TqApi(auth=TqAuth("your_username", "your_password"))
quote = api.get_quote("SHFE.cu2401")
print(f"Last price: {quote.last_price}, Volume: {quote.volume}")
klines = api.get_kline_serial("SHFE.cu2401", duration_seconds=60)
print(klines.tail())
api.close()
Symbol Format
EXCHANGE.CONTRACT
| Exchange | Code | Example |
|---|
| Shanghai Futures (SHFE) | SHFE | SHFE.cu2401 (Copper) |
| Dalian Commodity (DCE) | DCE | DCE.m2405 (Soybean meal) |
| Zhengzhou Commodity (CZCE) | CZCE | CZCE.CF405 (Cotton) |
| CFFEX (Financial) | CFFEX | CFFEX.IF2401 (CSI 300 futures) |
| Shanghai Energy (INE) | INE | INE.sc2407 (Crude oil) |
| Guangzhou Futures (GFEX) | GFEX | GFEX.si2407 (Industrial silicon) |
| SSE Options | SSE | SSE.10004816 (50ETF option) |
| SZSE Options | SZSE | SZSE.90000001 (300ETF option) |
Market Data
Real-time Quotes
from tqsdk import TqApi, TqAuth
api = TqApi(auth=TqAuth("user", "pass"))
quote = api.get_quote("CFFEX.IF2401")
while True:
api.wait_update()
if api.is_changing(quote, "last_price"):
print(f"Price update: {quote.last_price}")
K-line Data
klines = api.get_kline_serial(
"SHFE.cu2401",
duration_seconds=60,
data_length=200
)
klines_1m = api.get_kline_serial("SHFE.cu2401", 60)
klines_5m = api.get_kline_serial("SHFE.cu2401", 300)
klines_1d = api.get_kline_serial("SHFE.cu2401", 86400)
Tick Data
ticks = api.get_tick_serial("SHFE.cu2401", data_length=500)
Trading
Place Orders
from tqsdk import TqApi, TqAuth
api = TqApi(auth=TqAuth("user", "pass"))
order = api.insert_order(
symbol="SHFE.cu2401",
direction="BUY",
offset="OPEN",
volume=2,
limit_price=68000.0
)
order = api.insert_order(
symbol="SHFE.cu2401",
direction="BUY",
offset="OPEN",
volume=2
)
api.cancel_order(order)
while True:
api.wait_update()
if order.status == "FINISHED":
print(f"Order finished: filled={order.volume_orign - order.volume_left}")
break
Position & Account
account = api.get_account()
position = api.get_position("SHFE.cu2401")
Backtesting
from tqsdk import TqApi, TqAuth, TqBacktest, TqSim
from datetime import date
api = TqApi(
backtest=TqBacktest(
start_dt=date(2024, 1, 1),
end_dt=date(2024, 6, 30)
),
account=TqSim(init_balance=1000000),
auth=TqAuth("user", "pass")
)
klines = api.get_kline_serial("CFFEX.IF2401", 60 * 60)
position = api.get_position("CFFEX.IF2401")
while True:
api.wait_update()
if api.is_changing(klines.iloc[-1], "close"):
ma5 = klines["close"].iloc[-5:].mean()
ma20 = klines["close"].iloc[-20:].mean()
if ma5 > ma20 and position.pos_long == 0:
api.insert_order("CFFEX.IF2401", "BUY", "OPEN", 1, klines.iloc[-1]["close"])
elif ma5 < ma20 and position.pos_long > 0:
api.insert_order("CFFEX.IF2401", "SELL", "CLOSE", 1, klines.iloc[-1][])
api.close()
Advanced Examples
Dual-Contract Spread Trading
from tqsdk import TqApi, TqAuth
api = TqApi(auth=TqAuth("user", "pass"))
quote_near = api.get_quote("SHFE.rb2401")
quote_far = api.get_quote("SHFE.rb2405")
pos_near = api.get_position("SHFE.rb2401")
pos_far = api.get_position("SHFE.rb2405")
SPREAD_OPEN = 100
SPREAD_CLOSE = 20
while True:
api.wait_update()
spread = quote_near.last_price - quote_far.last_price
if spread > SPREAD_OPEN and pos_near.pos_short == 0:
api.insert_order("SHFE.rb2401", "SELL", "OPEN", 1, quote_near.bid_price1)
api.insert_order("SHFE.rb2405", "BUY", "OPEN", 1, quote_far.ask_price1)
print(f"Open spread trade: spread={spread:.0f}")
elif spread < SPREAD_CLOSE and pos_near.pos_short > 0:
api.insert_order("SHFE.rb2401", "BUY", "CLOSE", 1, quote_near.ask_price1)
api.insert_order("SHFE.rb2405", "SELL", "CLOSE", 1, quote_far.bid_price1)
()
ATR-Based Stop Loss Strategy
from tqsdk import TqApi, TqAuth
import numpy as np
api = TqApi(auth=TqAuth("user", "pass"))
symbol = "CFFEX.IF2401"
klines = api.get_kline_serial(symbol, 86400, data_length=50)
position = api.get_position(symbol)
ATR_PERIOD = 14
ATR_MULTIPLIER = 2.0
entry_price = 0.0
while True:
api.wait_update()
if not api.is_changing(klines.iloc[-1], "close"):
continue
highs = klines["high"].iloc[-ATR_PERIOD-1:]
lows = klines["low"].iloc[-ATR_PERIOD-1:]
closes = klines["close"].iloc[-ATR_PERIOD-1:]
tr = np.maximum(highs.values[1:] - lows.values[1:],
np.abs(highs.values[1:] - closes.values[:-1]),
np.abs(lows.values[1:] - closes.values[:-1]))
atr = np.mean(tr[-ATR_PERIOD:])
current_price = klines.iloc[-1]["close"]
ma20 = klines["close"].iloc[-20:].mean()
if position.pos_long == 0:
if current_price > ma20:
api.insert_order(symbol, "BUY", "OPEN", , current_price)
entry_price = current_price
()
:
stop_price = entry_price - ATR_MULTIPLIER * atr
current_price < stop_price:
api.insert_order(symbol, , , position.pos_long, current_price)
()
api.close()
Tips
- Free tier provides delayed quotes (15-min delay). Pro version needed for real-time data.
- Same code works for both backtesting and live trading — just change the API initialization.
api.wait_update() is the core event loop — all data updates are received through it.
- Use
api.is_changing() to check if specific data has been updated.
- Supports both futures and options across all major Chinese exchanges.
- Docs: https://doc.shinnytech.com/tqsdk/latest/
社区与支持
由 大佬量化 (Boss Quant) 维护 — 量化交易教学与策略研发团队。
微信客服: bossquant1 · Bilibili · 搜索 大佬量化 on 微信公众号 / Bilibili / 抖音