在 1.5.0 版之前, backtrader 使用直接的方法来进行时间管理,因为数据源计算的任何日期时间都只是按面值使用。
对于任何用户输入也是如此,例如可以提供给任何数据源的参数fromdate
(或 sessionstart
)的情况
考虑到直接控制冻结的数据源以进行回溯测试,这种方法很好。很容易假设输入日期时间在进入系统之前已经得到处理。
但是在 1.5.0 中,支持实时 数据源,这强制考虑 日期时间管理。如果始终 true以下情况,则不需要进行此类管理:
-
纽约的一位交易者交易ES-Mini。(或其中一个别名)的
US/Eastern
时区 -
柏林的一位交易者交易DAX期货。在这种情况下,
CET
对于两个(或Europe/Berling
)时区都适用
上面的直接输入输出日期时间方法将起作用,例如,在柏林的交易者总是可以做这样的事情:
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
。因为从 DST 更改为 DST 发生在一年中的不同时间点,这会导致时差在一年中的几个星期内不同步。以下方法并不总是有效:
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
为最终用户提供以下功能
-
默认情况下,平台不会触及数据源提供的日期时间
-
最终用户可以通过以下方式覆写此输入:
-
向数据源提供
tzinput
参数。这必须是与接口兼容的对象datetime.tzinfo
。最有可能的是,用户将提供一个pytz.timezone
实例
有了这个决定,内部
backtrader
使用的时间被认为是格式的UTC-like
,即:-
如果数据源已将其
UTC
格式存储 -
转换后通过
tzinput
-
它不是真的
UTC
,但它是用户的参考,因此UTC-like
-
-
如果 data feed 可以自动确定输出的时区,这将是默认值
这在即时馈送的情况下是有意义的,特别是在像柏林(
CET
时区)的交易者使用US/Eastern
时区交易产品这样的用例中。因为交易者总是得到正确的时间,在上面的例子中,开盘时间保持不变
09:30 US/Eastern
,而不是15:30 CET
一年中的大部分时间都,但有时16:30 CET
和有时14:30 CET
。 -
如果无法确定,则输出将是输入(该)时间内确定的任何内容。
UTC-like
-
最终用户可以覆盖和确定输出的实际时区
- 向数据源提供
tz
参数。这必须是与接口兼容的对象datetime.tzinfo
。最有可能的是,用户将提供一个pytz.timezone
实例
- 向数据源提供
注意
用户输入的参数fromdate
或 sessionstart
期望与实际 tz
参数同步,由数据源自动计算,由用户提供或保留为默认值(None
这意味着日期时间的直接输入输出)
考虑到所有这些,让我们回想一下柏林交易者,交易:US/Eastern
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 #
对于可以自动确定输出时区的数据来源:
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 #
甚至比上面更少的工作。
显然MyFeed
, MyFeedAuto
在上面的例子中只是虚拟的名字。
注意
在撰写本文时,分配中包含的唯一可以自动确定时区的数据源是连接到盈透证券的数据源