avatar


天勤量化(TqSdk)入门

简介

什么是TqSdk

天勤量化(TqSdk),一款主要针对期货场景的量化投资平台。

《和量化投资相关的一些软件:量化投资平台QMT入门》,我们讨论过QMT,QMT主要针对股票量化,天勤TqSdk主要针对期货量化。

注册

在官网的用户中心处,即可注册账号。

注册

注册之后,可以绑定实盘。

绑定实盘

安装

1
pip install tqsdk

获取行情

get_quote

使用方法

1
get_quote(self, symbol: str)

入参有且仅有一个symbol,只允许输入一个合约代码,如果我们想订阅多个合约,可以利用下文的get_quote_list

合约代码格式为交易所代码.合约代码,交易所代码如下:

  • CFFEX:中金所
  • SHFE:上期所
  • DCE:大商所
  • CZCE:郑商所
  • INE:能源交易所(原油)
  • SSE:上交所
  • SZSE:深交所
  • GFEX:广期所

题外话,这个代码格式,和Tushare正好相反,Tushare中的是格式是合约代码.交易所代码
参考链接:https://tushare.pro/document/2?doc_id=134

例子

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from tqsdk import TqApi, TqAuth

# 创建API实例
api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))
# 订阅实时行情
quote = api.get_quote("SHFE.ni2307")

# 主动获取行情
print(quote.last_price)

while True:
# 等待行情更新
api.wait_update()
print (quote.datetime, quote.last_price, quote.volume)

运行结果:

1
2
3
4
在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/
2023-07-17 19:31:10 - INFO - 通知 : 与 wss://api.shinnytech.com/t/nfmd/front/mobile 的网络连接已建立
170000.0
2023-07-17 14:59:59.000001 170000.0 24

关于Quote对象

注意

在不需要使用时,及时调用api.close()释放。

get_quote_list

使用方法

1
get_quote_list(self, symbols: List[str])

入参是合约列表,返回值是订阅列表。

例子

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from tqsdk import TqApi, TqAuth

# 创建API实例
api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))
# 订阅实时行情
quote_list = api.get_quote_list(symbols=['SHFE.ni2307', 'DCE.pg2307'])

# 主动获取行情
print(quote_list[0].last_price)
print(quote_list[1].last_price)

while True:
# 等待行情更新
api.wait_update()
for quote_list_iter in quote_list:
print(quote_list_iter.datetime, quote_list_iter.last_price, quote_list_iter.volume)

运行结果:

1
2
3
4
5
6
在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/
2023-07-17 19:50:47 - INFO - 通知 : 与 wss://api.shinnytech.com/t/nfmd/front/mobile 的网络连接已建立
170000.0
3960.0
2023-07-17 14:59:59.000001 170000.0 24
2023-07-17 14:59:59.999501 3960.0 10

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()返回的quoteget_kline_serial()返回的k_serialget_account返回的 account等。
  • key,(str/list of str),可选,需要判断的字段,默认不指定。
    • 不指定:当该obj下的任意字段有更新时返回True,否则返回False
    • str:当该obj下的指定字段有更新时返回True,否则返回False
    • list of str: 当该obj下的指定字段中的任何一个字段有更新时返回True,否则返回False

例子

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
from tqsdk import TqApi, TqAuth, TqSim, TqBacktest
from datetime import date

# 创建API实例
api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')
# 订阅实时行情
quote = api.get_quote("SHFE.ni2307")

while True:
api.wait_update()
if api.is_changing(quote, "last_price"):
print(quote.last_price)

注意

  • is_changing判断的是本次wait_update更新的数据,如果wait_update有延迟或者阻塞,可能会导致is_changing的返回与预期不符合。
  • 当生成新K线时,其所有字段都算作有更新,若此时执行api.is_changing(klines.iloc[-1])则一定返回True。

获取K线行情

使用方法

1
2
3
4
5
6
get_kline_serial(self, 
symbol: Union[str, List[str]],
duration_seconds: int,
data_length: int = 200,
chart_id: Optional[str] = None,
adj_type: Union[str, None] = None)

请求指定合约及周期的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秒。

TqSdk

