量化交易学习(四十一)backtrader文档——日期时间管理

今天这篇是backtrader文档的学习笔记。主要介绍了日期时间管理。

官方文档链接:https://www.backtrader.com/docu/timemgmt/

日期时间管理

在1.5.0版本之前,backtrader使用直接的时间管理方法,因为数据源计算的任何日期时间都只是按表面值使用。

这对于任何用户输入参数都是一样的,比如可以给任何数据源的fromdate(或sessionstart)参数。

对于可以直接用于回测的固定数据源,该方法很好。很容易假设输入日期时间在进入系统之前就已经得到处理。

但在 1.5.0 版本之后,支持实时数据源,这迫使我们考虑日期时间管理。如果以下情况始终为真,则不需要此类管理:

  • 纽约的一位交易员交易 ES-Mini。两者都使用相同的US/Eastern 时区

  • 柏林的一名交易员正在交易 DAX 期货。在这种情况下,两者都使用相同的CET(或Europe/Berling)时区。

上面的情况下直接输入输出日期时间方法是可行的,因为交易者(例如在柏林)总是可以执行如下操作:

1
2
3
4
5
6
7
8
class Strategy(bt.Strategy):

def next(self):

# The DAX future opens at 08:00 CET
if self.data.datetime.time() < datetime.time(8, 30):
# don't operate until the market has been running 30 minutes
return #

当柏林的同一交易者决定交易 ES-Mini时,直接的日期管理方法的问题就显现出来了。因为夏令时的更改发生在一年中的不同时间点,这会导致一年中的几周时差不同步。以下代码并不总是有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Strategy(bt.Strategy):

def next(self):

# The SPX opens at 09:30 US/Eastern all year long
# This is most of the year 15:30 CET
# But it is sometimes 16:30 CET or 14:30 CET if a DST switch on-off
# has happened in the USA and not in Europe

# That's why the code below is unreliable

if self.data.datetime.time() < datetime.time(16, 0):
# don't operate until the market has been running 30 minutes
return #

处理时区

为了解决上述情况并仍然与直接输入输出时间方法兼容,backtrader为最终用户提供以下功能

Datetime Input

  • 默认情况下,平台不会处理数据源提供的日期时间

    • 最终用户可以通过以下方式覆盖输入的日期时间:

      • 向数据源提供tzinput参数。这必须是与接口兼容的datetime.tzinfo对象。用户很可能会提供一个pytz.timezone实例

    这样处理后,backtrader内部使用的时间被认为是UTC-like格式的,即:

    • 如果数据源已经以UTC格式存储

    • 经过tzinput转换

    • 这不是真的UTC,但它是用户的参考,因此称为UTC-like

Datetime output

  • 如果数据源可以自动确定输出的时区,则这将是默认值

    这在实时数据源的情况下是有意义的,尤其是在类似于在柏林(CET时区)的交易者使用US/Eastern时区进行交易的情况下。

    因为交易者总是能获得正确的时间,并且在上面的示例中,开盘时间保持恒定为09:30 US/Eastern,而不是在一年中的大部分时间为15:30 CET,但有时候在16:30 CET,有时候在14:30 CET

  • 如果无法确定时区,则输出将是在输入(UTC-like)时确定的

  • 最终用户可以覆盖并指定实际输出的时区

    • 向数据源提供tz参数。这必须是与datetime.tzinfo接口兼容的对象。用户很可能会提供一个pytz.timezone实例

注意:

来自用户的输入例如参数fromdatesessionstart期望与实际的tz同步,无论是由数据源自动计算、由用户提供还是保留为默认值(None,这意味着日期时间的直接输入输出)

考虑到所有这些,让我们回想一下柏林交易员,在US/Eastern时区交易的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pytz

import bt

data = bt.feeds.MyFeed('ES-Mini', tz=pytz.timezone('US/Eastern'))

class Strategy(bt.Strategy):

def next(self):

# This will work all year round.
# The data source will return in the frame of the 'US/Eastern' time
# zone and the user is quoting '10:00' as reference time
# Because in the 'US/Eastern' timezone the SPX index always starts
# trading at 09:30, this will always work

if self.data.datetime.time() < datetime.time(10, 0):
# don't operate until the market has been running 30 minutes
return #

对于可以自动确定输出时区的数据源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import bt

data = bt.feeds.MyFeedAutoTZ('ES-Mini')

class Strategy(bt.Strategy):

def next(self):

# This will work all year round.
# The data source will return in the frame of the 'US/Eastern' time
# zone and the user is quoting '10:00' as reference time
# Because in the 'US/Eastern' timezone the SPX index always starts
# trading at 09:30, this will always work

if self.data.datetime.time() < datetime.time(10, 0):
# don't operate until the market has been running 30 minutes
return #

甚至比上面的工作还要少。

显然,在上面的示例中,MyFeedMyFeedAuto只是虚拟名称。


这一篇就到这里啦。欢迎大家点赞、转发、私信。还没有关注我的朋友可以关注 江达小记

江达小记