Backtrader 文档学习-Order Management and Execution

Backtrader 文档学习-Order Management and Execution

本章提供了关于order的详细功能测试用例,很好很重要。

最后的示例部分,详细分析总结了不同参数的效果和输出。

如果不能模拟订单交易回测就不会完整。为此,平台中提供了以下功能, 对于订单管理3个基本要素:

  • buy
  • sell
  • cancel
    对order执行逻辑,有以下类型:
  • Market
  • Close
  • Limit
  • Stop
  • StopLimit

1.Order Management

# buy the main data, with sizer default stake, Market order
# 使用默认data ,默认购买数量,市价订单
order = self.buy()

# Market order - valid will be "IGNORED"
# 有效截止日期到当前时间3天后
order = self.buy(valid=datetime.datetime.now() + datetime.timedelta(days=3))

# Market order - price will be IGNORED
# 成交价格用收盘价的+2%
order = self.buy(price=self.data.close[0] * 1.02)

# Market order - manual stake
# 市价单,25股
order = self.buy(size=25)

# Limit order - want to set the price and can set a validity
# 执行类型,限价执行,+2%的收盘价,当前三天内有效
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
# 限价单模式,+2%成交价收盘价,+7%成交价收盘价,止损(盈)
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 = self.broker.submit(order)

2.Order Execution Logic

当前数据已经发生,不能用于执行订单。 如果策略中的逻辑是:

 if self.data.close > self.sma:  # where sma is a Simple Moving Average
     self.buy()

策略中用收盘价检查是否触发buy,不能期望订单用策略中正在检查的收盘价执行,因为收盘价已经发生了。
策略条件设置,订单可以在下一组开盘/高/低/收盘价格点(以及订单在此规定的条件)的范围内触发执行 。修改为,用前一天的收盘价做策略,则可以触发buy 。

 if self.data.close[-1] > self.sma:  # where sma is a Simple Moving Average
     self.buy()
  • 成交量不起作用
    在实际交易中,如果交易者买入非流动性资产,或者恰好触及价格的极限(高/低),就会出现这种情况。(不明白 ??)

但触及高点/低点的情况很少发生(如果你做了……你就不需要BT),所选资产将有足够的流动性来吸收任何常规交易的订单 。(还是不明白 ??)

3.Market

执行:
下一组开盘/高/低/收盘价的开盘价(通常称为bar)
逻辑:
如果逻辑已经在时间点X执行并发布了市价单,将发生的下一个价格点就是即下一个bar的开盘价 。
说明:
该订单始终执行,不考虑用于创建该订单的price和valid 参数

4.Close

执行:
在下一bar平仓时 ,使用下一bar实际收盘价执行。

逻辑:
大多数回测加载数据包含已经收盘bar,订单将立即以下一bar收盘价执行。每日数据加载是最常见的示例。

但是系统可以加载“tick”价格,并且实际bar(时间/日期方面)会随着新tick成交点不断更新,不会实际移动到下一个bar(因为时间和/或日期没有改变,同一天内)。
意思是支持加载类似5分钟线,15分钟线,以tick可以触发买点。

只有当时间或日期改变时,bar才能实际上平仓,订单才会执行 。

5.Limit

  • 执行:
    如果数据触及订单创建时设置的价格,则下一个价格bar开始执行订单。
    如果设置了valid条件,达到有效时间点,订单将被取消

  • 价格匹配:
    BT尝试为限价单提供最现实的执行价格Limit。
    使用4个价格点(开盘/高/低/收盘)可以部分推断出请求的价格是否可以提高。

  • 对于买订单:

    • 场景1:
      如果bar开盘价低于限价订单将立即以开盘价执行。订单将在会话的开始阶段清除。

    • 场景 2:
      如果开盘价没有跌破限价,但最低价低于限价,则在交易期间达到限价,订单可以执行 。

卖单的逻辑显然是颠倒的。

6.Stop

  • 执行:
    数据触及订单时设置的触发价格,从下一个bar的价格开始。
    如果设置了valid并且达到了时间点,订单将被取消
  • 价格匹配:
    BT尝试为止损单提供最现实的触发价格。
    使用4个价格点(开盘/高/低/收盘)可以部分推断出请求的价格是否可以提高。

For Stop orders which Buy

场景 1:
如果bar开盘价高于止损价,订单将立即以开盘价执行。
目的是在价格相对于现有空头头寸向上移动时止损。做空止损

场景 2:
如果开盘价未突破止损价,但最高价高于止损价,则在交易过程中触发止损,订单执行 。
止损订单的逻辑与Sell相反。

7.StopLimit

  • 执行:
    触发价格从下一个bar价格开始设置订单。

  • 价格匹配:
    触发:使用- 止损匹配逻辑(但仅触发并将订单转换为限价订单)

  • Limit: 使用限价匹配逻辑 。

8.示例

信号出现:使用CrossOver 交叉指标的交叉。
对生成的buy订单调用被保留,在系统中最多只允许一个订单执行。

(1)Execution Type: Market
            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])
<1>图示

在这里插入图片描述

