BackTrader 中文文档(五)(2)

简介: BackTrader 中文文档(五)

BackTrader 中文文档(五)(1)https://developer.aliyun.com/article/1489253

返回值:

  • 创建的计时器
notify_timer(timer, when, *args, **kwargs)

接收定时器通知,其中timer是由add_timer返回的定时器,when是调用时间。argskwargs是传递给add_timer的任何额外参数。

实际的when时间可能会晚一些,但系统可能在之前无法调用定时器。这个值是定时器值,而不是系统时间。

带信号的策略

原文:www.backtrader.com/docu/signal_strategy/signal_strategy/

也可以操作backtrader而不必编写Strategy。尽管这是首选方法,但由于构成机器的对象层次结构,使用Signals也是可能的。

快速摘要:

  • 不是编写Strategy类,实例化Indicators,编写buy/sell逻辑…
  • 最终用户添加Signals(无论如何是指示器),其余操作由后台完成

快速示例:

import backtrader as bt
data = bt.feeds.OneOfTheFeeds(dataname='mydataname')
cerebro.adddata(data)
cerebro.add_signal(bt.SIGNAL_LONGSHORT, MySignal)
cerebro.run()

完成!。

当然,Signal本身是缺失的。让我们定义一个非常愚蠢的Signal,产生:

  • 如果close价格高于Simple Moving Average,则发出Long指示。
  • 如果close价格低于Simple Moving Average,则发出Short指示。

定义为:

class MySignal(bt.Indicator):
    lines = ('signal',)
    params = (('period', 30),)
    def __init__(self):
        self.lines.signal = self.data - bt.indicators.SMA(period=self.p.period)

现在真的完成了。当执行run时,Cerebro将负责实例化一个特殊的Strategy实例,该实例知道如何处理Signals

初始FAQ

  • /操作的数量如何确定?
    cerebro实例自动为策略添加了FixedSize大小器。最终用户可以使用cerebro.addsizer更改大小器以改变策略。
  • 订单是如何执行的?
    执行类型为Market,有效性为Good Until Canceled

Signals技术细节

从技术和理论角度描述如下:

  • 当被调用时返回另一个对象的可调用对象(仅一次)
    这在大多数情况下是类的实例化,但不一定是。
  • 支持__getitem__接口。唯一请求的key/index将为0

从实际角度和上述示例来看,Signal是:

  • 来自backtrader生态系统的lines对象,主要是Indicator
    当使用其他Indicators时,如示例中使用Simple Moving Average时,这很有帮助。

信号 指示

当用signal[0]查询signals时,signals提供指示,意思是:

  • > 0 -> long indication
  • < 0 -> short indication
  • == 0 -> 无指示

该示例对self.data - SMA进行了简单的算术运算,并且:

  • data高于SMA时发出long indication
  • data低于SMA时发出short indication

注意

data 没有指定特定的价格字段时,参考价格为 close 价格。

信号类型

如上例所示,下面指示的常量直接来自主要的backtrader模块,如下所示:

import backtrader as bt
bt.SIGNAL_LONG

共有 5 种Signals类型,分为 2 组。

主要组

  • LONGSHORT: 此信号的longshort指示均被采纳。
  • LONG
  • 采用long指示进入long
  • 采用short指示来close长头寸。但是:
  • 如果系统中存在LONGEXIT(见下文)信号,则将用于退出长头寸
  • 如果有SHORT信号可用,但没有LONGEXIT可用,则会在开放short之前关闭long
  • SHORT
  • short指示用于开空头寸
  • long指示用于关闭空头寸。但是:
  • 如果系统中存在一个SHORTEXIT(见下文)信号,它将被用于退出短头寸
  • 如果有LONG信号可用且没有SHORTEXIT可用,则将用于在开仓long之前关闭short

退出组

这两个信号旨在覆盖其他信号,并提供退出long / short头寸的标准

  • LONGEXITshort指示用于退出long头寸
  • SHORTEXIT指示被视为退出头寸

累积和订单并发

上面显示的示例信号会定期发出指示,因为它只是从close价格中减去SMA值,而这总是会是> 0< 0(数学上可能为0,但实际上不太可能发生)

这将导致连续生成订单,会产生 2 种情况:

  • Accumulation:即使已经在市场上,信号也会产生新订单,这将增加市场上的仓位
  • Concurrency:新订单将生成,而无需等待其他订单的执行

