基于时间维度目标持仓策略

本篇文档假设您已经了解 TargetPosTask 的用法,文档参考 交易辅助工具

简单来说,TargetPosTask 会创建 task,负责将指定合约调整到目标头寸(默认为账户的该合约净持仓)。

对于简单的大单拆分功能,可以在 TargetPosTask 类中设置拆分手数的上下限,TargetPosTask 实例在下单过程中就会将下单手数随机的拆分,以减少对市场冲击。

但是,对于比较复杂的下单策略,例如 twap(基于时间拆分手数),vwap(基于成交量拆分手数)等,使用 TargetPosTask 来构造策略不是很方便。

我们提供 TargetPosScheduler 类帮助用户完成复杂的下单策略,同时提供给用户极大的调整空间。

time_table 目标持仓任务列表

TargetPosScheduler 使用 time_table 参数来描述具体的下单策略。

time_tablepandas.DataFrame 类型。每一行表示一项目标持仓任务,每项任务按照顺序一个个执行。其应该包含以下几列:

  • interval: 当前这项任务的持续时间长度,单位为秒,经过这么多秒之后,此项任务应该退出,剩余未调整到的目标持仓,会留到下一项任务中
    • 注意1:对于最后一项任务,会按照当前项参数,调整到目标持仓后立即退出(时间参数不对最后一项任务起作用)

    • 注意2:时间长度可以跨非交易时间段(可以跨小节等待),但是不可以跨交易日

  • target_pos: 当前这项任务的目标净持仓手数

  • price: 当前这项任务的下单价格模式,此列中非 None 的项,会作为创建 TargetPosTask 实例的 price 参数,支持以下几种参数:
    • None: 不下单,表示暂停一段时间

    • "PASSIVE" : 排队价下单

    • "ACTIVE": 对价下单

    • Callable (direction: str) -> Union[float, int]: 传入函数作为价格参数,函数参数为下单方向,函数返回值是下单价格。如果返回 nan,程序会抛错。

TargetPosScheduler 执行目标持仓任务列表

TargetPosScheduler 类创建 target_pos_scheduler 实例,首先会将 time_tableinterval 间隔时间列转为 deadline,即这项任务结束时间的纳秒数。

然后,依次为 time_table 中的每一项任务创建 TargetPosTask 实例,调整目标持仓,并在到达 deadline 时退出。每一项未完成的目标持仓都会留都下一项任务中。

需要注意的是,最后一项任务,是以手数达到目标的,会按照当前项参数,调整到目标持仓再退出。如果最后一项 price 参数为 None (表示不下单),由于无法调整持仓,那么会立即退出。

简单示例

简单示例及说明如下:

time_table = DataFrame([
    [25, 10, "PASSIVE"]
    [5, 10, "ACTIVE"]
    [30, 18, "PASSIVE"]
    [5, 18, "ACTIVE"]
], columns=['interval', 'target_pos', 'price'])

target_pos_scheduler = TargetPosScheduler(api, "SHFE.cu2112", time_table)

# 这个 time_table 表示的下单策略依次是:
# 1. 使用排队价下单,调整 "SHFE.cu2112" 到 10 手,到达 25s 时退出(无论目标手数是否达到,都不会继续下单)
# 2. 使用对价下单,调整 "SHFE.cu2112" 到 10 手,到达 5s 时退出
#    如果上一步结束时目标持仓已经达到 10 手,这一步什么都不会做,等待 5s 到下一步;
#    如果上一步结束时目标持仓没有达到 10 手,这一步会继续调整目标持仓到 10 手
# 3. 使用排队价下单,调整 "SHFE.cu2112" 到 18 手,到达 30s 时退出(无论目标手数是否达到,都不会继续下单)
# 4. 使用对价下单,调整 "SHFE.cu2112" 到 18 手
#    如果上一步结束时目标持仓已经达到 18 手,这一步什么都不会做,立即退出;
#    如果上一步结束时目标持仓没有达到 18 手,这一步会继续调整目标持仓到 18 手后退出

到此为止,您可以根据您的具体策略构造出任意的 time_table 对象,然后调用 TargetPosScheduler 来执行。

为了方便用户使用,我们提供了 twap_table() 来生成一个默认的符合 twap 策略的 time_table 实例。

基于 TargetPosScheduler 的 twap 策略示例

我们在 tqsdk.algorithm - 算法模块 模块中提供了 twap_table(),可方便的生成一个基于 twap 策略的 time_table 实例。

在执行算法之前,您还可以定制化的调整 time_table 中的具体任务项。

一个完整的 twap 策略示例:

from tqsdk import TqApi, TargetPosScheduler
from tqsdk.algorithm import twap_table

api = TqApi(auth="快期账户,用户密码")
quote = api.get_quote("CZCE.MA109")

# 设置 twap 任务参数,
time_table = twap_table(api, "CZCE.MA105", -100, 600, 1, 5)  # 目标持仓 -100 手,600s 内完成

# 定制化调整 time_table,例如希望第一项任务延迟 10s 再开始下单
# 可以在 time_table 的头部加一行
time_table = pandas.concat([
    DataFrame([[10, 10, None]], columns=['interval', 'target_pos', 'price']),
    time_table
], ignore_index=True)

target_pos_sch = TargetPosScheduler(api, "CZCE.MA105", time_table)
while not target_pos_sch.is_finished():
    api.wait_update()

# 获取 target_pos_sch 实例所有的成交列表
print(target_pos_sch.trades_df)

# 利用成交列表,您可以计算出策略的各种表现指标,例如:
average_trade_price = sum(scheduler.trades_df['price'] * scheduler.trades_df['volume']) / sum(scheduler.trades_df['volume'])
print("成交均价:", average_trade_price)
api.close()