<2>输出
python ./order-execution-samples.py --exectype Market
2006-01-26T23:59:59.999989, BUY CREATE, exectype Market, price 3641.42
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3643.35, Cost: 3643.35, Comm 0.00
2006-03-02T23:59:59.999989, SELL CREATE, 3763.73
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59.999989, SELL EXECUTED, Price: 3763.95, Cost: 3643.35, Comm 0.00
<3>说明
  • notify_order() 检查状态:ORDER ACCEPTED/SUBMITTED ,BUY EXPIRED ,BUY EXECUTED ,SELL EXECUTED ,打印输出
  • next() 执行买卖操作
  • 2006-01-26T23:59:59.999989, BUY CREATE, exectype Market, price 3641.42 ,next触发
  • 2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED ,notify_order触发,是两个状态,第一次是提交,第二次是接收,所以有两条记录。
  • 2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3643.35, Cost: 3643.35, Comm 0.00 ,next触发,以27日的open价格成交买入。
  • 卖出的效果一下
(2)Execution Type: Close
            elif self.p.exectype == 'Close':
                self.buy(exectype=bt.Order.Close)

                self.log('BUY CREATE, exectype Close, price %.2f' %
                         self.data.close[0])
<1> 图示

在这里插入图片描述

<2> 输出
python ./order-execution-samples.py --exectype Close
2006-01-26T23:59:59.999989, BUY CREATE, exectype Close, price 3641.42
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3685.48, Cost: 3685.48, Comm 0.00
2006-03-02T23:59:59.999989, SELL CREATE, 3763.73
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59.999989, SELL EXECUTED, Price: 3763.95, Cost: 3685.48, Comm 0.00
<3>说明
  • 2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3685.48, Cost: 3685.48, Comm 0.00 ,执行类型是close ,买入的时候以收盘价买入,1月27日的收盘价。
  • 2006-03-03T23:59:59.999989, SELL EXECUTED, Price: 3763.95, Cost: 3685.48, Comm 0.00 ,卖出的时候,没有指定类型,sell()都没指定参数,默认是Market ,所以还是以3月3日的开票价卖出。
  • bt.Order.Close 执行模式,是要求以收盘价成交!!
  • 如果做复杂统一点,可以把sell()也加上相应的参数,与buy一直。
(3)Execution Type: Limit

有效性参数传递设置

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

设置低于信号生成价格1%的限价(bar的收盘价)。请注意这是如何阻止上面的许多订单被执行的。

            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)
<1> 图示

在这里插入图片描述

<2> 输出
python ./order-execution-samples.py --exectype Limit --perc1 1
2006-01-26T23:59:59.999989, BUY CREATE, exectype Limit, price 3605.01
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-05-18T23:59:59.999989, BUY EXECUTED, Price: 3605.01, Cost: 3605.01, Comm 0.00
2006-06-05T23:59:59.999989, SELL CREATE, 3604.33
2006-06-05T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-05T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-06T23:59:59.999989, SELL EXECUTED, Price: 3598.58, Cost: 3605.01, Comm 0.00
2006-06-21T23:59:59.999989, BUY CREATE, exectype Limit, price 3491.57
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-28T23:59:59.999989, BUY EXECUTED, Price: 3491.57, Cost: 3491.57, Comm 0.00
2006-07-13T23:59:59.999989, SELL CREATE, 3562.56
2006-07-13T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-13T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-14T23:59:59.999989, SELL EXECUTED, Price: 3545.92, Cost: 3491.57, Comm 0.00
2006-07-24T23:59:59.999989, BUY CREATE, exectype Limit, price 3596.60
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
<3>说明
  • 2006-01-26T23:59:59.999989, BUY CREATE, exectype Limit, price 3605.01,next创建了买单,因为是限价单,用1月26日的收盘价,3641.42 * (100 - 1)/100 = 3605.0058 = 3605.01 。即挂单是低于触发时的收盘价-1% 作为限价
  • 因为没有valid ,所以一直挂单到5月18日
  • 2006-05-18T23:59:59.999989, BUY EXECUTED, Price: 3605.01, Cost: 3605.01, Comm 0.00 ,5月18日的价格区间包括3605.01 ,所以能够成交买单,不用OLHC的价格,使用限价价格成交。

2006-5-18 3607.41 3649.54 3558.27 3606.33

  • 2006-06-06T23:59:59.999989, SELL EXECUTED, Price: 3598.58, Cost: 3605.01, Comm 0.00 ,卖单触发后,因为没有限价参数,所以都是以开盘价成交。
(4)Execution Type: Limit with validity

为了不永远等待限价单(限价单可能仅在价格与buy订单相反执行),该订单的有效期仅为4天(日历)。

<1>图示

在这里插入图片描述