为了避免这种情况,默认行为是:

  • 不累积
  • 不允许并发

如果希望这两种行为之一,可以通过cerebro控制:

  • cerebro.signal_accumulate(True)(或False以重新禁用它)
  • cerebro.signal_concurrency(True)(或False以重新禁用它)

示例

backtrader源代码包含一个用于测试功能的示例。

要使用的主要信号。

class SMACloseSignal(bt.Indicator):
    lines = ('signal',)
    params = (('period', 30),)
    def __init__(self):
        self.lines.signal = self.data - bt.indicators.SMA(period=self.p.period)

并且在指定选项的情况下退出信号

class SMAExitSignal(bt.Indicator):
    lines = ('signal',)
    params = (('p1', 5), ('p2', 30),)
    def __init__(self):
        sma1 = bt.indicators.SMA(period=self.p.p1)
        sma2 = bt.indicators.SMA(period=self.p.p2)
        self.lines.signal = sma1 - sma2

第一次运行:长和短

$ ./signals-strategy.py --plot --signal longshort

输出


注意:

  • 信号被绘制出来。这是正常的,因为它只是一个指标,适用于它的绘图规则
  • 策略实际上是longshort的。这可以看出,因为现金水平从未回到水平
  • 旁注:即使是一个愚蠢的想法…(没有佣金)策略也没有亏钱…

第二次运行:仅限长头寸

$ ./signals-strategy.py --plot --signal longonly

输出

注意:

  • 在每次卖出后,现金水平都会回到水平,这意味着策略已经退出市场
  • 旁注:再次没有损失金钱……

第三次运行:仅限短头寸

$ ./signals-strategy.py --plot --signal shortonly

输出

注意:

  • 第 1 次操作是卖出,符合预期,并且发生在上述两个示例中的第 1 次操作之后。只有在close低于SMA并且简单的减法得到负数时才会发生
  • 在每次买入后,现金水平都会回到水平,这意味着策略已经退出市场
  • 旁注:最终系统亏损

第四次运行:长+长退出

$ ./signals-strategy.py --plot --signal longonly --exitsignal longexit

输出

注意:

  • 许多交易都是相同的,但有些会在快速移动平均线在退出信号中向下穿过慢速移动平均线时中断
  • 该系统展示了其仅做多属性,现金在每次交易结束时的价值。
  • 旁注:再次赚钱……甚至有些修改后的交易也能获利

使用方法

$ ./signals-strategy.py --help
usage: signals-strategy.py [-h] [--data DATA] [--fromdate FROMDATE]
                           [--todate TODATE] [--cash CASH]
                           [--smaperiod SMAPERIOD] [--exitperiod EXITPERIOD]
                           [--signal {longshort,longonly,shortonly}]
                           [--exitsignal {longexit,shortexit}]
                           [--plot [kwargs]]
Sample for Signal concepts
optional arguments:
  -h, --help            show this help message and exit
  --data DATA           Specific data to be read in (default:
                        ../../datas/2005-2006-day-001.txt)
  --fromdate FROMDATE   Starting date in YYYY-MM-DD format (default: None)
  --todate TODATE       Ending date in YYYY-MM-DD format (default: None)
  --cash CASH           Cash to start with (default: 50000)
  --smaperiod SMAPERIOD
                        Period for the moving average (default: 30)
  --exitperiod EXITPERIOD
                        Period for the exit control SMA (default: 5)
  --signal {longshort,longonly,shortonly}
                        Signal type to use for the main signal (default:
                        longshort)
  --exitsignal {longexit,shortexit}
                        Signal type to use for the exit signal (default: None)
  --plot [kwargs], -p [kwargs]
                        Plot the read data applying any kwargs passed For
                        example: --plot style="candle" (to plot candles)
                        (default: None)

该代码

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import argparse
import collections
import datetime
import backtrader as bt
MAINSIGNALS = collections.OrderedDict(
    (('longshort', bt.SIGNAL_LONGSHORT),
     ('longonly', bt.SIGNAL_LONG),
     ('shortonly', bt.SIGNAL_SHORT),)
)
EXITSIGNALS = {
    'longexit': bt.SIGNAL_LONGEXIT,
    'shortexit': bt.SIGNAL_LONGEXIT,
}
class SMACloseSignal(bt.Indicator):
    lines = ('signal',)
    params = (('period', 30),)
    def __init__(self):
        self.lines.signal = self.data - bt.indicators.SMA(period=self.p.period)
