🧪 Skills

tqsdk

TqSdk — open-source Python SDK for futures/options trading by Shinny Tech, providing real-time quotes, backtesting, and live trading.

v1.0.0
❤️ 0
⬇️ 21
👁 1
Share

Description


name: tqsdk description: TqSdk — open-source Python SDK for futures/options trading by Shinny Tech, providing real-time quotes, backtesting, and live trading. version: 1.0.0 homepage: https://github.com/shinnytech/tqsdk-python metadata: {"clawdbot":{"emoji":"📡","requires":{"bins":["python3"]}}}

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

# Live mode (free account with delayed quotes)
api = TqApi(auth=TqAuth("your_username", "your_password"))

# Get real-time quote
quote = api.get_quote("SHFE.cu2401")  # Shanghai copper futures
print(f"Last price: {quote.last_price}, Volume: {quote.volume}")

# Get K-line data
klines = api.get_kline_serial("SHFE.cu2401", duration_seconds=60)  # 1-min bars
print(klines.tail())

# Close API
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")
# Key fields:
# quote.last_price      — Last traded price
# quote.bid_price1      — Best bid price
# quote.ask_price1      — Best ask price
# quote.bid_volume1     — Best bid volume
# quote.ask_volume1     — Best ask volume
# quote.highest         — Day high
# quote.lowest          — Day low
# quote.open            — Open price
# quote.close           — Previous close
# quote.volume          — Total volume
# quote.amount          — Total turnover
# quote.open_interest   — Open interest
# quote.upper_limit     — Upper price limit
# quote.lower_limit     — Lower price limit
# quote.pre_settlement  — Previous settlement price
# quote.settlement      — Today's settlement price

# Wait for quote update
while True:
    api.wait_update()
    if api.is_changing(quote, "last_price"):
        print(f"Price update: {quote.last_price}")

K-line Data

# Get K-line series (returns pandas DataFrame)
klines = api.get_kline_serial(
    "SHFE.cu2401",
    duration_seconds=60,     # Bar duration: 60=1min, 300=5min, 3600=1hour, 86400=daily
    data_length=200          # Number of bars to fetch
)
# Columns: datetime, open, high, low, close, volume, open_oi, close_oi

# Multiple durations
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)
# Columns: datetime, last_price, highest, lowest, bid_price1, ask_price1,
#          bid_volume1, ask_volume1, volume, amount, open_interest

Trading

Place Orders

from tqsdk import TqApi, TqAuth

api = TqApi(auth=TqAuth("user", "pass"))

# Limit order — buy open 2 lots
order = api.insert_order(
    symbol="SHFE.cu2401",
    direction="BUY",           # "BUY" or "SELL"
    offset="OPEN",             # "OPEN", "CLOSE", "CLOSETODAY"
    volume=2,                  # Number of lots
    limit_price=68000.0        # Limit price (None for market order)
)

# Market order (FAK — Fill and Kill)
order = api.insert_order(
    symbol="SHFE.cu2401",
    direction="BUY",
    offset="OPEN",
    volume=2
)

# Cancel order
api.cancel_order(order)

# Check order status
while True:
    api.wait_update()
    if order.status == "FINISHED":
        print(f"Order finished: filled={order.volume_orign - order.volume_left}")
        break

Position & Account

# Get account info
account = api.get_account()
# account.balance        — Account balance
# account.available      — Available funds
# account.margin         — Used margin
# account.float_profit   — Floating PnL
# account.position_profit — Position PnL
# account.commission     — Today's commission

# Get position
position = api.get_position("SHFE.cu2401")
# position.pos_long      — Long position volume
# position.pos_short     — Short position volume
# position.pos_long_today — Today's long position
# position.float_profit_long  — Long floating PnL
# position.float_profit_short — Short floating PnL
# position.open_price_long    — Long average open price
# position.open_price_short   — Short average open price

Backtesting

from tqsdk import TqApi, TqAuth, TqBacktest, TqSim
from datetime import date

# Create backtest API
api = TqApi(
    backtest=TqBacktest(
        start_dt=date(2024, 1, 1),
        end_dt=date(2024, 6, 30)
    ),
    account=TqSim(init_balance=1000000),  # Simulated account with 1M initial
    auth=TqAuth("user", "pass")
)

# Strategy logic (same code works for live and backtest)
klines = api.get_kline_serial("CFFEX.IF2401", 60 * 60)  # 1-hour bars
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]["close"])

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")   # Near-month rebar
quote_far = api.get_quote("SHFE.rb2405")    # Far-month rebar
pos_near = api.get_position("SHFE.rb2401")
pos_far = api.get_position("SHFE.rb2405")

SPREAD_OPEN = 100    # Open spread threshold
SPREAD_CLOSE = 20    # Close spread threshold

while True:
    api.wait_update()
    spread = quote_near.last_price - quote_far.last_price

    if spread > SPREAD_OPEN and pos_near.pos_short == 0:
        # Spread too wide: sell near, buy far
        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:
        # Spread converged: close both legs
        api.insert_order("SHFE.rb2401", "BUY", "CLOSE", 1, quote_near.ask_price1)
        api.insert_order("SHFE.rb2405", "SELL", "CLOSE", 1, quote_far.bid_price1)
        print(f"Close spread trade: spread={spread:.0f}")

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)  # Daily bars
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

    # Calculate ATR
    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:
        # Entry: price above 20-day MA
        if current_price > ma20:
            api.insert_order(symbol, "BUY", "OPEN", 1, current_price)
            entry_price = current_price
            print(f"Entry: price={current_price:.2f}, ATR={atr:.2f}")
    else:
        # ATR trailing stop
        stop_price = entry_price - ATR_MULTIPLIER * atr
        if current_price < stop_price:
            api.insert_order(symbol, "SELL", "CLOSE", position.pos_long, current_price)
            print(f"Stop loss: price={current_price:.2f}, stop={stop_price:.2f}")

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 / 抖音

Reviews (0)

Sign in to write a review.

No reviews yet. Be the first to review!

Comments (0)

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts!

Compatible Platforms

Pricing

Free

Related Configs