BackTrader 中文文档(二十八)(1)

简介: BackTrader 中文文档(二十八)


原文:www.backtrader.com/

订单管理和执行

原文:www.backtrader.com/blog/posts/2015-08-08-order-creation-execution/order-creation-execution/

回测,因此 backtrader,如果不能模拟订单,将不完整。为此,平台提供了以下功能。

对于订单管理有 3 个原语

  • 购买
  • 卖出
  • 取消

注意

update原语显然是一种逻辑,但常识告诉我们,这种方法主要由使用判断性交易方法的手动操作员使用。

对于订单执行逻辑,以下执行类型:

  • 市价
  • 关闭
  • 限价
  • 停止
  • StopLimit

订单管理

主要目标是易于使用,因此进行订单管理的最直接(和简单)的方法是从策略本身开始。

buyself原语具有以下签名作为Strategy方法:

  • def buy(self, data=None, size=None, price=None, plimit=None, exectype=None, valid=None):
  • def buy(self, data=None, size=None, price=None, exectype=None, valid=None)
  • data -> 数据源引用,用于购买的资产
  • 如果传递None,则策略的主要数据将用作目标
  • size -> 确定要应用的股份的 int/long
  • 如果传递None,则策略中可用的Sizer将被用于自动确定股份。默认的Sizer使用固定状态1
  • price -> 对于Market将被忽略并且可以留空,但对于其他订单类型必须是浮点数。如果留空,则将使用当前收盘价
  • plimit -> 在StopLimit订单中的限价,其中price将被用作触发价格
  • 如果留空,则price将被用作限价(触发和限价相同)
  • exectype -> 订单执行类型之一。如果传递None,则将假定为Market
  • 执行类型在Order中被枚举。例如:Order.Limit
  • valid -> 从 date2num(或数据源)获取的浮点值或 datetime.datetime Python 对象
  • 注意Market订单将在不考虑valid参数的情况下执行
    返回值:一个Order实例
  • def sell(self, data=None, size=None, price=None, exectype=None, valid=None)

因为取消订单只需要buyself返回的order引用,所以经纪人的原语可以使用(见下文)

一些例子:

# buy the main date, with sizer default stake, Market order
order = self.buy()
# Market order - valid will be "IGNORED"
order = self.buy(valid=datetime.datetime.now() + datetime.timedelta(days=3))
# Market order - price will be IGNORED
order = self.buy(price=self.data.close[0] * 1.02)
# Market order - manual stake
order = self.buy(size=25)
# Limit order - want to set the price and can set a validity
order = self.buy(exectype=Order.Limit,
                 price=self.data.close[0] * 1.02,
                 valid=datetime.datetime.now() + datetime.timedelta(days=3)))
# StopLimit order - want to set the price, price limit
order = self.buy(exectype=Order.StopLimit,
                 price=self.data.close[0] * 1.02,
                 plimit=self.data.close[0] * 1.07)
# Canceling an existing order
self.broker.cancel(order)

注意

所有订单类型都可以通过创建Order实例(或其子类之一),然后通过以下方式传递给经纪人:

order = self.broker.submit(order)

注意

broker本身有buysell原语,但对于默认参数要求更严格。

订单执行逻辑

broker使用 2 个主要准则(假设?)进行订单执行。

  • 当前数据已经发生,不能用于执行订单。
    如果策略中的逻辑如下:
if self.data.close > self.sma:  # where sma is a Simple Moving Average
     self.buy()
The expectation CANNOT be that the order will be executed with the
``close`` price which is being examined in the logic BECAUSE it has already
happened.
The order CAN BE 1st EXECUTED withing the bounds of the next set of
Open/High/Low/Close price points (and the conditions set forth herein by
the order)` 
  • 交易量不起作用
    实际上,在真实交易中,如果交易员选择非流动性资产,或者精确地击中了价格条的极值(高/低),订单将被取消。
    但是击中高/低点是个罕见的事件(如果你这么做…你就不需要backtrader了),并且所选择的资产将有足够的流动性来吸收任何常规交易的订单

市场

执行:

下一个一组 Open/High/Low/Close 价格(通常称为bar)的开盘价

理由:

如果逻辑在时间点 X 执行并发出了Market订单,则接下来会发生的价格点是即将到来的open价格

注意

这个订单总是执行,忽略任何用于创建它的pricevalid参数

关闭

执行:

当下一个价格条实际上关闭时,使用下一个价格条的close价格

理由:

大多数回测数据源已经包含了已关闭的价格条,订单将立即执行,使用下一个价格条的close价格。每日数据源是最常见的例子。

但是系统可以被喂入“tick”价格,实际的条(按时间/日期)正在不断地随着新的 ticks 更新,而实际上并没有移动到下一个条(因为时间和/或日期没有改变)

只有当时间或日期改变时,条才会实际上被关闭,订单才会执行

限价

执行:

订单创建时设置的price,如果data触及它,则从下一个价格条开始。

如果设置了valid并且到达了时间点,订单将被取消

价格匹配:

backtrader试图为Limit订单提供最真实的执行价格

使用 4 个价格点(Open/High/Low/Close),可以部分推断请求的price是否可以改善。

对于Buy订单

- Case 1:
  If the `open` price of the bar is below the limit price the order
  executes immediately with the `open` price. The order has been swept
  during the opening phase of the session
- Case 2:
  If the `open` price has not penetrated below the limit price but the
  `low` price is below the limit price, then the limit price has been
  seen during the session and the order can be executed

对于Sell订单,逻辑显然是相反的。

止损

执行:

订单创建时设置的触发器price,如果data触及它,则从下一个价格条开始。

如果设置了valid并且到达了时间点,订单将被取消

价格匹配:

backtrader试图为Stop订单提供最真实的触发价格

使用 4 个价格点(Open/High/Low/Close),可以部分推断请求的price是否可以改善。

对于\Stoporders whichBuy`