<2>输出
python ./order-execution-samples.py --exectype Limit --perc1 1 --valid 4
2006-01-26T23:59:59.999989, BUY CREATE, exectype Limit, price 3605.01, valid: 2006-01-30
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-30T23:59:59.999989, BUY EXPIRED
2006-03-10T23:59:59.999989, BUY CREATE, exectype Limit, price 3760.48, valid: 2006-03-14
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-14T23:59:59.999989, BUY EXPIRED
2006-03-30T23:59:59.999989, BUY CREATE, exectype Limit, price 3835.86, valid: 2006-04-03
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-04-03T23:59:59.999989, BUY EXPIRED
2006-04-20T23:59:59.999989, BUY CREATE, exectype Limit, price 3821.40, valid: 2006-04-24
2006-04-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-04-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-04-24T23:59:59.999989, BUY EXPIRED
2006-05-04T23:59:59.999989, BUY CREATE, exectype Limit, price 3804.65, valid: 2006-05-08
2006-05-04T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-05-04T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-05-08T23:59:59.999989, BUY EXPIRED
2006-06-01T23:59:59.999989, BUY CREATE, exectype Limit, price 3611.85, valid: 2006-06-05
2006-06-01T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-01T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-05T23:59:59.999989, BUY EXPIRED
2006-06-21T23:59:59.999989, BUY CREATE, exectype Limit, price 3491.57, valid: 2006-06-25
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-26T23:59:59.999989, BUY EXPIRED
2006-07-24T23:59:59.999989, BUY CREATE, exectype Limit, price 3596.60, valid: 2006-07-28
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-28T23:59:59.999989, BUY EXPIRED
2006-09-12T23:59:59.999989, BUY CREATE, exectype Limit, price 3751.07, valid: 2006-09-16
2006-09-12T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-12T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-18T23:59:59.999989, BUY EXPIRED
2006-09-20T23:59:59.999989, BUY CREATE, exectype Limit, price 3802.90, valid: 2006-09-24
2006-09-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-22T23:59:59.999989, BUY EXECUTED, Price: 3802.90, Cost: 3802.90, Comm 0.00
2006-11-02T23:59:59.999989, SELL CREATE, 3974.62
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-03T23:59:59.999989, SELL EXECUTED, Price: 3979.73, Cost: 3802.90, Comm 0.00
2006-11-06T23:59:59.999989, BUY CREATE, exectype Limit, price 4004.77, valid: 2006-11-10
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-10T23:59:59.999989, BUY EXPIRED
2006-12-11T23:59:59.999989, BUY CREATE, exectype Limit, price 4012.36, valid: 2006-12-15
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-15T23:59:59.999989, BUY EXPIRED
<3>说明
  • 2006-01-26, BUY CREATE, exectype Limit, price 3605.01, valid: 2006-01-30 ,触发买单,注意有valid ,限制在4天内有效,当前是26日,有效期到30日
  • 2006-01-30T23:59:59.999989, BUY EXPIRED ,30日,没有能够到达限价内,并且时间限制到达,所以买单过期
  • 2006-09-20T23:59:59.999989, BUY CREATE, exectype Limit, price 3802.90, valid: 2006-09-24 ,收盘价:3841.31,限价:3841.31 * 0.99 = 3802.8969 =3802.90 ,9月24日超期。
  • 2006-09-22T23:59:59.999989, BUY EXECUTED, Price: 3802.90, Cost: 3802.90, Comm 0.00 ,在9月22日的价格区间内,并且没有超过4天,买单成交。

2006-9-22 3839.51 3839.65 3800.65 3812.73

(5)Execution Type: Stop

设置高于信号价格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)
<1>图示

在这里插入图片描述

<2>输出
python ./order-execution-samples.py --exectype Stop --perc1 1
2006-01-26T23:59:59.999989, BUY CREATE, exectype Stop, price 3677.83
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3677.83, Cost: 3677.83, Comm 0.00
2006-03-02T23:59:59.999989, SELL CREATE, 3763.73
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59.999989, SELL EXECUTED, Price: 3763.95, Cost: 3677.83, Comm 0.00
2006-03-10T23:59:59.999989, BUY CREATE, exectype Stop, price 3836.44
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-15T23:59:59.999989, BUY EXECUTED, Price: 3836.44, Cost: 3836.44, Comm 0.00
2006-03-28T23:59:59.999989, SELL CREATE, 3811.45
2006-03-28T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-28T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-29T23:59:59.999989, SELL EXECUTED, Price: 3811.85, Cost: 3836.44, Comm 0.00
2006-03-30T23:59:59.999989, BUY CREATE, exectype Stop, price 3913.36
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-29T23:59:59.999989, BUY EXECUTED, Price: 3913.36, Cost: 3913.36, Comm 0.00
2006-11-02T23:59:59.999989, SELL CREATE, 3974.62
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-03T23:59:59.999989, SELL EXECUTED, Price: 3979.73, Cost: 3913.36, Comm 0.00
2006-11-06T23:59:59.999989, BUY CREATE, exectype Stop, price 4085.67
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-13T23:59:59.999989, BUY EXECUTED, Price: 4085.67, Cost: 4085.67, Comm 0.00
2006-11-24T23:59:59.999989, SELL CREATE, 4048.16
2006-11-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-27T23:59:59.999989, SELL EXECUTED, Price: 4045.05, Cost: 4085.67, Comm 0.00
2006-12-11T23:59:59.999989, BUY CREATE, exectype Stop, price 4093.42
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-13T23:59:59.999989, BUY EXECUTED, Price: 4093.42, Cost: 4093.42, Comm 0.00
<3>说明
  • 2006-01-26T23:59:59.999989, BUY CREATE, exectype Stop, price 3677.83 ,收盘价:3641.42 , 限价:3641.42 *1.01 = 3677.8342 = 3677.83

2006-1-26 3578.92 3641.42 3577.98 3641.42

  • 2006-01-27T23:59:59.999989, BUY EXECUTED, Price: 3677.83, Cost: 3677.83, Comm 0.00 ,限价包括在27日的价格中,成交。

2006-1-27 3643.35 3685.48 3643.35 3685.48

  • 从Limit 和 Stop 对比,区别在于设置限价,Limit是降低1个百分点,stop 是升高1个百分点。把Stop的增加1个百分点,修改为降低1个百分点,也可以执行。对比理解:
    Limit降低1个百分点的结果:
python ./order-execution-samples.py --exectype Limit --perc1 1
2006-01-26, BUY CREATE, exectype Limit, price 3605.01
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-05-18, BUY EXECUTED, Price: 3605.01, Cost: 3605.01, Comm 0.00

Stop降低1个百分点的结果:

python ./order-execution-samples.py --exectype Stop --perc1 1
2006-01-26, BUY CREATE, exectype Stop, price 3605.01
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-01-27, BUY EXECUTED, Price: 3643.35, Cost: 3643.35, Comm 0.00

Limit 和Stop 的区别:

  • Limit 执行的价格,要市价达到 3605.01 价格,才能成交,以限价价格成交。
  • Stop 执行的价格,只要市价大于 3605.01 价格,就可以成交,以市价的开盘价成交。所以有止损的功能!
(6)Execution Type: StopLimit

设置高于信号价格1%的止损价格。但是限价设置在信号(收盘)价以上0.5%,解释为等待力量出现,但不要购买峰值,等待下落。
有效期上限为20天(日历)。

            elif self.p.exectype == 'StopLimit':
                price = self.data.close * (1.0 + self.p.perc1 / 100.0)

                plimit = self.data.close * (1.0 + self.p.perc2 / 100.0)

                self.buy(exectype=bt.Order.StopLimit, price=price, valid=valid,
                         plimit=plimit)

                if self.p.valid:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' valid: %s, pricelimit: %.2f')
                    self.log(txt % (price, valid.strftime('%Y-%m-%d'), plimit))
                else:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' pricelimit: %.2f')
                    self.log(txt % (price, plimit))
<1>图示

在这里插入图片描述

<2>输出
python ./order-execution-samples.py --exectype StopLimit --perc1 1 --perc2 0.5 --valid 20
2006-01-26T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3677.83, valid: 2006-02-15, pricelimit: 3659.63
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-01-26T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-02-03T23:59:59.999989, BUY EXECUTED, Price: 3659.63, Cost: 3659.63, Comm 0.00
2006-03-02T23:59:59.999989, SELL CREATE, 3763.73
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-03T23:59:59.999989, SELL EXECUTED, Price: 3763.95, Cost: 3659.63, Comm 0.00
2006-03-10T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3836.44, valid: 2006-03-30, pricelimit: 3817.45
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-10T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-21T23:59:59.999989, BUY EXECUTED, Price: 3817.45, Cost: 3817.45, Comm 0.00
2006-03-28T23:59:59.999989, SELL CREATE, 3811.45
2006-03-28T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-28T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-29T23:59:59.999989, SELL EXECUTED, Price: 3811.85, Cost: 3817.45, Comm 0.00
2006-03-30T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3913.36, valid: 2006-04-19, pricelimit: 3893.98
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-03-30T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-04-19T23:59:59.999989, BUY EXPIRED
2006-04-20T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3898.60, valid: 2006-05-10, pricelimit: 3879.30
2006-04-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-04-20T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-05-10T23:59:59.999989, BUY EXPIRED
2006-06-01T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3684.81, valid: 2006-06-21, pricelimit: 3666.57
2006-06-01T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-01T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-02T23:59:59.999989, BUY EXECUTED, Price: 3666.57, Cost: 3666.57, Comm 0.00
2006-06-05T23:59:59.999989, SELL CREATE, 3604.33
2006-06-05T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-05T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-06T23:59:59.999989, SELL EXECUTED, Price: 3598.58, Cost: 3666.57, Comm 0.00
2006-06-21T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3562.11, valid: 2006-07-11, pricelimit: 3544.47
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-21T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-06-23T23:59:59.999989, BUY EXECUTED, Price: 3544.47, Cost: 3544.47, Comm 0.00
2006-07-13T23:59:59.999989, SELL CREATE, 3562.56
2006-07-13T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-13T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-14T23:59:59.999989, SELL EXECUTED, Price: 3545.92, Cost: 3544.47, Comm 0.00
2006-07-24T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3669.26, valid: 2006-08-13, pricelimit: 3651.09
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-07-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-08-01T23:59:59.999989, BUY EXECUTED, Price: 3651.09, Cost: 3651.09, Comm 0.00
2006-09-06T23:59:59.999989, SELL CREATE, 3772.21
2006-09-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-07T23:59:59.999989, SELL EXECUTED, Price: 3766.80, Cost: 3651.09, Comm 0.00
2006-09-12T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3826.85, valid: 2006-10-02, pricelimit: 3807.90
2006-09-12T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-12T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-09-22T23:59:59.999989, BUY EXECUTED, Price: 3807.90, Cost: 3807.90, Comm 0.00
2006-11-02T23:59:59.999989, SELL CREATE, 3974.62
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-02T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-03T23:59:59.999989, SELL EXECUTED, Price: 3979.73, Cost: 3807.90, Comm 0.00
2006-11-06T23:59:59.999989, BUY CREATE, exectype StopLimit, price 4085.67, valid: 2006-11-26, pricelimit: 4065.45
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-06T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-20T23:59:59.999989, BUY EXECUTED, Price: 4065.45, Cost: 4065.45, Comm 0.00
2006-11-24T23:59:59.999989, SELL CREATE, 4048.16
2006-11-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-24T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-11-27T23:59:59.999989, SELL EXECUTED, Price: 4045.05, Cost: 4065.45, Comm 0.00
2006-12-11T23:59:59.999989, BUY CREATE, exectype StopLimit, price 4093.42, valid: 2006-12-31, pricelimit: 4073.15
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-11T23:59:59.999989, ORDER ACCEPTED/SUBMITTED
2006-12-22T23:59:59.999989, BUY EXECUTED, Price: 4073.15, Cost: 4073.15, Comm 0.00
<3>说明
  • 2006-01-26T23:59:59.999989, BUY CREATE, exectype StopLimit, price 3677.83, valid: 2006-02-15, pricelimit: 3659.63

