BackTrader 中文文档(十三)(2)

简介: BackTrader 中文文档(十三)

BackTrader 中文文档(十三)(1)https://developer.aliyun.com/article/1505343

示例代码(tcal-intra.py)

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import argparse
import datetime
import backtrader as bt
class NYSE_2016(bt.TradingCalendar):
    params = dict(
        holidays=[
            datetime.date(2016, 1, 1),
            datetime.date(2016, 1, 18),
            datetime.date(2016, 2, 15),
            datetime.date(2016, 3, 25),
            datetime.date(2016, 5, 30),
            datetime.date(2016, 7, 4),
            datetime.date(2016, 9, 5),
            datetime.date(2016, 11, 24),
            datetime.date(2016, 12, 26),
        ],
        earlydays=[
            (datetime.date(2016, 11, 25),
             datetime.time(9, 30), datetime.time(13, 1))
        ],
        open=datetime.time(9, 30),
        close=datetime.time(16, 0),
    )
class St(bt.Strategy):
    params = dict(
    )
    def __init__(self):
        pass
    def prenext(self):
        self.next()
    def next(self):
        print('Strategy len {} datetime {}'.format(
            len(self), self.datetime.datetime()), end=' ')
        print('Data0 len {} datetime {}'.format(
            len(self.data0), self.data0.datetime.datetime()), end=' ')
        if len(self.data1):
            print('Data1 len {} datetime {}'.format(
                len(self.data1), self.data1.datetime.datetime()))
        else:
            print()
def runstrat(args=None):
    args = parse_args(args)
    cerebro = bt.Cerebro()
    # Data feed kwargs
    # kwargs = dict(tz='US/Eastern')
    # import pytz
    # tz = tzinput = pytz.timezone('Europe/Berlin')
    tzinput = 'Europe/Berlin'
    # tz = tzinput
    tz = 'US/Eastern'
    kwargs = dict(tzinput=tzinput, tz=tz)
    # Parse from/to-date
    dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S'
    for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']):
        if a:
            strpfmt = dtfmt + tmfmt * ('T' in a)
            kwargs[d] = datetime.datetime.strptime(a, strpfmt)
    # Data feed
    data0 = bt.feeds.BacktraderCSVData(dataname=args.data0, **kwargs)
    cerebro.adddata(data0)
    d1 = cerebro.resampledata(data0,
                              timeframe=getattr(bt.TimeFrame, args.timeframe))
    # d1.plotinfo.plotmaster = data0
    # d1.plotinfo.sameaxis = False
    if args.pandascal:
        cerebro.addcalendar(args.pandascal)
    elif args.owncal:
        cerebro.addcalendar(NYSE_2016())  # or NYSE_2016() to pass an instance
    # Broker
    cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')'))
    # Sizer
    cerebro.addsizer(bt.sizers.FixedSize, **eval('dict(' + args.sizer + ')'))
    # Strategy
    cerebro.addstrategy(St, **eval('dict(' + args.strat + ')'))
    # Execute
    cerebro.run(**eval('dict(' + args.cerebro + ')'))
    if args.plot:  # Plot if requested to
        cerebro.plot(**eval('dict(' + args.plot + ')'))
def parse_args(pargs=None):
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description=(
            'Trading Calendar Sample'
        )
    )
    parser.add_argument('--data0', default='yhoo-2016-11.csv',
                        required=False, help='Data to read in')
    # Defaults for dates
    parser.add_argument('--fromdate', required=False, default='2016-01-01',
                        help='Date[time] in YYYY-MM-DD[THH:MM:SS] format')
    parser.add_argument('--todate', required=False, default='2016-12-31',
                        help='Date[time] in YYYY-MM-DD[THH:MM:SS] format')
    parser.add_argument('--cerebro', required=False, default='',
                        metavar='kwargs', help='kwargs in key=value format')
    parser.add_argument('--broker', required=False, default='',
                        metavar='kwargs', help='kwargs in key=value format')
    parser.add_argument('--sizer', required=False, default='',
                        metavar='kwargs', help='kwargs in key=value format')
    parser.add_argument('--strat', required=False, default='',
                        metavar='kwargs', help='kwargs in key=value format')
    parser.add_argument('--plot', required=False, default='',
                        nargs='?', const='{}',
                        metavar='kwargs', help='kwargs in key=value format')
    pgroup = parser.add_mutually_exclusive_group(required=False)
    pgroup.add_argument('--pandascal', required=False, action='store',
                        default='', help='Name of trading calendar to use')
    pgroup.add_argument('--owncal', required=False, action='store_true',
                        help='Apply custom NYSE 2016 calendar')
    parser.add_argument('--timeframe', required=False, action='store',
                        default='Days', choices=['Days'],
                        help='Timeframe to resample to')
    return parser.parse_args(pargs)
