简介
什么是TqSdk
天勤量化(TqSdk),一款主要针对期货场景的量化投资平台。
- 官网:https://www.shinnytech.com/tianqin/
- 官方文档:https://doc.shinnytech.com/tqsdk/latest/
- GitHub地址:https://github.com/shinnytech/tqsdk-python
注册
在官网的用户中心处,即可注册账号。
注册之后,可以绑定实盘。
安装
1 | pip install tqsdk |
获取行情
get_quote
使用方法
1 | get_quote(self, symbol: str) |
入参有且仅有一个symbol
,只允许输入一个合约代码,如果我们想订阅多个合约,可以利用下文的get_quote_list
。
合约代码格式为交易所代码.合约代码
,交易所代码如下:
CFFEX
:中金所SHFE
:上期所DCE
:大商所CZCE
:郑商所INE
:能源交易所(原油)SSE
:上交所SZSE
:深交所GFEX
:广期所
例子
示例代码:
1 | from tqsdk import TqApi, TqAuth |
运行结果:
1 | 在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/ |
关于Quote对象
- 精度为tikc级别
- 对象的属性,可以查看官方文档:https://doc.shinnytech.com/tqsdk/latest/reference/tqsdk.objs.html
注意
在不需要使用时,及时调用api.close()
释放。
get_quote_list
使用方法
1 | get_quote_list(self, symbols: List[str]) |
入参是合约列表,返回值是订阅列表。
例子
示例代码:
1 | from tqsdk import TqApi, TqAuth |
运行结果:
1 | 在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/ |
is_changing
使用方法
1 | is_changing(self, obj: Any, key: Union[str, List[str], None] = None) |
is_changing
的作用是判定obj最近是否有更新,当业务数据更新导致wait_update
返回后可以使用该函数判断,本次业务数据更新是否包含特定obj或其中某个字段。
参数:
obj
,(any),任意业务对象,包括get_quote()
返回的quote
,get_kline_serial()
返回的k_serial
,get_account
返回的account
等。key
,(str/list of str),可选,需要判断的字段,默认不指定。- 不指定:当该
obj
下的任意字段有更新时返回True
,否则返回False
。 str
:当该obj
下的指定字段有更新时返回True
,否则返回False
。list of str
: 当该obj
下的指定字段中的任何一个字段有更新时返回True
,否则返回False
。
- 不指定:当该
例子
示例代码:
1 | from tqsdk import TqApi, TqAuth, TqSim, TqBacktest |
注意
is_changing
判断的是本次wait_update
更新的数据,如果wait_update
有延迟或者阻塞,可能会导致is_changing
的返回与预期不符合。- 当生成新K线时,其所有字段都算作有更新,若此时执行
api.is_changing(klines.iloc[-1])
则一定返回True。
获取K线行情
使用方法
1 | get_kline_serial(self, |
请求指定合约及周期的K线数据,序列数据会随着时间推进自动更新。
参数说明:
symbol
,(str/list of str),指定合约代码或合约代码列表。str
:一个合约代码list of str
:合约代码列表(一次提取多个合约的K线并根据相同的时间向第一个合约(主合约)对齐)
duration_seconds
,(int):K线数据周期,以秒为单位。- 例如,1分钟线为60,1小时线为3600,日线为86400。
- 注意,周期在日线以内时此参数可以任意填写,在日线以上时只能是日线(86400)的整数倍,最大为28天(86400*28)。
data_length
,(int):需要获取的序列长度。
默认200根,返回的K线序列数据是从当前最新一根K线开始往回取data_length根。chart_id
,(str):可选,指定序列id, 默认由api自动生成。adj_type
,(str/None):可选,指定复权类型,默认为None。
adj_type
参数只对股票和基金类型合约有效,"F"
表示前复权,"B"
表示后复权,None
表示不做处理。
歧义
在TqSdk的源代码的注释及其官方文档中,data_length
的长度的最大值均是8000,但是在其教学视频中,确明确说明最大为8964。
参考https://www.shinnytech.com/usage-example/
的使用K线和Tick数据
的3分23秒。
注意
- 主合约的字段名为原始K线数据字段,从第一个副合约开始,字段名在原始字段后加数字,如第一个副合约的开盘价为
open1
,第二个副合约的收盘价为close2
。 - 每条K线都包含了订阅的所有合约数据,即:如果任意一个合约(无论主、副)在某个时刻没有数据(即使其他合约在此时有数据),则不能对齐,此多合约K线在该时刻那条数据被跳过,现象表现为K线不连续(如主合约有夜盘,而副合约无夜盘,则生成的多合约K线无夜盘时间的数据)。
- 若设置了较大的序列长度参数,而所有可对齐的数据并没有这么多,则序列前面部分数据为NaN(这与获取单合约K线且数据不足序列长度时情况相似)。
- 若主合约与副合约的交易时间在所有合约数据中最晚一根K线时间开始往回的8000*周期时间段内完全不重合,则无法生成多合约K线,程序会报出获取数据超时异常。
- datetime、duration是所有合约公用的字段,则未单独为每个副合约增加一份副本,这两个字段使用原始字段名(即没有数字后缀)。
- 获取多合约K线,若填入
adj_type
,程序会报参数错误。
图形化
使用方法
只需要在创建API实例的时候,设置web_gui
即可。
web_gui
,(bool/str),可选,是否启用图形化界面功能, 默认不启用。
- 启用图形化界面传入参数
web_gui=True
会每次以随机端口生成网页
也可以直接设置本机IP和端口web_gui=[ip]:port
为网页地址,ip
可选,默认为0.0.0.0
,如果只指定端口,需要在端口前面填:
。 - 为了图形化界面能够接收到程序传输的数据并且刷新,在程序中,需要循环调用
api.wait_update()
的形式去更新和获取数据。
例子
示例代码:
1 | from tqsdk import TqApi, TqAuth |
运行结果:
1 | 在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/ |
点击右侧,即可切换合约。
画指标线
以绘制20日均线为例,主要两步:
- 定义20日均线
ma = MA(kline_serial, n=20)
- 20日均线添加到
kline_serial
kline_serial['ma_MAIN'] = ma.ma
1 | from tqsdk import TqApi, TqAuth |
下单和撤单
insert_order(下单)
1 | insert_order(self, |
参数:
symbol
,(str),拟下单的合约symbol,格式为交易所代码.合约代码
。direction
,(str),"BUY"
或"SELL"
offset
,(str)
"OPEN"
,"CLOSE"
或"CLOSETODAY"
上期所和上期能源分平今/平昨,平今用"CLOSETODAY"
,平昨用"CLOSE"
,其他交易所直接用"CLOSE"
,按照交易所的规则平仓。volume
,(int),下单交易数量,期货为下单手数,A股股票为股数。limit_price
,(float | str),可选,下单价格,默认为None
,股票交易目前仅支持限价单,该字段必须指定。- 数字类型,限价单,按照限定价格或者更优价格成交
None
,市价单,默认值就是市价单(郑商所期货/期权、大商所期货支持)"BEST"
,最优一档,以对手方实时最优一档价格为成交价格成交(仅中金所支持)"FIVELEVEL"
,最优五档,在对手方实时最优五个价位内以对手方价格为成交价格依次成交(仅中金所支持)
advanced
,(str),可选,"FAK"
,"FOK"
,默认为None
,股票交易中该参数不支持。None
,对于限价单,任意手数成交,委托单当日有效;对于市价单、最优一档、最优五档(与FAK
指令一致),任意手数成交,剩余撤单。"FAK"
,剩余即撤销,指在指定价位成交,剩余委托自动被系统撤销。(限价单、市价单、最优一档、最优五档有效)。"FOK"
,全成或全撤,指在指定价位要么全部成交,否则全部自动被系统撤销。(限价单、市价单有效,郑商所期货品种不支持FOK
)。
order_id
,(str),可选,指定下单单号,默认由api
自动生成,股票交易下单时,无需指定。account
,(TqAccount
/TqKq
/TqKqStock
/TqSim
),可选,指定发送下单指令的账户实例,多账户模式下,该参数必须指定
cancel_order(撤单)
1 | cancel_order(self, order_or_order_id: Union[str, Order], account: Optional[UnionTradeable] = None) |
参数:
order_or_order_id
,(str/ :py:class:~tqsdk.objs.Order
),拟撤委托单或单号。
即上一步insert_order
的入参order_id
,或者返回的Order
对象。account
,(TqAccount
/TqKq
/TqKqStock
/TqSim
/TqSimStock
),可选,指定发送撤单指令的账户实例,多账户模式下,该参数必须指定。
例子
1 | from tqsdk import TqApi, TqAuth |
解释说明:
ALIVE
的本质是委托单状态可以变化FINISHED
的本质是委托单状态不再变化
注意下单规则
在天勤量化TqSdk中,指令将在下次调用wait_update()
时发出
在天勤量化TqSdk的官方文档,有如下的论述:
关于insert_order
和cancel_order
,有如下的论述:
关于wait_update
,有如下的论述:
即,其结构如下:
模拟
在天勤量化(TqSdk)中,支持两种模拟方式,分别是:
TqSim
天勤模拟,信息都是本地存储,程序关闭,信息清除。TqKq
快期模拟,信息同步至信易账号,可以在快期程序中查看。
两种调用方式,只需要修改TqApi
的构造方法的第一个参数即可。
TqSim
,天勤模拟,示例代码:
1 | from tqsdk import TqApi, TqAuth, TqSim |
TqKq
,快期模拟,示例代码:
1 | from tqsdk import TqApi, TqAuth, TqKq |
实盘
在进行实盘交易时,指定TqApi
构造方法的第一个参数为TqAccount
。
示例代码:
1 | from tqsdk import TqApi, TqAuth, TqAccount |
TqAccount
的参数有:
broker_id
,(str),期货公司。
支持的期货公司列表:https://www.shinnytech.com/blog/tq-support-broker/account_id
,(str),帐号。password
,(str),密码。td_url
,(str),可选,用于指定账户连接的交易服务器地址。sm
,(bool),可选,是否通过国密连接到服务器。
回测
使用方法
将TqBacktest
类的对象传入TqApi的构造函数,则策略就会进入回测模式。
1 | from tqsdk import TqApi, TqAuth, TqSim, TqBacktest |
参数:
start_dt
,(date/datetime),回测起始时间,如果类型为date
则指的是交易日,如果为datetime
则指的是具体时间点。end_dt
,(date/datetime),回测结束时间,如果类型为date
则指的是交易日,如果为datetime
则指的是具体时间点。
注意
- 回测模式下L会在刚创建出来时和结束时分别更新一次,在这之间K是不会更新的。
- 回测模式下quote的更新频率由所订阅的
tick
和K线周期确定:- 只要订阅了
tick
,则对应合约的quote
就会使用tick
生成,更新频率也和tick
一致,但只有以下字段:datetime
、ask&bid_price1
、ask&bid_volume1
、last_price
、highest
、lowest
、average
、volume
、amount
、open_interest
、price_tick
、price_decs
、volume_multiple
、max&min_limit&market_order_volume
、underlying_symbol
、strike_price
。 - 如果没有订阅
tick
,但是订阅了K线,则对应合约的quote会使用K线生成,更新频率和K线的周期一致
如果订阅了某个合约的多个周期的K线,则任一个周期的K线有更新时,quote都会更新。
使用K线生成的quote的盘口由收盘价分别加/减一个最小变动单位,并且highest
、lowest
、average
、amount
始终为nan
,volume
始终为0 - 如果即没有订阅tick,也没有订阅K线或订阅的K线周期大于分钟线,则TqBacktest会 自动订阅分钟线 来生成quote。
- 如果没有订阅tick,但是订阅了K线,则对应合约的quote只有下字段:
datetime
、ask&bid_price1
、ask&bid_volume1
、last_price
、open_interest
、price_tick
、price_decs
、volume_multiple
、max&min_limit&market_order_volume
、underlying_symbol
、strike_price
。
- 只要订阅了
- 模拟交易要求报单价格大于等于对手盘价格才会成交,例如下买单,要求价格大于等于卖一价才会成交,如果不能立即成交则会等到下次行情更新再重新判断。
- 回测模式下
wait_update
每次最多推进一个行情时间。 - 回测结束后会抛出BacktestFinished。
- 对 组合合约 进行回测时需注意,只能通过订阅
tick
数据来回测,不能订阅K线,因为K线是由最新价合成的,而交易所发回的组合合约数据中无最新价。
复盘
使用方法
指定TqApi
构造方法的backtest
参数为TqReplay
类的对象。
示例代码:
1 | from tqsdk import TqApi, TqAuth, TqReplay, TqSim |
和回测模式的区别
除了传统的回测模式以外,TqSdk提供独具特色的复盘模式,它与回测模式有以下区别:
- 复盘模式为时间驱动,回测模式为事件驱动。
在复盘模式下,你可以指定任意一天交易日,后端行情服务器会传输用户订阅合约的当天的所有历史行情数据,重演当天行情。
在回测模式下,我们根据用户订阅的合约周期数据来进行推送。
因此在复盘模式下K线更新和实盘一模一样,而在回测模式下就算订阅了Tick数据,回测中任意周期K线最后一根的 close 和其他数据也不会随着 Tick 更新而更新,而是随着K线频率生成和结束时更新一次。 - 复盘和回测的行情速度
因为两者的驱动机制不同,回测会更快,但是在复盘模式下也提供行情速度调节功能,可以结合web_gui来实现。 - 复盘目前只支持单日复盘
因为复盘提供对应合约当日全部历史行情数据,对后端服务器会有较大压力,目前只支持复盘模式下选择单日进行复盘。
超时问题
下载数据
使用
DataDownloader
,数据下载工具,是TqSdk专业版中的功能,能让用户下载目前TqSdk提供的全部期货、期权和股票类的历史数据,下载数据支持tick级别精度和任意kline周期。
参数:
api
,(TqApi),TqApi实例,该下载器将使用指定的api下载数据。symbol_list
,(str/list of str),需要下载数据的合约代码,当指定多个合约代码时将其他合约按第一个合约的交易时间对齐。dur_sec
,(int),数据周期,以秒为单位。
例如: 1分钟线为60,1小时线为3600,日线为86400,Tick数据为0。start_dt
,(date/datetime),起始时间,如果类型为date
则指的是交易日,如果为datetime
则指的是具体时间点。end_dt
,(date/datetime),结束时间, 如果类型为date
则指的是交易日, 如果为datetime
则指的是具体时间点。csv_file_name
,(str/StreamWriter),必填,输出方式:str
:输出csv的文件名StreamWriter
:直接将内容输出到StreamWriter
adj_type
,(str/None),复权计算方式,默认值为None。
"F"
为前复权;"B"
为后复权;None
表示不复权。
只对股票、基金合约有效。
例子
示例代码:
1 | from datetime import datetime, date |
同时下载
在上例中,我们是同时下载。同时下载可能会更快,但是当我们同时进行下载的任务特别多的时候,不一定会更快。
(就好比,多线程太多,不一定就是快。)
时间范围
- 期货和相关期权的数据从2016年开始
- 股票和相关期权的数据从2018年开始
简单趋势策略(案例)
策略思路
- 连续三根阴线就做空
- 连续三根阳线就做多
- 否则空仓
实现代码
1 | # 策略思路连续了根阴线就做空,连绩了根阳线就做多,否则空仓 |
为什么是length + 1
解释一下为什么get_kline_serial
中的data_length
是length + 1
,而不是length
。
1 | # 获取SHFE.ni2307的10秒K线的引用,长度为length + 1 |
因为通过is_changing
所获取的K线,不一定是一根完整的K线,所以判断阴线和阳线的数量,应该通过前length + 1
根K线判断。
1 | api.wait_update() |
这也是为什么我们跳过最后一根刚生成的K线。
1 | # 跳过最后一根刚生成的K线 |
价差回归策略(案例)
策略思路
当近月合约减去远月合约的价差:
- 大于250时,做空近月合约,做多远月合约。
- 小于200时,平仓。
实现代码
1 | from tqsdk import TqApi, TqAuth, TargetPosTask |
运行结果:
1 | 在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/ |