2006-1-26 3578.92 3641.42 3577.98 3641.42
用收盘价计算:
3641.42 * 1.01 = 3677.8342 = 3677.83
3641.42 * 1.005 = 3659.6271 = 3659.63

数据一致:
price: 3677.83
pricelimit: 3659.63

  • 2006-02-03T23:59:59.999989, BUY EXECUTED, Price: 3659.63, Cost: 3659.63, Comm 0.00

2006-2-3 3677.05 3696 3652.76 3678.48
不是以限价3677.83成交,而是以止损限价3659.63成交。

再理解一下:
设置高于信号价格1%的止损价格。但是限价设置在信号(收盘)价以上0.5%,解释为等待力量出现,但不要购买峰值,等待下落。

(7)Test Script Execution Help
python ./order-execution-samples.py --help
usage: order-execution-samples.py [-h] [--infile INFILE]
                                  [--csvformat {bt,visualchart,sierrachart,yahoo,yahoo_unreversed}]
                                  [--fromdate FROMDATE] [--todate TODATE]
                                  [--plot] [--plotstyle {bar,line,candle}]
                                  [--numfigs NUMFIGS] [--smaperiod SMAPERIOD]
                                  [--exectype EXECTYPE] [--valid VALID]
                                  [--perc1 PERC1] [--perc2 PERC2]

Showcase for Order Execution Types

optional arguments:
  -h, --help            show this help message and exit
  --infile INFILE, -i INFILE
                        File to be read in
  --csvformat {bt,visualchart,sierrachart,yahoo,yahoo_unreversed}, -c {bt,visualchart,sierrachart,yahoo,yahoo_unreversed}
                        CSV Format
  --fromdate FROMDATE, -f FROMDATE
                        Starting date in YYYY-MM-DD format
  --todate TODATE, -t TODATE
                        Ending date in YYYY-MM-DD format
  --plot, -p            Plot the read data
  --plotstyle {bar,line,candle}, -ps {bar,line,candle}
                        Plot the read data
  --numfigs NUMFIGS, -n NUMFIGS
                        Plot using n figures
  --smaperiod SMAPERIOD, -s SMAPERIOD
                        Simple Moving Average Period
  --exectype EXECTYPE, -e EXECTYPE
                        Execution Type: Market (default), Close, Limit, Stop,
                        StopLimit
  --valid VALID, -v VALID
                        Validity for Limit sample: default 0 days
  --perc1 PERC1, -p1 PERC1
                        % distance from close price at order creation time for
                        the limit/trigger price in Limit/Stop orders
  --perc2 PERC2, -p2 PERC2
                        % distance from close price at order creation time for
                        the limit price in StopLimit orders
(8)源码
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import argparse
import datetime
import os.path
import time
import sys


import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind


class OrderExecutionStrategy(bt.Strategy):
    params = (
        ('smaperiod', 15),
        ('exectype', 'Market'),
        ('perc1', 3),
        ('perc2', 1),
        ('valid', 4),
    )

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.data.datetime[0]
        if isinstance(dt, float):
            dt = bt.num2date(dt)
        print('%s, %s' % (dt.isoformat(), txt))

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            self.log('ORDER ACCEPTED/SUBMITTED', dt=order.created.dt)
            self.order = order
            return

        if order.status in [order.Expired]:
            self.log('BUY EXPIRED')

        elif order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

        # Sentinel to None: new orders allowed
        self.order = None

    def __init__(self):
        # SimpleMovingAverage on main data
        # Equivalent to -> sma = btind.SMA(self.data, period=self.p.smaperiod)
        sma = btind.SMA(period=self.p.smaperiod)

        # CrossOver (1: up, -1: down) close / sma
        self.buysell = btind.CrossOver(self.data.close, sma, plot=True)

        # Sentinel to None: new ordersa allowed
        self.order = None

    def next(self):
        if self.order:
            # An order is pending ... nothing can be done
            return

        # Check if we are in the market
        if self.position:
            # In the maerket - check if it's the time to sell
            if self.buysell < 0:
                self.log('SELL CREATE, %.2f' % self.data.close[0])
                self.sell()

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

            # Not in the market and signal to buy
            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])

            elif self.p.exectype == 'Close':
                self.buy(exectype=bt.Order.Close)

                self.log('BUY CREATE, exectype Close, price %.2f' %
                         self.data.close[0])

            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)

            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)

            elif self.p.exectype == 'StopLimit':
                price = self.data.close * (1.0 + self.p.perc1 / 100.0)

                plimit = self.data.close * (1.0 + self.p.perc2 / 100.0)

                self.buy(exectype=bt.Order.StopLimit, price=price, valid=valid,
                         plimit=plimit)

                if self.p.valid:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' valid: %s, pricelimit: %.2f')
                    self.log(txt % (price, valid.strftime('%Y-%m-%d'), plimit))
                else:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' pricelimit: %.2f')
                    self.log(txt % (price, plimit))


def runstrat():
    args = parse_args()

    cerebro = bt.Cerebro()

    data = getdata(args)
    cerebro.adddata(data)

    cerebro.addstrategy(
        OrderExecutionStrategy,
        exectype=args.exectype,
        perc1=args.perc1,
        perc2=args.perc2,
        valid=args.valid,
        smaperiod=args.smaperiod
    )
    cerebro.run()

    if args.plot:
        cerebro.plot(numfigs=args.numfigs, style=args.plotstyle)