class SMAExitSignal(bt.Indicator):
    lines = ('signal',)
    params = (('p1', 5), ('p2', 30),)
    def __init__(self):
        sma1 = bt.indicators.SMA(period=self.p.p1)
        sma2 = bt.indicators.SMA(period=self.p.p2)
        self.lines.signal = sma1 - sma2
def runstrat(args=None):
    args = parse_args(args)
    cerebro = bt.Cerebro()
    cerebro.broker.set_cash(args.cash)
    dkwargs = dict()
    if args.fromdate is not None:
        fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
        dkwargs['fromdate'] = fromdate
    if args.todate is not None:
        todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
        dkwargs['todate'] = todate
    # if dataset is None, args.data has been given
    data = bt.feeds.BacktraderCSVData(dataname=args.data, **dkwargs)
    cerebro.adddata(data)
    cerebro.add_signal(MAINSIGNALS[args.signal],
                       SMACloseSignal, period=args.smaperiod)
    if args.exitsignal is not None:
        cerebro.add_signal(EXITSIGNALS[args.exitsignal],
                           SMAExitSignal,
                           p1=args.exitperiod,
                           p2=args.smaperiod)
    cerebro.run()
    if args.plot:
        pkwargs = dict(style='bar')
        if args.plot is not True:  # evals to True but is not True
            npkwargs = eval('dict(' + args.plot + ')')  # args were passed
            pkwargs.update(npkwargs)
        cerebro.plot(**pkwargs)
def parse_args(pargs=None):
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description='Sample for Signal concepts')
    parser.add_argument('--data', required=False,
                        default='../../datas/2005-2006-day-001.txt',
                        help='Specific data to be read in')
    parser.add_argument('--fromdate', required=False, default=None,
                        help='Starting date in YYYY-MM-DD format')
    parser.add_argument('--todate', required=False, default=None,
                        help='Ending date in YYYY-MM-DD format')
    parser.add_argument('--cash', required=False, action='store',
                        type=float, default=50000,
                        help=('Cash to start with'))
    parser.add_argument('--smaperiod', required=False, action='store',
                        type=int, default=30,
                        help=('Period for the moving average'))
    parser.add_argument('--exitperiod', required=False, action='store',
                        type=int, default=5,
                        help=('Period for the exit control SMA'))
    parser.add_argument('--signal', required=False, action='store',
                        default=MAINSIGNALS.keys()[0], choices=MAINSIGNALS,
                        help=('Signal type to use for the main signal'))
    parser.add_argument('--exitsignal', required=False, action='store',
                        default=None, choices=EXITSIGNALS,
                        help=('Signal type to use for the exit signal'))
    # Plot options
    parser.add_argument('--plot', '-p', nargs='?', required=False,
                        metavar='kwargs', const=True,
                        help=('Plot the read data applying any kwargs passed\n'
                              '\n'
                              'For example:\n'
                              '\n'
                              '  --plot style="candle" (to plot candles)\n'))
    if pargs is not None:
        return parser.parse_args(pargs)
    return parser.parse_args()
if __name__ == '__main__':
    runstrat()

BackTrader 中文文档(五)(3)https://developer.aliyun.com/article/1489262

相关文章
|
5月前
|
Unix 索引 Python
BackTrader 中文文档(一)(2)
BackTrader 中文文档(一)
114 0
|
5月前
|
存储 编解码 API
BackTrader 中文文档(四)(1)
BackTrader 中文文档(四)
64 1
|
5月前
|
Python
BackTrader 中文文档(五)(4)
BackTrader 中文文档(五)
62 0
|
5月前
|
Python
BackTrader 中文文档(六)(3)
BackTrader 中文文档(六)
81 0
|
5月前
|
存储 DataX Python
BackTrader 中文文档(五)(1)
BackTrader 中文文档(五)
91 0
|
5月前
|
测试技术 索引 Python
BackTrader 中文文档(二)(2)
BackTrader 中文文档(二)
61 0
|
5月前
|
存储 API 索引
BackTrader 中文文档(四)(3)
BackTrader 中文文档(四)
47 0
|
5月前
|
存储
BackTrader 中文文档(四)(4)
BackTrader 中文文档(四)
42 0
|
5月前
|
Python
BackTrader 中文文档(一)(3)
BackTrader 中文文档(一)
54 0
|
5月前
BackTrader 中文文档(一)(4)
BackTrader 中文文档(一)
58 0