滑点#
回测无法保证真实的市场条件。无论市场模拟得有多好,在真实的市场条件下都可能发生滑点。这意味着:
请求的价格可能无法匹配。
集成的回测经纪人支持滑点。以下参数可以传递给经纪人:
slip_perc
(默认值:0.0
)以绝对值表示的百分比(正值),用于在买入/卖出订单中上下滑动价格注意:
0.01
表示1%
0.001
表示0.1%
slip_fixed
(默认值:0.0
)以单位表示的百分比(正值),用于在买入/卖出订单中上下滑动价格注意:如果
slip_perc
不为零,则优先使用它。- slip_open (默认值为 False ):是否在订单执行时滑动价格,以便特别使用下一个柱状图的 开盘价 。一个示例是市价订单,它会以下一个可用的tick执行,即柱状图的开盘价。对于其他一些执行方式,也适用此逻辑,因为它试图检测是否在进入新的柱状图时 开盘价 会与请求的价格/执行类型匹配。
slip_match (默认值为 True ):
如果为 True ,则经纪人将通过将滑点限制在 high/low 价格范围内来提供匹配,以防超出滑点。
如果为 False ,经纪人将不会与当前价格匹配订单,并将尝试在下一次迭代中执行。
slip_limit (默认值为 True )
对于给定的精确匹配价格的 Limit 订单,即使 slip_match 为`False`,也会进行匹配。
此选项控制该行为。
如果为 True ,则 Limit 订单将通过将价格限制为 limit / high/low 价格来匹配。
如果为 False ,并且滑点超过了限制,那么将没有匹配。-
slip_out
(默认值:“False”)即使价格超出“high”-“low”范围,也提供*滑点*。
工作原理#
为了决定何时应用*滑点*,考虑了订单执行类型:
Close
- 不应用 滑点此订单与“close”价格匹配,该价格是当天的最后一个价格。滑点不会发生,因为订单只能在会话的最后一个刻度发生,这是一个独特的价格,没有公差。
Market
- 应用*滑点*请检查
slip_open
异常。因为“市价”订单将与下一个柱的*开盘*价格匹配。
Limit
- 按照以下逻辑应用*滑点*
如果匹配价格是 开盘*价格,则根据参数 ``slip_open`` 应用 滑点 。如果应用滑点,则价格永远不会比请求的“limit”价格更差。- 如果匹配价格不是“限价”价格,则会应用 滑点*,限制在“高/低”范围内。在这种情况下,
slip_mlimit
决定是否会发生匹配,如果超过了限制。
如果匹配价格是“限价”价格,则不应用滑点。
停止单
- 一旦订单被*触发*,与“市价”订单相同的逻辑适用。停限单
- 一旦订单被*触发*,与“限价”订单相同的逻辑适用。
这种方法尽可能在模拟和可用数据的界限内提供最逼真的方法。
配置滑点#
每次运行时, cerebro 引擎会为每个运行实例化一个 broker ,并使用默认参数。有两种方法可以更改行为:
使用方法来配置滑点
将经纪人替换为以下内容:
import backtrader as bt
cerebro = bt.Cerebro() cerebro.broker = bt.brokers.BackBroker(slip_perc=0.005) # 0.5%
实际示例 *** ** ** **
源代码包含了一个使用订单执行类型 Market
和使用 信号*的 多头/空头*方法的示例。这可以帮助理解逻辑。
使用无滑点的运行和初始图表供以后参考:
$ ./slippage.py --plot
01 2005-03-22 23:59:59 卖出 数量: -1 / 价格: 3040.55
02 2005-04-11 23:59:59 买入 数量: +1 / 价格: 3088.47
03 2005-04-11 23:59:59 买入 数量: +1 / 价格: 3088.47
04 2005-04-19 23:59:59 卖出 数量: -1 / 价格: 2948.38
05 2005-04-19 23:59:59 卖出 数量: -1 / 价格: 2948.38
06 2005-05-19 23:59:59 买入 数量: +1 / 价格: 3034.88
...
35 2006-12-19 23:59:59 买入 数量: +1 / 价格: 4121.01
- 使用配置为
1.5%
的*滑点*进行相同的运行: $ ./slippage.py –slip_perc 0.015 –slip_open –slip_out 01 2005-03-22 23:59:59 SELL Size: -1 / Price: 3021.66 02 2005-04-11 23:59:59 BUY Size: +1 / Price: 3088.47 03 2005-04-11 23:59:59 BUY Size: +1 / Price: 3088.47 04 2005-04-19 23:59:59 SELL Size: -1 / Price: 2948.38 05 2005-04-19 23:59:59 SELL Size: -1 / Price: 2948.38 06 2005-05-19 23:59:59 BUY Size: +1 / Price: 3055.14 … 35 2006-12-19 23:59:59 BUY Size: +1 / Price: 4121.01
在这种情况下,我们可以立即看到价格已经 发生变动 。而且分配的价格与第35次操作的最低或相同。 这不是粘贴错误
在2006-12-19的开盘和最高价是相同的。
价格不能被推高到超过最高价,因为这意味着返回一个不存在的价格。
当然,如果希望,在 backtrader 中可以打破最高价和最低价范围外匹配,只需激活 slip_out
。对其进行激活的运行:```
$ ./slippage.py –slip_perc 0.015 –slip_open –slip_out
01 2005-03-22 23:59:59 卖出数量:-1 / 价格:2994.94
02 2005-04-11 23:59:59 买入数量:+1 / 价格:3134.80
03 2005-04-11 23:59:59 买入数量:+1 / 价格:3134.80
04 2005-04-19 23:59:59 卖出数量:-1 / 价格:2904.15
05 2005-04-19 23:59:59 卖出数量:-1 / 价格:2904.15
06 2005-05-19 23:59:59 买入数量:+1 / 价格:3080.40
…
35 2006-12-19 23:59:59 买入数量:+1 / 价格:4182.83
匹配成功的价格表达式为:天哪!价格明显偏离了范围。足够看到第35次操作,它被匹配到 4182.83
。快速检查本文档中的图表可知,资产从未接近到那个价格。
slip_match
的默认值是 True
,这意味着 backtrader 提供了一个匹配,无论是有上限还是无上限的价格,如上所示。让我们禁用它:
$ ./slippage.py –slip_perc 0.015 –slip_open –no-slip_match 01 2005-04-15 23:59:59 卖出数量:-1 / 价格:3028.10 02 2005-05-18 23:59:59 买入数量:+1 / 价格:3029.40 03 2005-06-01 23:59:59 买入数量:+1 / 价格:3124.03 04 2005-10-06 23:59:59 卖出数量:-1 / 价格:3365.57 05 2005-10-06 23:59:59 卖出数量:-1 / 价格:3365.57 06 2005-12-01 23:59:59 买入数量:+1 / 价格:3499.95 07 2005-12-01 23:59:59 买入数量:+1 / 价格:3499.95 08 2006-02-28 23:59:59 卖出数量:-1 / 价格:3782.71 09 2006-02-28 23:59:59 卖出数量:-1 / 价格:3782.71 10 2006-05-23 23:59:59 买入数量:+1 / 价格:3594.68 11 2006-05-23 23:59:59 买入数量:+1 / 价格:3594.68 12 2006-11-27 23:59:59 卖出数量:-1 / 价格:3984.37 13 2006-11-27 23:59:59 卖出数量:-1 / 价格:3984.37
千万火箭!从35变为13。原因是:
禁用 slip_match
将不允许在 滑点*会将匹配价格推高到柱状图的 ``高`` 或推低到 ``低`` 的情况下进行匹配操作。似乎使用请求的 滑点* 1.5%
,有大约22个操作未能执行。