分类
联系方式
  1. 新浪微博
  2. E-mail

BackTrader Strategy 交易策略

交易策略是回测的核心,在 BackTrader 中对应位 Strategy 类。在本文中记录了对 Strategy 类的介绍。

声明策略

按照如下方式声明策略:

import backtrader as bt

class TestStrategy(bt.Strategy):
    pass

类初始化

进行初始化操作:

  1. 数据加工
  2. 状态声明
  3. 指标创建

示例代码:

def __init__(self):
    # 数据加工
    self.dataclose = self.datas[0].close

    # 状态声明
    self.order = None
    self.buyprice = None
    self.buycomm = None

    # 指标创建
    self.rsi = bt.indicators.RSI_SMA(self.datas[0], period=self.params.maperiod)
    bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
    bt.indicators.WeightedMovingAverage(self.datas[0], period=25, subplot=True)
    bt.indicators.StochasticSlow(self.datas[0])

notify_order

该方法在执行买入卖出时会被回调。方法签名:

def notify_order(self, order):

其中 order 包含一系列状态:

Order 状态
状态 说明
Submitted
Accepted
Completed 交易完成
Canceled
Margin
Rejected

其中,目前实际用到的只有 Completed 状态。

示例代码:

def notify_order(self, order):
    if order.status in [order.Submitted, order.Accepted]:
        # Buy/Sell order submitted/accepted to/by broker - Nothing to do
        return

    # 交易完成
    # Attention: broker could reject order if not enough cash
    if 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)
            )

            self.buyprice = order.executed.price  # 买入价格
            self.buycomm = order.executed.comm  # 买入手续费
        elif order.issell():
            self.log(
                "SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
                % (order.executed.price, order.executed.value, order.executed.comm)
            )

        self.bar_executed = len(self)  # 买入日期

    elif order.status in [order.Canceled, order.Margin, order.Rejected]:
        self.log("Order Canceled/Margin/Rejected")

    # Write down: no pending order
    self.order = None

notify_trade

该方法在一直股票清仓后会被回调。方法签名:

def notify_trade(self, trade):

示例代码,展示此次交易的利润:

def notify_trade(self, trade):
    if not trade.isclosed:
        return

    self.log("OPERATION PROFIT, GROSS %.2f, NET %.2f" % (trade.pnl, trade.pnlcomm))

一个是扣手续费之前的利润,一个是实际到手的利润。

next

这是具体编写策略的位置。具体来说,根据股票数据,和指标,编写数学、逻辑算法,决定执行买入、卖出操作。

stop

策略定制回调。

self.datas 数据

在 Strategy 类中,通过 self.datas 访问股票数据。

self.datas 是由 Data Feed 传入的股票数据,data 表示一个数据表,datas 表示多个数据表。也就是说,在 BackTrader 中,允许向 Strategy 传入多个数据表(datas),而每个 data 表示一支股票的数据。

取第 N 个数据表

由于 self.datas 是数据表的合计,因此在实际数据获取时,需要从中取出某一个数据。BackTrader 支持通过索引进行获取:

# 支持两种写法
self.datas[0]
self.data0

self.data

在 BackTrader,也提供 self.data 属性,默认指向添加的第一组数据(第一个数据表)。

根据表名获取数据

在添加 Data Feed 时,可以指定一个名称(name)。

这样在获取时,也可以按表明进行获取。具体方法:

self.getdatabyname('dataname')