一、跟量下单算法详解
在算法交易的各种策略中,按执行行为对市场的主动程度,可以将其划分为三类:被动型算法交易、主动型算法交易以及综合型算法交易。其中,跟量下单(Percentage of Volume, 简称 POV)策略被归类为主动型算法交易方法。它通过监测市场成交量的实时变化,动态调整下单节奏,是一种将执行行为与市场活跃度紧密挂钩的策略。
跟量下单(POV)算法的核心思想是:按照市场成交量的一定比例来执行订单。交易者预先设定一个跟量比例(如 10%),系统在运行过程中持续获取市场成交量的最新数据,并据此计算当前应执行的交易手数。例如,当某一时间段内市场成交量新增了 500 手,设定的比例为 10%,那么策略此阶段应成交 50 手。这种机制可以使策略在市场流动性高时自动加快交易速度,而在流动性较低时放慢执行节奏,从而降低市场冲击和滑点风险。
POV 策略的优势较为明显,它能够根据市场的流动性自动调节交易节奏,在流动性充足时迅速完成交易,提升效率;而在市场冷清时则主动减速,降低对盘口的冲击。这种'顺势而为'的执行逻辑,使交易行为更加自然,有效提升了执行的隐蔽性和整体质量。但 POV 策略也存在一定的局限性。首先,它强依赖市场成交量,在成交量骤降或出现价格急变时,可能会错失最佳交易时机,导致未能及时建仓或平仓。其次,由于严格受限于市场成交量占比,当市场情绪剧烈波动或临近收盘时,其被动性可能导致交易不完全或执行滞后。此外,POV 策略的执行路径容易被高频交易者捕捉,在极端市场中存在被'跟单'或'反向打击'的风险,从而降低策略的隐蔽性和执行效率。
二、环境准备
- 环境准备
- 安装 Python 环境(推荐 Python 3.6 或以上版本)
- 安装量化库:pip install tqsdk
- 注册账户获取访问密钥
- 数据准备
- 订阅近月与远月合约行情
- 获取历史 K 线或者 Tick 数据(用于分析与行情推进)
- 策略编写
- 设计信号生成逻辑
- 编写交易执行模块(开仓、平仓逻辑)
- 实现风险控制措施(止损、资金管理)
三、代码实现
本策略基于 Python 开发,使用量化接口进行编写。该策略的设计目标是在市场成交量波动的基础上,精细控制下单节奏与手数,从而在控制市场冲击的前提下完成指定规模的成交任务。
从策略设计角度来看,核心在于如何'以量定速',即通过追踪市场成交量的变化动态调整订单执行频率。为实现这一点,系统需持续采集并比较市场的累计成交量变化,计算新增成交量,并将其乘以预设的比例系数得到应执行的交易手数。随后根据剩余目标手数进行约束,防止过量提交订单。考虑到不同市场条件下的订单需求与滑点控制,本策略允许用户选择'对价'或'挂价'两种报单方式,以适应不同的流动性环境。
策略在整个执行过程中保持一个清晰的状态更新机制:每轮订单提交后,系统等待其成交完成,再更新成交基准量,并进入下一轮判断与执行。该过程既保证了成交控制的准确性,也为后续扩展提供了良好的结构基础。
该策略的实现可分为以下四个步骤:
- 设定策略初始参数,包括交易合约代码、方向(买入/卖出)、目标交易总手数、跟量比例,以及报单方式等。
- 初始化变量并读取当前市场累计成交量作为基准值,同时设置已成交手数为零,用于后续累计与判断。
- 在策略主循环中,实时监控市场成交量的变化,计算成交量的增量部分,并按设定比例计算应挂出的订单手数;随后根据报单类型选择合适价格提交限价单,并等待订单成交。
- 每轮交易完成后更新成交基准和累计成交量,循环执行,直到完成全部目标手数为止。
核心代码
#!/usr/bin/env python # coding=utf-8
from tqsdk import TqApi, TqAuth, TqKq
import math
# === 用户参数 ===
SYMBOL = "SHFE.ag2506" # 交易合约
DIRECTION = "BUY" # "BUY"为买入,"SELL"为卖出
OFFSET = "OPEN"
TOTAL_VOLUME =
POV_RATIO =
ORDER_TYPE =
acc = TqKq()
api = TqApi(account=acc, auth=TqAuth(, ))
quote = api.get_quote(SYMBOL)
base_volume = quote.volume
traded_volume =
last_printed_volume =
()
:
traded_volume < TOTAL_VOLUME:
api.wait_update()
new_volume = quote.volume
delta = new_volume - base_volume
order_volume = (math.floor(delta * POV_RATIO))
order_volume = (order_volume, TOTAL_VOLUME - traded_volume)
order_volume > :
()
()
()
ORDER_TYPE == :
price = quote.ask_price1 DIRECTION == quote.bid_price1
:
price = quote.bid_price1 DIRECTION == quote.ask_price1
order = api.insert_order(
symbol=SYMBOL,
direction=DIRECTION,
offset=OFFSET,
volume=order_volume,
limit_price=price
)
()
last_status = order.status
last_volume_left = order.volume_left
order.status == :
api.wait_update()
order.status != last_status order.volume_left != last_volume_left:
()
last_status = order.status
last_volume_left = order.volume_left
order.is_error:
()
actual_trade = order.volume_orign - order.volume_left
actual_trade > :
()
traded_volume += actual_trade
base_volume = new_volume
traded_volume > last_printed_volume:
()
last_printed_volume = traded_volume
:
()
Exception e:
()
:
api.close()