注意

  1. 主合约的字段名为原始K线数据字段,从第一个副合约开始,字段名在原始字段后加数字,如第一个副合约的开盘价为open1,第二个副合约的收盘价为 close2
  2. 每条K线都包含了订阅的所有合约数据,即:如果任意一个合约(无论主、副)在某个时刻没有数据(即使其他合约在此时有数据),则不能对齐,此多合约K线在该时刻那条数据被跳过,现象表现为K线不连续(如主合约有夜盘,而副合约无夜盘,则生成的多合约K线无夜盘时间的数据)。
  3. 若设置了较大的序列长度参数,而所有可对齐的数据并没有这么多,则序列前面部分数据为NaN(这与获取单合约K线且数据不足序列长度时情况相似)。
  4. 若主合约与副合约的交易时间在所有合约数据中最晚一根K线时间开始往回的8000*周期时间段内完全不重合,则无法生成多合约K线,程序会报出获取数据超时异常。
  5. datetime、duration是所有合约公用的字段,则未单独为每个副合约增加一份副本,这两个字段使用原始字段名(即没有数字后缀)。
  6. 获取多合约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
2
3
4
5
6
7
8
9
from tqsdk import TqApi, TqAuth

# 创建API实例
api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')
# 订阅实时行情
kline_serial = api.get_kline_serial(symbol=['SHFE.ni2307', 'DCE.pg2307'], duration_seconds=10)

while True:
api.wait_update()

运行结果:

1
2
3
在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/
2023-07-17 20:24:43 - INFO - 您可以访问 http://127.0.0.1:9999 查看策略绘制出的 K 线图形。
2023-07-17 20:24:45 - INFO - 通知 : 与 wss://api.shinnytech.com/t/nfmd/front/mobile 的网络连接已建立

点击右侧,即可切换合约。
web_gui

画指标线

以绘制20日均线为例,主要两步:

  1. 定义20日均线
    ma = MA(kline_serial, n=20)
  2. 20日均线添加到kline_serial
    kline_serial['ma_MAIN'] = ma.ma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from tqsdk import TqApi, TqAuth
from tqsdk.ta import MA

# 创建API实例
api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')
# 订阅实时行情
kline_serial = api.get_kline_serial(symbol='SHFE.ni2307', duration_seconds=10)

# 绘制20日均线
ma = MA(kline_serial, n=20)
kline_serial['ma_MAIN'] = ma.ma

while True:
api.wait_update()

下单和撤单

insert_order(下单)

1
2
3
4
5
6
7
8
9
insert_order(self, 
symbol: str,
direction: str,
offset: str = "",
volume: int = 0,
limit_price: Union[str, float, None] = None,
advanced: Optional[str] = None,
order_id: Optional[str] = None,
account: Optional[UnionTradeable] = None)

参数:

  • 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from tqsdk import TqApi, TqAuth

api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))
quote = api.get_quote("DCE.m1809")
order = {}

while True:
api.wait_update()
# 当行情有变化且当前挂单价格不优时,则撤单
if order and \
api.is_changing(quote) and \
order.status == "ALIVE" and quote.bid_price1 > order.limit_price:
print("价格改变,撤单重下")
api.cancel_order(order)
# 当委托单已撤或还没有下单时则下单
if (not order and api.is_changing(quote)) or \
(api.is_changing(order) and order.volume_left != 0 and order.status == "FINISHED"):
print("下单: 价格 %f" % quote.bid_price1)
order = api.insert_order(symbol="DCE.m1809",
direction="BUY",
offset="OPEN",
volume=order.get("volume_left", 3),
limit_price=quote.bid_price1)
if api.is_changing(order):
print("单状态: %s, 已成交: %d 手" % (order.status, order.volume_orign - order.volume_left))

解释说明:

  • ALIVE的本质是委托单状态可以变化
  • FINISHED的本质是委托单状态不再变化

注意下单规则

《和量化投资相关的一些软件:量化投资平台QMT入门》,我们讨论过两种下单规则:

  1. K线走完(Bar结束)下单
  2. 立即下单

这是一个"坑",这个"坑"在TqSdk中同样存在。

在天勤量化TqSdk中,指令将在下次调用wait_update()时发出

在天勤量化TqSdk的官方文档,有如下的论述:

关于insert_ordercancel_order,有如下的论述:

下单规则-1

关于wait_update,有如下的论述:

下单规则-2

即,其结构如下:

下单规则-3

模拟

在天勤量化(TqSdk)中,支持两种模拟方式,分别是:

  1. TqSim
    天勤模拟,信息都是本地存储,程序关闭,信息清除。
  2. TqKq
    快期模拟,信息同步至信易账号,可以在快期程序中查看。

两种调用方式,只需要修改TqApi的构造方法的第一个参数即可。

TqSim,天勤模拟,示例代码:

1
2
3
4
from tqsdk import TqApi, TqAuth, TqSim

# 创建API实例
api = TqApi(TqSim(), auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')

TqKq,快期模拟,示例代码:

1
2
3
4
from tqsdk import TqApi, TqAuth, TqKq

# 创建API实例
api = TqApi(TqKq(), auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')

实盘

在进行实盘交易时,指定TqApi构造方法的第一个参数为TqAccount

示例代码:

1
2
3
4
from tqsdk import TqApi, TqAuth, TqAccount

# 创建API实例
api = TqApi(TqAccount(), auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')

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
2
3
4
5
6
7
8
9
10
from tqsdk import TqApi, TqAuth, TqSim, TqBacktest
from datetime import date

# 创建API实例
api = TqApi(TqSim(),
backtest=TqBacktest(
start_dt=date(2023, 6, 1),
end_dt=date(2023, 7, 17)),
auth=TqAuth("【天勤账号】", "【天勤密码】"),
web_gui=':9999')

参数:

  • start_dt,(date/datetime),回测起始时间,如果类型为date则指的是交易日,如果为datetime则指的是具体时间点。
  • end_dt,(date/datetime),回测结束时间,如果类型为date则指的是交易日,如果为datetime则指的是具体时间点。

注意

  1. 回测模式下L会在刚创建出来时和结束时分别更新一次,在这之间K是不会更新的。
  2. 回测模式下quote的更新频率由所订阅的tick和K线周期确定:
    • 只要订阅了tick,则对应合约的quote就会使用tick生成,更新频率也和tick一致,但只有以下字段:datetimeask&bid_price1ask&bid_volume1last_pricehighestlowestaveragevolumeamountopen_interestprice_tickprice_decsvolume_multiplemax&min_limit&market_order_volumeunderlying_symbolstrike_price
    • 如果没有订阅tick,但是订阅了K线,则对应合约的quote会使用K线生成,更新频率和K线的周期一致
      如果订阅了某个合约的多个周期的K线,则任一个周期的K线有更新时,quote都会更新。
      使用K线生成的quote的盘口由收盘价分别加/减一个最小变动单位,并且highestlowestaverageamount始终为nanvolume始终为0
    • 如果即没有订阅tick,也没有订阅K线或订阅的K线周期大于分钟线,则TqBacktest会 自动订阅分钟线 来生成quote。
    • 如果没有订阅tick,但是订阅了K线,则对应合约的quote只有下字段:datetimeask&bid_price1ask&bid_volume1last_priceopen_interestprice_tickprice_decsvolume_multiplemax&min_limit&market_order_volumeunderlying_symbolstrike_price
  3. 模拟交易要求报单价格大于等于对手盘价格才会成交,例如下买单,要求价格大于等于卖一价才会成交,如果不能立即成交则会等到下次行情更新再重新判断。
  4. 回测模式下wait_update每次最多推进一个行情时间。
  5. 回测结束后会抛出BacktestFinished。
  6. 组合合约 进行回测时需注意,只能通过订阅tick数据来回测,不能订阅K线,因为K线是由最新价合成的,而交易所发回的组合合约数据中无最新价。

复盘

使用方法

指定TqApi构造方法的backtest参数为TqReplay类的对象。

示例代码:

1
2
3
4
5
from tqsdk import TqApi, TqAuth, TqReplay, TqSim
from datetime import date

# 创建API实例
api = TqApi(TqSim(), backtest=TqReplay(date(2023, 7, 17)), auth=TqAuth("【天勤账号】", "【天勤密码】"), web_gui=':9999')

和回测模式的区别

除了传统的回测模式以外,TqSdk提供独具特色的复盘模式,它与回测模式有以下区别:

  1. 复盘模式为时间驱动,回测模式为事件驱动。
    在复盘模式下,你可以指定任意一天交易日,后端行情服务器会传输用户订阅合约的当天的所有历史行情数据,重演当天行情。
    在回测模式下,我们根据用户订阅的合约周期数据来进行推送。
    因此在复盘模式下K线更新和实盘一模一样,而在回测模式下就算订阅了Tick数据,回测中任意周期K线最后一根的 close 和其他数据也不会随着 Tick 更新而更新,而是随着K线频率生成和结束时更新一次。
  2. 复盘和回测的行情速度
    因为两者的驱动机制不同,回测会更快,但是在复盘模式下也提供行情速度调节功能,可以结合web_gui来实现。
  3. 复盘目前只支持单日复盘
    因为复盘提供对应合约当日全部历史行情数据,对后端服务器会有较大压力,目前只支持复盘模式下选择单日进行复盘。

超时问题

超时问题

下载数据

使用

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from datetime import datetime, date
from contextlib import closing
from tqsdk import TqApi, TqAuth, TqSim
from tqsdk.tools import DataDownloader

api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))

download_tasks = {}

# 下载从 2018-01-01 到 2018-09-01 的 SR901 日线数据
download_tasks["SR_daily"] = DataDownloader(api, symbol_list="CZCE.SR901", dur_sec=24 * 60 * 60,
start_dt=date(2018, 1, 1), end_dt=date(2018, 9, 1),
csv_file_name="SR901_daily.csv")

# 下载从 2017-01-01 到 2018-09-01 的 rb主连 5分钟线数据
download_tasks["rb_5min"] = DataDownloader(api, symbol_list="KQ.m@SHFE.rb", dur_sec=5 * 60,
start_dt=date(2017, 1, 1), end_dt=date(2018, 9, 1),
csv_file_name="rb_5min.csv")

# 下载从 2018-01-01凌晨6点 到 2018-06-01下午4点 的 cu1805,cu1807,IC1803 分钟线数据,所有数据按 cu1805 的时间对齐
# 例如 cu1805 夜盘交易时段, IC1803 的各项数据为 N/A
# 例如 cu1805 13:00-13:30 不交易, 因此 IC1803 在 13:00-13:30 之间的K线数据会被跳过
download_tasks["cu_min"] = DataDownloader(api, symbol_list=["SHFE.cu1805", "SHFE.cu1807", "CFFEX.IC1803"], dur_sec=60,
start_dt=datetime(2018, 1, 1, 6, 0, 0), end_dt=datetime(2018, 6, 1, 16, 0, 0),
csv_file_name="cu_min.csv")

# 下载从 2018-05-01凌晨0点 到 2018-06-01凌晨0点 的 T1809 盘口Tick数据
download_tasks["T_tick"] = DataDownloader(api, symbol_list=["CFFEX.T1809"], dur_sec=0,
start_dt=datetime(2018, 5, 1), end_dt=datetime(2018, 6, 1),
csv_file_name="T1809_tick.csv")

# 使用with closing机制确保下载完成后释放对应的资源
with closing(api):
while not all([v.is_finished() for v in download_tasks.values()]):
api.wait_update()
print("progress: ", {k: ("%.2f%%" % v.get_progress()) for k, v in download_tasks.items()})

同时下载

在上例中,我们是同时下载。同时下载可能会更快,但是当我们同时进行下载的任务特别多的时候,不一定会更快。

(就好比,多线程太多,不一定就是快。)

时间范围

  • 期货和相关期权的数据从2016年开始
  • 股票和相关期权的数据从2018年开始

简单趋势策略(案例)

策略思路

  1. 连续三根阴线就做空
  2. 连续三根阳线就做多
  3. 否则空仓

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 策略思路连续了根阴线就做空,连绩了根阳线就做多,否则空仓
from tqsdk import TqApi, TqAuth, TargetPosTask

api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))

