索引和切片

索引和切片#

索引:0 和 -1#

Backtrader 中,Line 代表一组按时间顺序排列的点。这些点在策略执行期间动态生成,可通过索引访问。

使用索引访问 Line#

访问当前值: 使用 0 索引访问当前的线值,如 self.data.close[0] 获取当前收盘价。

class MyStrategy(bt.Strategy):
   def next(self):
       print(self.data.close[0])  # 当前的收盘价

访问前值: 使用负数索引访问之前的值,如 self.data.close[-1] 获取上一条数据的收盘价。

class MyStrategy(bt.Strategy):
   def next(self):
       if self.data.close[0] > self.data.close[-1]:
           print("今天的收盘价高于昨日的收盘价")

索引的意义:

  • 0 索引指向当前时刻的值,-1 指向上一个时刻的值,以此类推。
  • 负数索引指向历史数据点,对时间序列分析和策略数据回溯非常有用。

简单示例:

class MyStrategy(bt.Strategy):
    def next(self):
        # 比较今天的收盘价和昨天的收盘价
        if self.data.close[0] > self.data.close[-1]:
            print("今天的收盘价更高")
        else:
            print("今天的收盘价更低")

在这个示例中,self.data.close[0] 是今天的收盘价,self.data.close[-1] 是昨天的收盘价。


切片#

Backtrader 不支持对 Line 对象进行切片操作,这是为了保持设计一致性。切片适用于普通 Python 数组,但 Line 对象是动态增长的,因此切片存在限制。

为什么不支持切片#

首先是为了保持 Line 设计的一致性。

Line 对象的数据通过索引(如 0-1)动态访问,基于时间序列处理数据。切片在此不适用,因为数据是按时间顺序排列的。

而常规可索引对象的切片是什么样的?

对于普通的 Python 对象,切片操作如下:

my_list = [1, 2, 3, 4, 5]
sliced_list = my_list[1:3]  # 返回 [2, 3]

Backtrader 中的 Line 对象更像一个流式数据源,不能直接进行切片。

如何获取线的某些点#

虽然 Line 不支持切片,但你仍然可以使用 get() 方法来获取线的一部分数据。例如:

# 获取最后 10 个数据点
myslice = self.my_sma.get(size=10)  # 获取最近的 10 个值

这样可以获取指定数量的最近历史数据。


延迟索引#

Backtrader 中,延迟索引允许在 __init__ 阶段访问历史数据,无需手动使用负索引。通常 [] 操作符在 next 阶段提取数据值,而延迟索引可在初始化阶段引用历史数据,生成可在 next 中直接使用的 Lines 对象。

例如,比较前一日的收盘价与当前简单移动平均线(SMA),无需在每次迭代中手动比较,可通过预先生成的 Lines 对象来实现:

初始化时使用延迟索引#

__init__ 方法中,你可以通过延迟索引定义需要的历史数据。例如,比较前一天的收盘价和当前的移动平均值:

class MyStrategy(bt.Strategy):
   params = dict(period=20)

   def __init__(self):
       self.movav = btind.SimpleMovingAverage(self.data, period=self.p.period)
       self.cmpval = self.data.close(-1) > self.movav  # 比较前一日收盘价与当前20日均线

这里,self.data.close(-1) 通过延迟索引获取前一天的收盘价,self.movav 是当前的20日简单移动平均线。self.cmpval 是一个新的 Lines 对象,保存每次比较的结果。

next 方法中使用延迟数据#

next 方法中,你可以直接使用 Lines 对象的值进行逻辑判断。self.cmpval[0] 会返回当前条件是否成立:

class MyStrategy(bt.Strategy):
   def next(self):
       if self.cmpval[0]:  # 如果前一日收盘价高于当前移动平均线
           print("前一日收盘价高于当前简单移动平均线")

延迟索引的工作原理#

self.data.close(-1) 使用延迟索引从历史数据中提取前一天的收盘价。它返回一个 Line 对象,但带有延迟偏移,即相对于当前时刻,它表示前一个时间点的 Line

语句 self.data.close(-1) > self.movav 生成一个新的 Line 对象,该对象在 next 中返回 1(真)或 0(假),可在 next 中直接使用比较结果。

通过这种方式,Backtrader 提供了简洁灵活的方式来引用和比较历史数据,无需手动管理索引,简化了策略编写和逻辑实现。