def getdata(args):

    dataformat = dict(
        bt=btfeeds.BacktraderCSVData,
        visualchart=btfeeds.VChartCSVData,
        sierrachart=btfeeds.SierraChartCSVData,
        yahoo=btfeeds.YahooFinanceCSVData,
        yahoo_unreversed=btfeeds.YahooFinanceCSVData
    )

    dfkwargs = dict()
    if args.csvformat == 'yahoo_unreversed':
        dfkwargs['reverse'] = True

    if args.fromdate:
        fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
        dfkwargs['fromdate'] = fromdate

    if args.todate:
        fromdate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
        dfkwargs['todate'] = todate

    dfkwargs['dataname'] = args.infile

    dfcls = dataformat[args.csvformat]

    return dfcls(**dfkwargs)


def parse_args():
    parser = argparse.ArgumentParser(
        description='Showcase for Order Execution Types')

    parser.add_argument('--infile', '-i', required=False,
                        default='./datas/2006-day-001.txt',
                        help='File to be read in')

    parser.add_argument('--csvformat', '-c', required=False, default='bt',
                        choices=['bt', 'visualchart', 'sierrachart',
                                 'yahoo', 'yahoo_unreversed'],
                        help='CSV Format')

    parser.add_argument('--fromdate', '-f', required=False, default=None,
                        help='Starting date in YYYY-MM-DD format')

    parser.add_argument('--todate', '-t', required=False, default=None,
                        help='Ending date in YYYY-MM-DD format')

    parser.add_argument('--plot', '-p', action='store_false', required=False,
                        help='Plot the read data')

    parser.add_argument('--plotstyle', '-ps', required=False, default='bar',
                        choices=['bar', 'line', 'candle'],
                        help='Plot the read data')

    parser.add_argument('--numfigs', '-n', required=False, default=1,
                        help='Plot using n figures')

    parser.add_argument('--smaperiod', '-s', required=False, default=15,
                        help='Simple Moving Average Period')

    parser.add_argument('--exectype', '-e', required=False, default='Market',
                        help=('Execution Type: Market (default), Close, Limit,'
                              ' Stop, StopLimit'))

    parser.add_argument('--valid', '-v', required=False, default=0, type=int,
                        help='Validity for Limit sample: default 0 days')

    parser.add_argument('--perc1', '-p1', required=False, default=0.0,
                        type=float,
                        help=('%% distance from close price at order creation'
                              ' time for the limit/trigger price in Limit/Stop'
                              ' orders'))

    parser.add_argument('--perc2', '-p2', required=False, default=0.0,
                        type=float,
                        help=('%% distance from close price at order creation'
                              ' time for the limit price in StopLimit orders'))

    return parser.parse_args()


if __name__ == '__main__':
    runstrat()
(9)修改为ipython版本

把所有输入参数都内置到程序中,通过调整参数,实现命令行方式的参数测试。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

#import argparse
import datetime
import os.path
import time
import sys


import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind

%matplotlib inline

class OrderExecutionStrategy(bt.Strategy):
    params = (
        ('smaperiod', 15),
        ('exectype', 'Market'),
        ('perc1', 3),
        ('perc2', 1),
        ('valid', 4),
    )

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.data.datetime[0]
        if isinstance(dt, float):
            dt = bt.num2date(dt)
        print('%s, %s' % (dt.isoformat()[:10], txt)) # 字符串,仅显示日期,不显示时分秒

    def notify_order(self, order):
        
        # 订单提交、接收状态处理
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            self.log('ORDER ACCEPTED/SUBMITTED', dt=order.created.dt)
            self.order = order
            return

        #订单过期处理
        if order.status in [order.Expired]:
            self.log('BUY EXPIRED')

        #订单完成处理
        elif order.status in [order.Completed]:
            #买单操作
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

            #卖单操作
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

        # Sentinel to None: new orders allowed
        self.order = None

    def __init__(self):
        # SimpleMovingAverage on main data
        # Equivalent to -> sma = btind.SMA(self.data, period=self.p.smaperiod)
        # SMA赋值,用params参数中的周期 15 天
        sma = btind.SMA(period=self.p.smaperiod)

        # CrossOver (1: up, -1: down) close / sma
        # 买卖标志,收盘上穿SMA 1 ,收盘下穿SMA -1 
        self.buysell = btind.CrossOver(self.data.close, sma, plot=True)

        # Sentinel to None: new orders allowed
        self.order = None

    def next(self):
        
        # 如有订单,无操作,返回
        if self.order:
            # An order is pending ... nothing can be done
            return

        # Check if we are in the market
        # 如无订单,检查仓位
        if self.position:
            # In the maerket - check if it's the time to sell
            # 小于0 ,卖出
            if self.buysell < 0:
                self.log('SELL CREATE, %.2f' % self.data.close[0])
                self.sell()

        # 大于0 ,买入
        elif self.buysell > 0:
            # 买入时,(1)先检查param的参数valid ,使用valid参数,设置订单有效期限
            if self.p.valid:
                valid = self.data.datetime.date(0) + \
                        datetime.timedelta(days=self.p.valid)
            else:
                valid = None

            # Not in the market and signal to buy
            # 买入时,(2)检查执行类型 ,默认是 Market 
            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])

            # 买入时,执行类型,Close
            elif self.p.exectype == 'Close':
                self.buy(exectype=bt.Order.Close)

                self.log('BUY CREATE, exectype Close, price %.2f' %
                         self.data.close[0])

            # 买入时,执行类型,限价Limit
            elif self.p.exectype == 'Limit':
                price = self.data.close * (1.0 - self.p.perc1 / 100.0)

                # 执行买入操作,限价,执行参数: price valid
                self.buy(exectype=bt.Order.Limit, price=price, valid=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)

            # 买入时,执行类型,止损止盈 Stop
            elif self.p.exectype == 'Stop':
                # 执行价格:收盘价的 +3% 
                price = self.data.close * (1.0 + self.p.perc1 / 100.0)

                # 执行买入操作, Stop操作
                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)

            # 设置高于信号价格3%的止损止盈价格,限价设置在信号(收盘)价以上1%
            elif self.p.exectype == 'StopLimit':
                price = self.data.close * (1.0 + self.p.perc1 / 100.0)

                plimit = self.data.close * (1.0 + self.p.perc2 / 100.0)

                self.buy(exectype=bt.Order.StopLimit, price=price, valid=valid,
                         plimit=plimit)

                if self.p.valid:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' valid: %s, pricelimit: %.2f')
                    self.log(txt % (price, valid.strftime('%Y-%m-%d'), plimit))
                
                else:
                    txt = ('BUY CREATE, exectype StopLimit, price %.2f,'
                           ' pricelimit: %.2f')
                    self.log(txt % (price, plimit))