# 设定连续多少根阳线 / 阴线
length = 3
# 获取SHFE.ni2307的10秒K线的引用,长度为length + 1
kline_serial = api.get_kline_serial("SHFE.ni2307", 10, data_length=length + 1)
# 创建SHFE.ni2307的目标持仓task,该task负责调整SHFE.ni2307的仓位到指定的日标仓位
target_pos = TargetPosTask(api, "SHFE.ni2105", offset_priority="今昨开")
while True:
api.wait_update()
# 只有在新创建出K线时才判断开平仓条件
if api.is_changing(kline_serial.iloc[-1], "datetime"):
# 跳过最后一根刚生成的K线
df = kline_serial.iloc[:-1]
# 比较收盘价和开盘价,判断是阳线还是阴线
# df.close 为收盘价序列,df.open 为开盘价序列,
# ">"(pandas.series.gt)返回收盘价是否大于开盘的一个新序列
up = df.close > df.open
down = df.close < df.open
if all(up):
print("连续阳线:目标持仓 多头1手")
# 设置日标持仓为正数表示多头,负数表示空头,0表示空仓
target_pos.set_target_volume(1)
elif all(down):
print("连续阴线:目标持仓 空头1手")
target_pos.set_target_volume(-1)
else:
print("目标持仓:空仓")
target_pos.set_target_volume(0)