if __name__ == '__main__':
    runstrat()

自动化回测

原文:www.backtrader.com/docu/automated-bt-run/automated-bt-run/

到目前为止,所有的backtrader示例和工作样本都是从头开始创建一个主要的Python模块,该模块加载数据、策略、观察器,并准备好现金和佣金方案。

算法交易的一个目标之一是交易的自动化,鉴于 backtrader 是一个用于检查交易算法的回测平台(因此是一个算法交易平台),自动化使用 backtrader 是一个明显的目标。

当安装backtrader时,它提供了两个脚本/可执行文件形式的入口点,可以自动化大多数任务:

  • bt-run-py 一个使用下一项中的代码库的脚本

  • btrun(可执行文件)
    打包过程中由setuptools创建的入口点。在理论上,在 Windows 下不会出现“路径/文件未找到”的错误。

下面的描述同样适用于这两个工具。

btrun 允许最终用户:

  • 说出必须加载的数据源
  • 设置加载数据的格式
  • 指定数据的日期范围
  • 向 Cerebro 传递参数
  • 禁用标准观察器
  • 这是在“Cerebro”参数实现之前的一个原始额外开关。因此,如果向 cerebro 传递关于标准观察器的参数,这将被忽略(参数stdstats到 Cerebro)
  • 加载一个或多个观察器(例如:DrawDown)从内置的或来自 Python 模块
  • 为经纪人设置现金和佣金方案参数(佣金、保证金、倍数)
  • 启用绘图,控制图表的数量和数据呈现的样式
  • 向系统添加一个带参数的写入器

最后应该是核心能力是什么:

  • 加载一个策略(内置的或来自 Python 模块)
  • 向加载的策略传递参数

请参阅下面关于脚本的使用

应用用户定义的策略

让我们考虑以下策略:

  • 简单加载一个 SimpleMovingAverage(默认周期为 15)
  • 打印输出
  • 存储在一个名为mymod.py的文件中
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import backtrader as bt
import backtrader.indicators as btind
class MyTest(bt.Strategy):
    params = (('period', 15),)
    def log(self, txt, dt=None):
  ''' Logging function fot this strategy'''
        dt = dt or self.data.datetime[0]
        if isinstance(dt, float):
            dt = bt.num2date(dt)
        print('%s, %s' % (dt.isoformat(), txt))
    def __init__(self):
        sma = btind.SMA(period=self.p.period)
    def next(self):
        ltxt = '%d, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f'
        self.log(ltxt %
                 (len(self),
                  self.data.open[0], self.data.high[0],
                  self.data.low[0], self.data.close[0],
                  self.data.volume[0], self.data.openinterest[0]))

使用通常的测试样本执行策略很容易:

btrun --csvformat btcsv \
      --data ../../datas/2006-day-001.txt \
      --strategy mymod.py

图表输出

控制台输出:

2006-01-20T23:59:59+00:00, 15, 3593.16, 3612.37, 3550.80, 3550.80, 0.00, 0.00
2006-01-23T23:59:59+00:00, 16, 3550.24, 3550.24, 3515.07, 3544.31, 0.00, 0.00
2006-01-24T23:59:59+00:00, 17, 3544.78, 3553.16, 3526.37, 3532.68, 0.00, 0.00
2006-01-25T23:59:59+00:00, 18, 3532.72, 3578.00, 3532.72, 3578.00, 0.00, 0.00
...
...
2006-12-22T23:59:59+00:00, 252, 4109.86, 4109.86, 4072.62, 4073.50, 0.00, 0.00
2006-12-27T23:59:59+00:00, 253, 4079.70, 4134.86, 4079.70, 4134.86, 0.00, 0.00
2006-12-28T23:59:59+00:00, 254, 4137.44, 4142.06, 4125.14, 4130.66, 0.00, 0.00
2006-12-29T23:59:59+00:00, 255, 4130.12, 4142.01, 4119.94, 4119.94, 0.00, 0.00