- Case 1:
  If the `open` price of the bar is above the stop price the order is
  executed immediately with the `open` price.
  Intended to stop a loss if the price is moving upwards against an
  existing short position
- Case 2:
  If the `open` price has not penetrated above the stop price but the
  `high` price is above the stop price, then the stop price has been
  seen during the session and the order can be executed

对于Sell订单,逻辑显然是相反的。

止损限价

执行:

触发器price设置了订单的启动,从下一个价格条开始。

价格匹配:

  • 触发器:使用Stop匹配逻辑(但仅触发并将订单转换为Limit订单)
  • 限制:使用Limit价格匹配逻辑

一些样本

像往常一样,图片(带代码)价值数百万长的解释。请注意,代码片段集中在订单创建部分。完整代码在底部。

一个价格高于/低于简单移动平均线策略将用于生成买入/卖出信号

信号在图表底部可见:使用交叉指标的CrossOver

仅保留对生成的“买入”订单的引用,以允许系统中最多只有一个同时订单。

执行类型:市价

请在图表中查看订单如何在生成信号后一根棒棒后以开盘价执行。

if self.p.exectype == 'Market':
                self.buy(exectype=bt.Order.Market)  # default if not given
                self.log('BUY CREATE, exectype Market, price %.2f' %
                         self.data.close[0])

输出图表。

命令行和输出:

$ ./order-execution-samples.py --exectype Market
2006-01-26T23:59:59+00:00, BUY CREATE, exectype Market, price 3641.42
2006-01-26T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59+00:00, BUY EXECUTED, Price: 3643.35, Cost: 3643.35, Comm 0.00
2006-03-02T23:59:59+00:00, SELL CREATE, 3763.73
2006-03-02T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59+00:00, SELL EXECUTED, Price: 3763.95, Cost: 3763.95, Comm 0.00
...
...
2006-12-11T23:59:59+00:00, BUY CREATE, exectype Market, price 4052.89
2006-12-11T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-12-12T23:59:59+00:00, BUY EXECUTED, Price: 4052.55, Cost: 4052.55, Comm 0.00

执行类型:收盘

注意

Issue#11之后,创建了一个开发分支,更新了图表和输出。错误的收盘价格被使用。

现在订单也是在信号后一根棒棒后执行,但是使用的是收盘价。

elif self.p.exectype == 'Close':
                self.buy(exectype=bt.Order.Close)
                self.log('BUY CREATE, exectype Close, price %.2f' %
                         self.data.close[0])

输出图表。

命令行和输出:

$ ./order-execution-samples.py --exectype Close
2006-01-26T23:59:59+00:00, BUY CREATE, exectype Close, price 3641.42
2006-01-26T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59+00:00, BUY EXECUTED, Price: 3685.48, Cost: 3685.48, Comm 0.00
2006-03-02T23:59:59+00:00, SELL CREATE, 3763.73
2006-03-02T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59+00:00, SELL EXECUTED, Price: 3763.95, Cost: 3763.95, Comm 0.00
...
...
2006-11-06T23:59:59+00:00, BUY CREATE, exectype Close, price 4045.22
2006-11-06T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-07T23:59:59+00:00, BUY EXECUTED, Price: 4072.86, Cost: 4072.86, Comm 0.00
2006-11-24T23:59:59+00:00, SELL CREATE, 4048.16
2006-11-24T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-27T23:59:59+00:00, SELL EXECUTED, Price: 4045.05, Cost: 4045.05, Comm 0.00
2006-12-11T23:59:59+00:00, BUY CREATE, exectype Close, price 4052.89
2006-12-11T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-12-12T23:59:59+00:00, BUY EXECUTED, Price: 4059.74, Cost: 4059.74, Comm 0.00

执行类型:限价

