我们之前已经了解了如何使用 backtrader 提取数据并创建最简单的策略(如果您错过了这个故事:使用 Python 回测您的交易系统 - 简介)。 我们现在将看到如何制定复杂的策略。
战略的骨架
以下是任何策略的框架:
import backtrader as btclass MyStrategy(bt.Strategy):
params = (
)
def __init__(self):
pass
def log(self, msg, dt=None):
pass def next(self):
pass
def notify_order(self, order):
pass
def notify_trade(self, trade):
pass
- params:策略的参数。
- init:策略的构造函数,用于指标的初始化。
- log:可用于显示文本的方法。
- next:每次迭代执行的方法。
- notify_order:创建或更新订单时执行的方法。
- notify_trade:创建或更新交易时执行的方法。
指标
也许您想在策略中使用指标。 谢天谢地,backtrader 有一些可用的基本指标,例如 RSI、MACD、EMA 等……如果您想要自定义指标,您可以开发自己的指标,但我们稍后会看到。
您需要首先导入要使用的指标,例如 EMA。
from backtrader.indicators import ExponentialMovingAverage as EMA
然后,您可以在策略的构造函数中初始化它们:
def __init__(self):
self.ema = EMA(period=10)
如您所见,我们可以为指标指定参数。
然后,如果我们在策略的下一个方法中需要我们的 ema 值,我们可以像获得收盘价一样获得它。 我们想要获取我们的 ema 属性的 ema 行:
ema_now = self.ema.ema[0]
如果我们想要 ema 早一点:
ema_earlier = self.ema.ema[-1]
参数
参数化我们的策略很有用,无论是为了优化还是为了尝试。 我们可以在 params 属性中指定参数。
class MyStrategy(bt.Strategy):
params = (
('ema_period', 10),
)
参数是一个元组,其第一个元素是参数的名称,第二个元素是默认值。
然后我们可以使用 self.p 在策略中的任何位置访问我们的参数:
def __init__(self):
self.ema = EMA(period=self.p.ema_period)
我们在初始化策略时指定一个参数的值:
cerebro.addstrategy(MyStrategy, ema_period=10)
规则
为了定义我们的策略规则,我们使用下一个方法。
def next(self):
if self.datas[0].close[0] < self.ema.ema[0]:
# do something
订单
为了处理订单,我们首先必须在策略的构造函数中初始化一个空列表:
def __init__(self):
self.orders_ref = list()
现在,我们必须实现 notify_order :
def notify_order(self, order):
if not order.alive() and order.ref in self.orders_ref:
self.orders_ref.remove(order.ref)
这样,当创建或更新订单时,我们会检查订单是否仍然有效。 如果他不是,我们将其删除。
然后,当我们的策略信号被触发时,我们必须创建订单。 为方便起见,我们将从一个简单的购买订单开始:
def next(self):
if self.datas[0].close[0] < self.ema[0]:
orders = [self.buy()]
self.orders_ref = [order.ref for order in orders if order]
if self.datas[0].close[0] > self.ema[0]:
self.close()
我们使用 self.buy() 购买和 self.sell() 出售。 self.close() 关闭我们的订单。
如果我们想让事情变得更复杂,我们可以使用 OCO 订单:
orders = self.buy_bracket(price=ACTUAL_PRICE, stopprice=stop_price, limitprice=take_profit_price)
我们还可以使用止损单或限价单:
orders = [self.buy(), self.sell(exectype=bt.Order.Stop, price=stop_price)]
# or
orders = [self.buy(), self.sell(exectype=bt.Order.Limit, price=take_profit_price)]
混合一切
现在,我们可以使用我们所知道的一切来完成我们的策略框架:
class MyStrategy(bt.Strategy):
params = (
('ema_period', 10),
)
def __init__(self):
self.ema = EMA(period=self.p.ema_period)
def log(self, msg, dt=None):
print("{} - {}".format(dt or self.datas[0].datetime.date(0), msg))
def next(self):
self.log('{} - {} {} @ {}'.format(self.datas[0].datetime.date(0), self.datas[0].close[0], self.datas[0]._name, self.ema[0]))
if self.datas[0].close[0] < self.ema[0]:
orders = [self.buy()]
self.orders_ref = [order.ref for order in orders if order]
if self.datas[0].close[0] > self.ema[0]:
self.close()
def notify_order(self, order):
self.log('{} - {} {} @ {}'.format(order.data._name, order.size, order.data._name, order.price))
if not order.alive() and order.ref in self.orders_ref:
self.orders_ref.remove(order.ref)
def notify_trade(self, trade):
self.log('{} - {} {} @ {}'.format(trade.dt.date(0), trade.size, trade.data._name, trade.price))
我们可以运行我们的策略:
btc_eur = yf.Ticker("BTC-EUR")
data = btc_eur.history()
pandas_data = btfeeds.PandasData(dataname=data)
cerebro.adddata(pandas_data)
cerebro.addstrategy(MyStrategy, ema_period=200)cerebro.run()
您的策略将经过回测,您应该会看到一些数据被记录下来。
然后?
然后,什么也没有发生,因为我们不使用任何分析器。 我们将在下一个故事中看到如何使用它们来分析您的策略结果。 同时,您可以在 cerebro.run() 之后为 cerebro.plot() 添加一行。 它将显示您的策略图表。
请务必关注我,这样您就不会错过下一个关于使用 Python 回测您的交易系统的故事!
关注七爪网,获取更多APP/小程序/网站源码资源!