相同的策略,但:

  • 将参数period设置为 50

命令行:

btrun --csvformat btcsv \
      --data ../../datas/2006-day-001.txt \
      --plot \
      --strategy mymod.py:period=50

图表输出。

注意

如果没有给出.py扩展名,bt-run 将会添加它。

使用内置策略

backtrader 将逐渐包含样例(教科书)策略。与 bt-run.py 脚本一起,一个标准的简单移动平均线交叉策略已经包含在内。这个名称:

  • SMA_CrossOver
  • 参数
  • fast(默认 10)快速移动平均线的周期
  • slow(默认 30)慢速移动平均线的周期

如果快速移动平均线上穿过快速移动平均线,则策略买入,如果它以前已经买入,则在快速移动平均线下穿过慢速移动平均线时卖出。

代码

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import backtrader as bt
import backtrader.indicators as btind
class SMA_CrossOver(bt.Strategy):
    params = (('fast', 10), ('slow', 30))
    def __init__(self):
        sma_fast = btind.SMA(period=self.p.fast)
        sma_slow = btind.SMA(period=self.p.slow)
        self.buysig = btind.CrossOver(sma_fast, sma_slow)
    def next(self):
        if self.position.size:
            if self.buysig < 0:
                self.sell()
        elif self.buysig > 0:
            self.buy()

标准执行:

btrun --csvformat btcsv \
      --data ../../datas/2006-day-001.txt \
      --plot \
      --strategy :SMA_CrossOver

请注意 :。加载策略的标准表示法(见下文)是:

  • module:stragegy:kwargs

使用以下规则:

  • 如果存在模块和/或策略,则将使用该策略
  • 如果模块存在但未指定策略,则将返回模块中找到的第 1 个策略
  • 如果没有指定模块,则假定“strategy”是指 backtrader 包中的策略
  • 如果存在模块和/或策略,并且存在 kwargs,则将其传递给相应的策略

注意

相同的表示法和规则适用于 --observer--analyzer--indicator 选项

显然,适用于相应的对象类型

输出

最后一个例子,添加佣金方案,现金和更改参数:

btrun --csvformat btcsv \
      --data ../../datas/2006-day-001.txt \
      --plot \
      --cash 20000 \
      --commission 2.0 \
      --mult 10 \
      --margin 2000 \
      --strategy :SMA_CrossOver:fast=5,slow=20

输出

我们已经对策略进行了回测:

  • 更改移动平均周期
  • 设置新的起始现金
  • 为类似期货的工具设置佣金方案
    请注意每个柱状图中现金的连续变化,因为现金会根据类似期货的工具的每日变化进行调整


BackTrader 中文文档(十三)(3)https://developer.aliyun.com/article/1505346

相关文章
|
9月前
|
算法 数据可视化 程序员
BackTrader 中文文档(十四)(1)
BackTrader 中文文档(十四)
94 0
BackTrader 中文文档(十四)(1)
|
9月前
|
机器学习/深度学习 人工智能 测试技术
BackTrader 中文文档(十四)(3)
BackTrader 中文文档(十四)
82 0
BackTrader 中文文档(十四)(3)
|
9月前
|
存储
BackTrader 中文文档(十四)(4)
BackTrader 中文文档(十四)
91 0
BackTrader 中文文档(十四)(4)
|
9月前
|
程序员 Python
BackTrader 中文文档(十三)(4)
BackTrader 中文文档(十三)
68 0
|
9月前
BackTrader 中文文档(十三)(1)
BackTrader 中文文档(十三)
63 0
|
9月前
|
Web App开发 Shell Python
BackTrader 中文文档(十三)(3)
BackTrader 中文文档(十三)
69 0
|
9月前
|
存储 编解码 算法
BackTrader 中文文档(十一)(3)
BackTrader 中文文档(十一)
143 0
|
9月前
|
Oracle 关系型数据库 测试技术
BackTrader 中文文档(十一)(1)
BackTrader 中文文档(十一)
62 0
|
9月前
|
存储 API 索引
BackTrader 中文文档(十一)(2)
BackTrader 中文文档(十一)
157 0
|
9月前
|
存储 测试技术 API
BackTrader 中文文档(十一)(4)
BackTrader 中文文档(十一)
146 0

热门文章

最新文章