'''
--exectype Market
--exectype Close
--exectype Limit --perc1 1
--exectype Limit --perc1 1 --valid 4
--exectype Stop --perc1 1
--exectype StopLimit --perc1 1 --perc2 0.5 --valid 20
'''

def runstrat():
    param_exectype = ['Market', 'Close', 'Limit','Stop', 'StopLimit']
    param_plotstyle=['bar', 'line', 'candle']
    param_numfigs = 1 # no use 
    param_perc1 = 0
    param_perc2 = 0
    param_valid = 0
    param_smaperiod = 15
    param_plot = False

    cerebro = bt.Cerebro()

    data = getdata()
    #print(data)
    
    cerebro.adddata(data)
    #print('add data finished!')

    cerebro.addstrategy(
        OrderExecutionStrategy,
        exectype=param_exectype[3],
        perc1=param_perc1,
        perc2=param_perc2,
        valid=param_valid,
        smaperiod=param_smaperiod
    )
    #print('add strategy finished!')
    
    cerebro.run()

    if param_plot:
        cerebro.plot(iplot=False, style=param_plotstyle[0])


def getdata():

    dataformat = dict(
        bt=btfeeds.BacktraderCSVData,
        visualchart=btfeeds.VChartCSVData,
        sierrachart=btfeeds.SierraChartCSVData,
        yahoo=btfeeds.YahooFinanceCSVData,
        yahoo_unreversed=btfeeds.YahooFinanceCSVData
    )
    choices=['bt', 'visualchart', 'sierrachart','yahoo', 'yahoo_unreversed']

    param_infile = './datas/2006-day-001.txt'
    param_csvformat = choices[0] # default : bt
    
    param_fromdate = None
    param_todate = None
    
    dfkwargs = dict()
    if param_csvformat == 'yahoo_unreversed':
        dfkwargs['reverse'] = True

    if param_fromdate:
        fromdate = datetime.datetime.strptime(param_fromdate, '%Y-%m-%d')
        dfkwargs['fromdate'] = fromdate

    if param_todate:
        tomdate = datetime.datetime.strptime(param_todate, '%Y-%m-%d')
        dfkwargs['todate'] = todate

    dfkwargs['dataname'] = param_infile

    dfcls = dataformat[param_csvformat]
    #print (dfkwargs)
    
    return dfcls(**dfkwargs)


if __name__ == '__main__':
    runstrat()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/350011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LLM之Agent(九)| 通过API集成赋能Autogen Multi-Agent系统

随着大型语言模型的快速发展&#xff0c;构建基于LLM驱动的自治代理&#xff08;autonomous agents&#xff09;已经成为一个备受关注的话题。仅在过去一年中&#xff0c;就出现了许多基于这一理念的新技术和框架。 ​ 本文将探索微软开源的Agent框架&#xff1a;Autogen…

幻兽帕鲁服务器搭建教程分享,小白有福了

如何自建幻兽帕鲁服务器&#xff1f;基于阿里云服务器搭建幻兽帕鲁palworld服务器教程来了&#xff0c;一看就懂系列。本文是利用OOS中幻兽帕鲁扩展程序来一键部署幻兽帕鲁服务器&#xff0c;阿里云百科aliyunbaike.com分享官方基于阿里云服务器快速创建幻兽帕鲁服务器教程&…

vue 样式隔离原理

日常写单文件组件时&#xff0c;会在style添加scoped属性&#xff0c;如<style scoped>&#xff0c;目的是为了隔离组件与组件之间的样式&#xff0c;如下面的例子&#xff1a; <template><p class"foo">这是foo</p><p class"bar&q…

【SpringCloud Nacos】 微服务治理介绍及Nacos引入初体验

文章目录 前言服务治理介绍什么是服务治理1、服务发现2、服务配置3、服务健康检测 常见的注册中心ZookeeperEurekaConsulNacos Nacos 简介Nacos 实战入门搭建nacos环境1、安装nacos2、配置nacos3、访问nacos 将商品微服务注册到 nacos1、在 pom. xml 中添加 nacos 的依赖2、在主…

华为机考入门python3--(0)测试题1-句子平均重量

分类&#xff1a;字符串 知识点&#xff1a; 获取输入 input().strip().split(" ") 拼接列表 " ".join(list) 输出指定位数的浮点数 print("%.2f" % value) len() 函数对于很多内置的数据类型都适用&#xff0c;它返回对象的元素个数或长度。…