为什么是length + 1

解释一下为什么get_kline_serial中的data_lengthlength + 1,而不是length

1
2
# 获取SHFE.ni2307的10秒K线的引用,长度为length + 1
kline_serial = api.get_kline_serial("SHFE.ni2307", 10, data_length=length + 1)

因为通过is_changing所获取的K线,不一定是一根完整的K线,所以判断阴线和阳线的数量,应该通过前length + 1根K线判断。

1
2
3
api.wait_update()
# 只有在新创建出K线时才判断开平仓条件
if api.is_changing(kline_serial.iloc[-1], "datetime"):

这也是为什么我们跳过最后一根刚生成的K线。

1
2
# 跳过最后一根刚生成的K线
df = kline_serial.iloc[:-1]

价差回归策略(案例)

策略思路

当近月合约减去远月合约的价差:

  • 大于250时,做空近月合约,做多远月合约。
  • 小于200时,平仓。

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from tqsdk import TqApi, TqAuth, TargetPosTask

api = TqApi(auth=TqAuth("【天勤账号】", "【天勤密码】"))

quote_near = api.get_quote("SHFE.ni2307")
quote_deferred = api.get_quote("SHFE.ni2308")

# 创建 ni2307 的目标持仓task,该task 负责调整 ni2307 的仓位到指定的目标仓位
target_pos_near = TargetPosTask(api, "SHFE.ni2307")
# 创建 ni2308 的目标持仓 task,该task 负责调整 ni2308 的仓位到指定的目标仓位
target_pos_deferred = TargetPosTask(api, "SHFE.ni2308")

while True:
api.wait_update()
if api.is_changing(quote_near) or api.is_changing(quote_deferred):
spread = quote_near.last_price - quote_deferred.last_price
print("当前价差:", spread)
if spread > 250:
print("目标持仓:空近月,多远月")
# 设置目标持仓为正数表示多头,负数表示空头,口表示空仓
target_pos_near.set_target_volume(-1)
target_pos_deferred.set_target_volume(1)
elif spread < 200:
print("目标持仓:空仓")
target_pos_near.set_target_volume(0)
target_pos_deferred.set_target_volume(0)

运行结果:

1
2
3
4
5
6
7
在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/
2023-07-17 23:47:36 - INFO - 通知 : 与 wss://api.shinnytech.com/t/nfmd/front/mobile 的网络连接已建立
当前价差: 7140.0
目标持仓:空近月,多远月
2023-07-17 23:47:37 - INFO - 模拟交易下单 TQSIM, PYSDK_target_4c1ab4a439431203e1d984a063e7db63: 时间: 2023-07-17 23:47:36.511996, 合约: SHFE.ni2307, 开平: OPEN, 方向: SELL, 手数: 1, 价格: 171000.0
2023-07-17 23:47:37 - INFO - 模拟交易下单 TQSIM, PYSDK_target_aaa9a7958188b8a43136c9ea7aba875c: 时间: 2023-07-17 23:47:36.512413, 合约: SHFE.ni2308, 开平: OPEN, 方向: BUY, 手数: 1, 价格: 162890.0
2023-07-17 23:47:37 - INFO - 模拟交易委托单 TQSIM, PYSDK_target_aaa9a7958188b8a43136c9ea7aba875c: 全部成交
文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/20502
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

评论区