在几行之前计算有效性以防已作为参数传递。

if self.p.valid:
                valid = self.data.datetime.date(0) + \
                        datetime.timedelta(days=self.p.valid)
            else:
                valid = None

设置了信号生成价格(信号条的收盘价)下跌 1%的限价。请注意,这阻止了上面许多订单的执行。

elif self.p.exectype == 'Limit':
                price = self.data.close * (1.0 - self.p.perc1 / 100.0)
                self.buy(exectype=bt.Order.Limit, price=price, valid=valid)
                if self.p.valid:
                    txt = 'BUY CREATE, exectype Limit, price %.2f, valid: %s'
                    self.log(txt % (price, valid.strftime('%Y-%m-%d')))
                else:
                    txt = 'BUY CREATE, exectype Limit, price %.2f'
                    self.log(txt % price)

输出图表。

仅发布了 4 个订单。尝试捕捉小幅度下跌的价格完全改变了输出。

命令行和输出:

$ ./order-execution-samples.py --exectype Limit --perc1 1
2006-01-26T23:59:59+00:00, BUY CREATE, exectype Limit, price 3605.01
2006-01-26T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-05-18T23:59:59+00:00, BUY EXECUTED, Price: 3605.01, Cost: 3605.01, Comm 0.00
2006-06-05T23:59:59+00:00, SELL CREATE, 3604.33
2006-06-05T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-06-06T23:59:59+00:00, SELL EXECUTED, Price: 3598.58, Cost: 3598.58, Comm 0.00
2006-06-21T23:59:59+00:00, BUY CREATE, exectype Limit, price 3491.57
2006-06-21T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-06-28T23:59:59+00:00, BUY EXECUTED, Price: 3491.57, Cost: 3491.57, Comm 0.00
2006-07-13T23:59:59+00:00, SELL CREATE, 3562.56
2006-07-13T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-07-14T23:59:59+00:00, SELL EXECUTED, Price: 3545.92, Cost: 3545.92, Comm 0.00
2006-07-24T23:59:59+00:00, BUY CREATE, exectype Limit, price 3596.60
2006-07-24T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED

执行类型:限价与有效期

为了不会永远等待一个限价订单,该订单仅在 4(日历)天内有效,该订单可能只有在价格对“买入”订单不利时才执行。

输出图表。

更多订单已生成,但除了一个“买入”订单过期外,其他所有订单都过期了,进一步限制了操作数量。

命令行和输出:

$ ./order-execution-samples.py --exectype Limit --perc1 1 --valid 4
2006-01-26T23:59:59+00:00, BUY CREATE, exectype Limit, price 3605.01, valid: 2006-01-30
2006-01-26T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-01-30T23:59:59+00:00, BUY EXPIRED
2006-03-10T23:59:59+00:00, BUY CREATE, exectype Limit, price 3760.48, valid: 2006-03-14
2006-03-10T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-14T23:59:59+00:00, BUY EXPIRED
2006-03-30T23:59:59+00:00, BUY CREATE, exectype Limit, price 3835.86, valid: 2006-04-03
2006-03-30T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-04-03T23:59:59+00:00, BUY EXPIRED
2006-04-20T23:59:59+00:00, BUY CREATE, exectype Limit, price 3821.40, valid: 2006-04-24
2006-04-20T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-04-24T23:59:59+00:00, BUY EXPIRED
2006-05-04T23:59:59+00:00, BUY CREATE, exectype Limit, price 3804.65, valid: 2006-05-08
2006-05-04T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-05-08T23:59:59+00:00, BUY EXPIRED
2006-06-01T23:59:59+00:00, BUY CREATE, exectype Limit, price 3611.85, valid: 2006-06-05
2006-06-01T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-06-05T23:59:59+00:00, BUY EXPIRED
2006-06-21T23:59:59+00:00, BUY CREATE, exectype Limit, price 3491.57, valid: 2006-06-25
2006-06-21T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-06-26T23:59:59+00:00, BUY EXPIRED
2006-07-24T23:59:59+00:00, BUY CREATE, exectype Limit, price 3596.60, valid: 2006-07-28
2006-07-24T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-07-28T23:59:59+00:00, BUY EXPIRED
2006-09-12T23:59:59+00:00, BUY CREATE, exectype Limit, price 3751.07, valid: 2006-09-16
2006-09-12T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-09-18T23:59:59+00:00, BUY EXPIRED
2006-09-20T23:59:59+00:00, BUY CREATE, exectype Limit, price 3802.90, valid: 2006-09-24
2006-09-20T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-09-22T23:59:59+00:00, BUY EXECUTED, Price: 3802.90, Cost: 3802.90, Comm 0.00
2006-11-02T23:59:59+00:00, SELL CREATE, 3974.62
2006-11-02T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-03T23:59:59+00:00, SELL EXECUTED, Price: 3979.73, Cost: 3979.73, Comm 0.00
2006-11-06T23:59:59+00:00, BUY CREATE, exectype Limit, price 4004.77, valid: 2006-11-10
2006-11-06T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-10T23:59:59+00:00, BUY EXPIRED
2006-12-11T23:59:59+00:00, BUY CREATE, exectype Limit, price 4012.36, valid: 2006-12-15
2006-12-11T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-12-15T23:59:59+00:00, BUY EXPIRED