Android App开发基础(3)——App的设计规范

3 App的设计规范 本节介绍了App工程的源码设计规范&#xff0c;首先App将看得见的界面设计与看不见的代码逻辑区分开&#xff0c;然后利用XML标记描绘应用界面&#xff0c;同时使用Java代码书写程序逻辑&#xff0c;从而形成App前后端分离的设计规约&#xff0c;有利于提高App集…

零基础学编程工具简介,中文编程开发工具

零基础学编程工具简介&#xff0c;中文编程开发工具 一、前言 零基础自学编程&#xff0c;中文编程工具下载&#xff0c;中文编程工具构件之扩展系统菜单构件教程 编程系统化教程链接https://jywxz.blog.csdn.net/article/details/134073098?spm1001.2014.3001.5502 给大家…

大创项目推荐 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现

文章目录 0 前言1 项目背景2 算法架构3 FP-Growth算法原理3.1 FP树3.2 算法过程3.3 算法实现3.3.1 构建FP树 3.4 从FP树中挖掘频繁项集 4 系统设计展示5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于FP-Growth的新闻挖掘算法系统的设计与实现…

并行化K-means聚类算法的实现与分析

并行化K-means聚类算法 并行化K-means聚类算法的实现与分析项目背景与意义算法原理与串行实现分析并行化策略与关键细节实验结果与讨论未来改进方向结语 并行化K-means聚类算法的实现与分析 在大数据时代&#xff0c;对数据进行高效的聚类是数据分析与挖掘的重要工具之一。本文…

云轴科技ZStack成为交通运输业上云用云推进中心首批成员单位

近日&#xff0c;中国信息通信研究院、中国交通运输协会信息专业委员会联合发起成立“交通运输业上云用云推进中心”&#xff0c;上海云轴信息科技有限公司&#xff08;简称云轴科技ZStack&#xff09;凭借优秀的产品技术创新能力和在交通运输领域的实践经验成为首批成员单位并…

37、Flink 的CDC 格式:debezium部署以及mysql示例(完整版)

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点&#xff0c;并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分&#xff0c;比如术语、架构、编程模型、编程指南、基本的…

记录yolov8_obb训练自己的数据集

一.数据集制作 1.标注软件&#xff1a;roLabelImg roLabelImg是基于labelImg改进的&#xff0c;是用来标注为VOC格式的数据&#xff0c;但是在labelImg的基础上增加了能够使标注的框进行旋转的功能。 2.数据格式转换 2.1 xml转txt # 文件名称 &#xff1a;roxml_to_dota.p…

Linux | makefile简单教程 | Makefile的工作原理

前言 在学习完了Linux的基本操作之后&#xff0c;我们知道在linux中编写代码&#xff0c;编译代码都是要手动gcc命令&#xff0c;来执行这串代码的。 但是我们难道在以后运行代码的时候&#xff0c;难道都要自己敲gcc命令嘛&#xff1f;这是不是有点太烦了&#xff1f; 在vs中…

接口自动化测试:mock server之Moco工具

什么是mock server mock&#xff1a;英文可以翻译为模仿的&#xff0c;mock server是我们用来解除依赖&#xff08;耦合&#xff09;&#xff0c;假装实现的技术&#xff0c;比如说&#xff0c;前端需要使用某些api进行调试&#xff0c;但是服务端并没有开发完成这些api&#…

SAP 票据批导实现方法

增强结构定义 变量定义 调用bapi前处理相关变量

【JavaScript权威指南第七版】读书笔记速度

JavaScript权威指南第七版 序正文前言&#xff1a;图中笔记重点知识第1章 JavaScript简介第一章总结 第2章 词法结构注释字面量标识符和保留字Unicode可选的分号第二章总结 第3章 类型、值和变量【重要】原始类型特殊类型第三章总结 第4章 表达式与操作符表达式操作符条件式调用…

HTML-框架标签、实体、全局属性和元信息

HTML 1.框架标签 <iframe name"b站" src"https://www.bilibili.com" width"500" height"300" frameborder"0"></iframe>iframe 标签的实际应用&#xff1a; 在网页中嵌入广告。与超链接或表单的 target 配合&a…

林浩然的Java冒险:从单分支到多分支的奇趣编程之旅

林浩然的Java冒险&#xff1a;从单分支到多分支的奇趣编程之旅 Lin Haoran’s Java Adventure: A Whimsical Journey from Single Branch to Multiple Branches 在那个充满神秘色彩的Java编程世界里&#xff0c;林浩然是一位无畏的程序武士。他的江湖历险从单一的分支结构开始&…

链表的应用1--多项式求和

今天学数据结构学到的链表应用于多项式相加&#xff0c;但是书上的代码没看懂&#xff0c;在看了点资料和问ChatGPT以后想到的一个算法&#xff0c;后面有更好的想法在回来更新算法 1.链表相关结构&#xff1a; //链表结点结构 typedef struct linknode {int coef;//系数 int…

磁悬浮轴承行业调研:未来高端市场占比将有所提升

磁悬浮轴承是利用磁力作用将转子悬浮于空中&#xff0c;使转子与定子之间没有机械接触。其原理是磁感应线与磁浮线成垂直&#xff0c;轴芯与磁浮线是平行的&#xff0c;所以转子的重量就固定在运转的轨道上&#xff0c;利用几乎是无负载的轴芯往反磁浮线方向顶撑&#xff0c;形…