使用手册
功能在哪 · 是什么 · 怎么调出来一、TqSdk 是什么
TqSdk 是信易科技开源的国内期货 Python SDK,特点:
- 纯 Python,pip 安装
- 行情和交易统一接口
- 内置回测引擎,回测/实盘同一套代码
- 免费版提供全部国内期货、商品/金融期权及主要股指的实时行情
白话注解:TqSdk 就像一个"翻译官"——你用 Python 写"买开一手螺纹钢",它翻译成期货交易所能懂的语言发出去。你不用管底层 CTP 协议有多复杂。
A 股股票实时/历史行情属于专业版功能;期货与期权行情免费版即可用。写策略前先确认你需要的行情在不在免费额度内。
二、安装与环境
pip install tqsdk --upgrade
- Python 3.7+(推荐 3.8~3.11,太新的 Python 版本个别依赖可能滞后)
- 安装慢可换国内源:
pip install tqsdk -i https://pypi.tuna.tsinghua.edu.cn/simple - 验证安装:
python -c "import tqsdk; print(tqsdk.__version__)"
白话注解:TqSdk 连接的是信易科技的服务器再转到交易所,所以你本机不需要装 CTP 动态库——这也是它比 vn.py 对新手友好的最大原因。
三、连接:三种账户 TqSim / TqKq / TqAccount
from tqsdk import TqApi, TqAuth, TqSim, TqKq, TqAccount
# 1) 本地模拟(默认):虚拟资金在本地撮合,记录不同步到任何客户端
api = TqApi(auth=TqAuth('快期账号', '密码'))
# 2) 快期模拟:账户保存在云端,可在快期APP/专业版里看到持仓和成交
api = TqApi(TqKq(), auth=TqAuth('快期账号', '密码'))
# 3) 实盘:连接期货公司 CTP(期货公司名首字母大写)
api = TqApi(TqAccount("H宏源期货", "320102", "123456"), auth=TqAuth('快期账号', '密码'))
三种账户对比:
| 账户 | 资金 | 记录在哪 | 用途 |
|---|---|---|---|
TqSim() | 默认 1000 万虚拟 | 仅本地程序内 | 回测、快速验证 |
TqKq() | 快期云端虚拟 | 快期 APP / 专业版可查 | 模拟盘长期验证 |
TqAccount(公司, 账号, 密码) | 真实资金 | 期货公司 | 实盘 |
# 登录失败处理:TqApi 创建 60 秒内登录不成功会抛异常
try:
api = TqApi(TqAccount("H宏源期货", "320102", "123456"), auth=TqAuth('快期账号', '密码'))
except Exception as e:
print("连接失败:行情服务器不通 / 期货公司服务器关了 / 账号密码错")
实盘常见报错:CTP:不合法登录=账号密码或席位错;CTP:客户端认证失败=需联系期货公司把账户与天勤 APPID 绑定。每个快期账户默认最多绑 3 个实盘账户。
操作教程
一步一步 · 跟着做完一件事四、合约代码规则(含主连/指数/组合)
TqSdk 合约代码统一为 交易所代码.品种代码 格式,大小写敏感:
| 交易所 | 代码 | 示例 |
|---|---|---|
| 上海期货交易所 | SHFE | SHFE.cu2607 |
| 大连商品交易所 | DCE | DCE.m2609 |
| 郑州商品交易所 | CZCE | CZCE.SR609 |
| 中国金融交易所 | CFFEX | CFFEX.IF2606 |
| 上海能源中心 | INE | INE.sc2607 |
| 广州期货交易所 | GFEX | GFEX.si2607 |
特殊合约:
| 类型 | 格式 | 示例 |
|---|---|---|
| 主连合约 | KQ.m@交易所.品种 | KQ.m@SHFE.rb |
| 品种指数 | KQ.i@交易所.品种 | KQ.i@SHFE.bu |
| 跨期组合 | SPD 合约A&合约B | SHFE.SPD au2610&au2704 |
| 期权 | 各交易所格式不同 | DCE.m2609-C-2700、CZCE.CF609C13400 |
| 股票 | SSE.代码 / SZSE.代码 | SSE.600000 |
两个高频坑:①郑商所合约是三位数字且字母大写(CZCE.SR609,不是 SR2609);②主连合约不能直接交易——要用 quote.underlying_symbol 拿到当前主力合约代码再下单(见第十三章)。
五、实时行情 get_quote(全字段表)
get_quote() 一次拿到实时行情 + 合约信息,返回对象在 wait_update() 时自动刷新:
q = api.get_quote("SHFE.cu2607")
api.wait_update() # 首次 wait_update 后字段才有值
print(q.last_price, q.upper_limit)
常用字段(完整字段见官方 objs 文档):
| 字段 | 含义 | 策略里干嘛用 |
|---|---|---|
last_price | 最新价 | 信号计算 |
ask_price1 / bid_price1 | 卖一 / 买一 | 对价下单(主动买用卖一,主动卖用买一) |
upper_limit / lower_limit | 涨停 / 跌停价 | 风控:涨跌停不追单 |
pre_settlement | 昨结算价 | 算当日盈亏基准 |
price_tick | 最小变动价位 | 限价单价格必须是 price_tick 的整数倍 |
volume_multiple | 合约乘数 | 算保证金与止损金额 |
margin / commission | 每手保证金 / 手续费 | 仓位计算 |
trading_time | 交易时段 | 判断夜盘是否存在 |
underlying_symbol | 主连对应的实际主力合约 | 交易主连必用 |
expire_rest_days | 距到期天数 | 移仓提醒、规避交割月 |
ins_class | 合约类型 FUTURE / OPTION 等 | 多品种策略里区分品种 |
白话注解:每个合约的 quote 只需 get 一次,之后它就像一个"活的窗口"——每次 wait_update() 后再看,里面永远是最新值。
六、K线与 Tick:get_kline_serial / get_tick_serial
# 60 秒 K 线(1分钟)
klines = api.get_kline_serial("SHFE.rb2405", 60)
# 日线:86400 秒
daily = api.get_kline_serial("SHFE.rb2405", 86400, data_length=200)
# Tick 序列
ticks = api.get_tick_serial("SHFE.rb2405")
关键规则:
- 周期以秒数表示,支持不超过 1 日的任意周期(
70秒线也行;超过 86400 无效) - 每条序列最多返回最近 8000 根,无论什么周期
- 返回值就是
pandas.DataFrame,直接用 pandas 的一切操作
K线 DataFrame 列:
| 列 | 含义 |
|---|---|
datetime | K线起点时间(纳秒时间戳,转换见第十一章 tafunc) |
open / high / low / close | 开高低收 |
volume | 该根成交量 |
open_oi / close_oi | K线起止时刻的持仓量 |
id | 序列号 |
白话注解:多合约还能"时间对齐"——api.get_kline_serial(["SHFE.au2608", "SHFE.au2610"], 5) 返回以后一个合约向前一个对齐的 K 线,做价差策略直接用。
七、事件驱动模型:wait_update / is_changing
TqSdk 程序的主循环骨架永远是这个:
while True:
api.wait_update() # 阻塞:等到任何订阅的数据有更新才往下走
if api.is_changing(klines.iloc[-1], "datetime"):
# 只有"新K线生成"才进这里,避免一根K线内重复触发
do_something()
| 函数 | 作用 | 要点 |
|---|---|---|
api.wait_update() | 等下一个数据更新事件 | 同时负责把下单/撤单请求真正发出去、驱动后台任务(如 TargetPosTask) |
api.is_changing(对象, "字段") | 判断这次更新是不是该对象该字段 | 不给字段名 = 对象任意字段变了都返回 True |
api.wait_update(deadline=...) | 限时等待 | 超时也返回,适合"长时间没行情也要干活"的场景 |
白话注解:为什么判断信号常用iloc[-2]?因为最新那根 K 线(iloc[-1])还在走、收盘价没定型,用它算指标每 tick 都会变;iloc[-2]是刚走完的、定型的 K 线,信号才可靠。这是新手最容易踩的"未来函数"。
八、下单 insert_order(全参数)
order = api.insert_order(
symbol="SHFE.rb2610",
direction="BUY", # BUY=买, SELL=卖
offset="OPEN", # OPEN=开仓, CLOSE=平仓, CLOSETODAY=平今
volume=2, # 手数
limit_price=4310 # 限价;None=市价
)
参数全解:
| 参数 | 可选值 | 说明 |
|---|---|---|
direction | "BUY" / "SELL" | 买 / 卖 |
offset | "OPEN" / "CLOSE" / "CLOSETODAY" | 上期所和上期能源必须区分平今平昨(见第九章) |
limit_price | 数字 / None / "BEST" / "FIVELEVEL" | 数字=限价单;None=市价单(郑商所不支持市价);BEST/FIVELEVEL 仅中金所 |
advanced | "FAK" / "FOK" | 剩余即撤 / 全成或全撤(郑商所不支持 FOK) |
order_id | 字符串 | 自定义单号,默认自动生成 |
account | 账户实例 | 多账户模式下必须指定 |
Order 对象关键字段(在 wait_update() 时自动更新):
| 字段 | 含义 |
|---|---|
order_id / exchange_order_id | 柜台单号 / 交易所单号 |
volume_orign / volume_left | 总报单手数 / 未成交手数 |
price_type | ANY=市价,LIMIT=限价 |
status | ALIVE=有效,FINISHED=已完(终态) |
last_msg | 委托状态描述,如"报单成功" |
insert_date_time | 下单时间(纳秒时间戳) |
insert_order() 调用后立即返回引用,但报单真正发出是在下一次 wait_update()。下单后没有自动追单——价格不动你的单就挂着,需要自己实现"撤单重下"或直接用 TargetPosTask(第十五章)。
九、平仓与平今平昨(上期所必读)
国内交易所平仓规则不同,这是实盘绕不过去的坑:
| 交易所 | 平昨仓 | 平今仓 |
|---|---|---|
| 上期所 SHFE / 上期能源 INE | offset="CLOSE" | offset="CLOSETODAY" |
| 大商所 DCE / 郑商所 CZCE / 中金所 CFFEX / 广期所 GFEX | 统一 offset="CLOSE",交易所自动先平今 |
# 平今仓(仅上期所/上期能源需要)
api.insert_order(symbol, direction="SELL", offset="CLOSETODAY", volume=1, limit_price=quote.bid_price1)
# 平昨仓
api.insert_order(symbol, direction="SELL", offset="CLOSE", volume=1, limit_price=quote.bid_price1)
白话注解:上期所把"今天开的仓"和"昨天以前开的仓"当成两种东西管理,平仓时必须说清平的是哪种,手续费还可能不一样(平今更贵)。你昨天的多单今天用CLOSETODAY去平,会被拒单。记不住规则就别手动拼 offset——用 TargetPosTask,它按offset_priority自动处理。
十、查持仓和资金:Position / Account 字段
account = api.get_account() # 账户资金(自动刷新)
pos = api.get_position("SHFE.rb2610") # 该合约持仓
| Account 字段 | 含义 |
|---|---|
balance | 动态权益(含浮动盈亏) |
available | 可用资金 |
margin | 占用保证金 |
position_profit / float_profit | 持仓盈亏(含昨仓)/ 浮动盈亏(按市价) |
risk_ratio | 风险度 = 保证金 / 权益,风控核心指标 |
commission | 今日手续费 |
| Position 字段 | 含义 |
|---|---|
pos_long / pos_short | 多单 / 空单总手数 |
pos_long_his / pos_long_today | 多单昨仓 / 多单今仓(平仓前先看清) |
pos_short_his / pos_short_today | 空单昨仓 / 空单今仓 |
position_profit | 持仓盈亏 |
open_price_long / open_price_short | 开仓均价 |
白话注解:风控就盯 risk_ratio——超过 50% 就该减仓,接近 100% 随时可能被强平。千万别满仓梭哈一个合约,一个反向跳空就爆仓。
十一、TargetPosTask 目标持仓(框架自动开平仓)
TqSdk 的杀手锏:你不写"怎么开平",只声明"我要几手净持仓",框架自动算差额、自动处理平今平昨顺序、自动追单:
from tqsdk import TqApi, TqAuth, TqSim, TargetPosTask
api = TqApi(TqSim(), auth=TqAuth("账号", "密码"))
klines = api.get_kline_serial("SHFE.rb2610", 3600)
# 每个合约只能创建一个 TargetPosTask 实例
# 注意:3.10.2 实测构造参数没有 direction——任务方向由 set_target_volume 的正负决定
target_pos = TargetPosTask(api, "SHFE.rb2610",
offset_priority="今昨,开",
price="ACTIVE")
while True:
api.wait_update()
# ...信号计算...
if 想持多:
target_pos.set_target_volume(5) # 净多头5手
elif 想持空:
target_pos.set_target_volume(-5) # 净空头5手
else:
target_pos.set_target_volume(0) # 清仓
关键参数:
| 参数 | 默认 | 可选值与说明 |
|---|---|---|
| (无 direction 参数) | — | 任务方向由 set_target_volume 的正负决定:正数=持多,负数=持空(旧文档的 direction= 写法在 3.10.x 会直接报 TypeError) |
offset_priority | "今昨,开" | 开平顺序:"今昨,开"先平今再平昨再开仓;"昨今,开";"今,开";"昨,开";"今昨"/"昨今"只平不开 |
price | "ACTIVE" | "ACTIVE"对价(买以卖一、卖以买一);"PASSIVE"排队价;"MARKET"市价;也可给具体价格 |
min_volume / max_volume | None | 最小/每笔最大调仓手数(大仓位拆单) |
trade_chan | None | 异步接收成交回报的 channel |
与手动 insert_order 对比:
| 维度 | insert_order | TargetPosTask |
|---|---|---|
| 抽象层级 | 一笔委托单 | 目标净持仓 |
| 平今平昨 | 自己判断交易所规则 | 按 offset_priority 自动处理 |
| 未成交追单 | 自己写撤单重下 | 内置自动追单 |
| 使用约束 | 随意 | 每合约一个实例,不要与手动下单混用 |
| 适合 | 抢单、精细限价控制 | 信号驱动的趋势/调仓策略 |
白话注解:set_target_volume里正数=净多头手数、负数=净空头手数、0=清仓。它只是"声明意图",实际调仓在下一次wait_update()后由后台任务执行。做趋势策略,90% 的情况用它比手动下单省心得多。
注意:TqApi 不传账户时默认用 TqSim;TargetPosTask 暂不支持股票(股票 T+1 规则,见第十九章)。同一合约同时用 insert_order 和 TargetPosTask 会互相干扰。
十二、委托管理进阶:状态轮询 / 撤单 / 成交回报
# 委托状态轮询:直到终态
order = api.insert_order(symbol, direction="BUY", offset="OPEN", volume=2, limit_price=4300)
while order.status != "FINISHED":
api.wait_update()
print(order.status, "未成交", order.volume_left, "手 |", order.last_msg)
# 撤单
api.cancel_order(order)
# 全部委托 / 成交记录
orders = api.get_order() # 所有委托(dict,key=order_id)
trades = api.get_trade() # 所有成交记录
典型"未成交自动撤单重下"逻辑(手动追单的最小骨架):
import time
order = api.insert_order(symbol, "BUY", "OPEN", volume=2, limit_price=4300)
t0 = time.time()
while order.status != "FINISHED":
api.wait_update(deadline=time.time() + 5)
if order.status == "ALIVE" and time.time() - t0 > 10: # 挂单超10秒
api.cancel_order(order) # 撤旧单
order = api.insert_order(symbol, "BUY", "OPEN", volume=order.volume_left,
limit_price=新价格) # 只追未成交部分
t0 = time.time()
白话注解:追单只追volume_left(未成交部分),别把已成交的再下一遍——否则仓位翻倍。get_order()不带参数返回全部委托字典,程序重启后想恢复现场就靠它。
十三、多合约行情与套利
# 一个 wait_update 监控多个合约
q1 = api.get_quote("SHFE.cu2607")
q2 = api.get_quote("SHFE.cu2608")
k1 = api.get_kline_serial("SHFE.cu2607", 60)
k2 = api.get_kline_serial("SHFE.cu2608", 60)
while api.wait_update():
if api.is_changing(q1): print("cu2607:", q1.last_price)
if api.is_changing(q2): print("cu2608:", q2.last_price)
if api.is_changing(k1.iloc[-1], "datetime"): pass # 新K线
- 跨期价差可以直接算:
spread = q1.last_price - q2.last_price - 交易所组合合约(如
SHFE.SPD au2610&au2704)一腿下单自动成交两条腿,但回测只能用 tick 数据(组合合约无K线) - 时间对齐 K 线:
api.get_kline_serial(["合约A", "合约B"], 5)(见第六章)
白话注解:套利策略的核心是把两腿当成一个"价差合约"来算信号。组合合约下单交易所保证两腿同成同败,规避单腿风险——但流动性往往差,下单前看盘口。
十四、web_gui 可视化
TqSdk 内置网页图形界面,一行参数开启:
api = TqApi(TqSim(), web_gui=True, auth=TqAuth("账号", "密码"))
- 启动后自动打开浏览器,K 线主图与账户权益曲线自动实时绘制
- 回测 + web_gui 组合:回测结束后想继续看图,程序不能退出:
except BacktestFinished as e:
print(acc.tqsdk_stat)
while True:
api.wait_update() # 保持进程活着,浏览器里继续看图
白话注解:web_gui 调试阶段神器——信号对不对、在哪根K线开的仓,图上一眼看出来。VPS 上无浏览器,加 web_gui=True 前想清楚(可远程端口转发访问)。
十五、异常处理与程序稳定性
from tqsdk import BacktestFinished
try:
api = TqApi(...)
while True:
api.wait_update(deadline=...)
...
except BacktestFinished:
api.close() # 回测正常结束
except Exception as e:
api.close()
print("策略异常退出:", type(e).__name__, e)
# 实盘:记录日志 → 告警 → 由守护进程重启并恢复现场
实盘稳定性清单:
- 主循环永远套 try/except,异常退出要告警而不是静默重启
- 重启后先
get_order()/get_position()恢复现场,再继续交易 wait_update(deadline=)加超时,行情长时间不来也能执行巡检逻辑- 日志写文件(带时间戳与合约名),出问题能复盘
- 风险度
risk_ratio熔断线写死在代码里
白话注解:程序崩了不可怕,可怕的是崩了没人知道、或者重启后带着旧持仓乱交易。实盘前三件事:告警渠道、状态恢复、风控熔断。
十六、TqSdk vs vn.py vs Backtrader
| 对比项 | TqSdk | vn.py | Backtrader |
|---|---|---|---|
| 入门难度 | 最简单(pip 装完即用) | 中等(CTP 环境配置多) | 简单 |
| 国内期货实盘 | 支持 CTP(云端中继) | 支持 CTP(本机直连) | 核心定位回测,可经 Store 扩展(IB 等) |
| 回测 | 内置,与实盘同代码 | 内置 | 内置,功能最全 |
| 图形界面 | web_gui 内置 | 完整 GUI 客户端 | matplotlib 静态图 |
| 股票/期权 | 期货+期权+股票(部分专业版) | 全市场网关丰富 | 靠数据源扩展 |
| 适合 | 国内期货入门与中低频策略 | 专业期货量化、多市场 | 回测研究与学习 |
白话注解:国内期货从零起步,选 TqSdk 上手最快;要接多家期货公司、多市场、复杂网关,上 vn.py;纯研究回测,Backtrader。三者不冲突,很多团队回测用 Backtrader、实盘用 TqSdk/vn.py。
十七、VPS 部署注意事项
TqSdk 跑实盘建议用 VPS:
- 选离期货公司机房近的服务器(比如上海)
- Windows Server 或 Linux 都可以
- 保持网络稳定,断线重连 TqSdk 自动处理,但主循环要套 try/except
- 用 systemd / 任务计划守护进程自动拉起,重启后先恢复持仓现场再交易
- 日志落盘 + 告警通知(微信/短信),异常必知
白话注解:为什么要用 VPS?因为你电脑关机了策略就停了。VPS 是一台 24 小时不关机的远程电脑,放在期货公司机房旁边,下单速度最快。
十八、本课小结
- TqSdk 纯 Python,pip 安装,回测/实盘同一套代码
- 三种账户:
TqSim本地模拟 /TqKq快期模拟 /TqAccount实盘 - 合约代码规则与主连不能直接交易(用
underlying_symbol) - 主循环 =
wait_update+is_changing;信号用定型K线iloc[-2] insert_order下单(记住平今平昨规则),get_order/get_trade管委托TargetPosTask声明目标持仓,框架自动开平仓与追单TqBacktest一行切回测,except BacktestFinished拿tqsdk_stat统计- tafunc 提供 ma/crossup/hhv/llv 及 get_sharp 等绩效函数
- 回测乐观于实盘:先模拟、再小仓、风控熔断写进代码
本站固定免责声明:本教程仅讲解软件编程与操作方法,不构成投资建议或策略推荐。回测业绩不代表未来收益,EA自动交易风险大,请谨慎决策。
💬 用户评价 (0)
立即登录