滑点#

回测无法保证真实的市场条件。无论市场模拟得有多好,在真实的市场条件下都可能发生滑点。这意味着:

  • 请求的价格可能无法匹配。

集成的回测经纪人支持滑点。以下参数可以传递给经纪人:

  • 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个操作未能执行。

示例应该说明了不同*滑点*选项是如何一起工作的。 ```