执行类型:止损

设置了信号价格上涨 1%的止损价。这意味着策略仅在生成信号并价格继续上涨时购买,这可以被解释为强势信号。

这完全改变了执行情况。

elif self.p.exectype == 'Stop':
                price = self.data.close * (1.0 + self.p.perc1 / 100.0)
                self.buy(exectype=bt.Order.Stop, price=price, valid=valid)
                if self.p.valid:
                    txt = 'BUY CREATE, exectype Stop, price %.2f, valid: %s'
                    self.log(txt % (price, valid.strftime('%Y-%m-%d')))
                else:
                    txt = 'BUY CREATE, exectype Stop, price %.2f'
                    self.log(txt % price)

输出图表。

命令行和输出:

$ ./order-execution-samples.py --exectype Stop --perc1 1
2006-01-26T23:59:59+00:00, BUY CREATE, exectype Stop, price 3677.83
2006-01-26T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59+00:00, BUY EXECUTED, Price: 3677.83, Cost: 3677.83, Comm 0.00
2006-03-02T23:59:59+00:00, SELL CREATE, 3763.73
2006-03-02T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59+00:00, SELL EXECUTED, Price: 3763.95, Cost: 3763.95, Comm 0.00
2006-03-10T23:59:59+00:00, BUY CREATE, exectype Stop, price 3836.44
2006-03-10T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-15T23:59:59+00:00, BUY EXECUTED, Price: 3836.44, Cost: 3836.44, Comm 0.00
2006-03-28T23:59:59+00:00, SELL CREATE, 3811.45
2006-03-28T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-03-29T23:59:59+00:00, SELL EXECUTED, Price: 3811.85, Cost: 3811.85, Comm 0.00
2006-03-30T23:59:59+00:00, BUY CREATE, exectype Stop, price 3913.36
2006-03-30T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-09-29T23:59:59+00:00, BUY EXECUTED, Price: 3913.36, Cost: 3913.36, Comm 0.00
2006-11-02T23:59:59+00:00, SELL CREATE, 3974.62
2006-11-02T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-03T23:59:59+00:00, SELL EXECUTED, Price: 3979.73, Cost: 3979.73, Comm 0.00
2006-11-06T23:59:59+00:00, BUY CREATE, exectype Stop, price 4085.67
2006-11-06T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-13T23:59:59+00:00, BUY EXECUTED, Price: 4085.67, Cost: 4085.67, Comm 0.00
2006-11-24T23:59:59+00:00, SELL CREATE, 4048.16
2006-11-24T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-11-27T23:59:59+00:00, SELL EXECUTED, Price: 4045.05, Cost: 4045.05, Comm 0.00
2006-12-11T23:59:59+00:00, BUY CREATE, exectype Stop, price 4093.42
2006-12-11T23:59:59+00:00, ORDER ACCEPTED/SUBMITTED
2006-12-13T23:59:59+00:00, BUY EXECUTED, Price: 4093.42, Cost: 4093.42, Comm 0.00


BackTrader 中文文档(二十八)(2)https://developer.aliyun.com/article/1505487

相关文章
|
5天前
BackTrader 中文文档(二十八)(2)
BackTrader 中文文档(二十八)
11 0
|
5天前
|
测试技术 C语言 Python
BackTrader 中文文档(二十八)(4)
BackTrader 中文文档(二十八)
14 0
|
5天前
|
存储 算法 C++
BackTrader 中文文档(二十八)(3)
BackTrader 中文文档(二十八)
11 0
|
5天前
BackTrader 中文文档(二十九)(3)
BackTrader 中文文档(二十九)
10 0
|
5天前
BackTrader 中文文档(二十九)(2)
BackTrader 中文文档(二十九)
11 0
|
5天前
|
算法 索引
BackTrader 中文文档(二十九)(1)
BackTrader 中文文档(二十九)
11 0
|
5天前
|
存储 API
BackTrader 中文文档(二十九)(4)
BackTrader 中文文档(二十九)
14 0
|
5天前
|
算法 索引 Python
BackTrader 中文文档(二十七)(2)
BackTrader 中文文档(二十七)
15 0
|
5天前
BackTrader 中文文档(二十七)(1)
BackTrader 中文文档(二十七)
10 0
|
5天前
|
存储 数据库连接 数据库
BackTrader 中文文档(二十七)(4)
BackTrader 中文文档(二十七)
10 0